From 6a26f35ebc1630f7a6bf0a13c9252b059953ee75 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 5 Jun 2013 16:04:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=87=8F=E5=B0=91PreparedStatementProxyImpl?= =?UTF-8?q?=E7=9A=84=E5=86=85=E5=AD=98=E5=8D=A0=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../druid/filter/logging/LogFilter.java | 32 +- .../alibaba/druid/filter/stat/StatFilter.java | 2062 +++++++++-------- .../jdbc/PreparedStatementProxyImpl.java | 1207 +++++----- .../druid/proxy/jdbc/StatementProxy.java | 115 +- .../druid/proxy/jdbc/StatementProxyImpl.java | 1148 ++++----- .../pool/PreparedStatementProxyImplTest.java | 42 +- 6 files changed, 2324 insertions(+), 2282 deletions(-) diff --git a/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java b/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java index 1412851959..745d1c334e 100644 --- a/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java +++ b/src/main/java/com/alibaba/druid/filter/logging/LogFilter.java @@ -21,7 +21,6 @@ import java.sql.Savepoint; import java.sql.Types; import java.util.ArrayList; import java.util.List; -import java.util.Map; import com.alibaba.druid.filter.FilterChain; import com.alibaba.druid.filter.FilterEventAdapter; @@ -507,15 +506,16 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM return; } - Map parameterMap = statement.getParameters(); - if (parameterMap == null || parameterMap.size() == 0) { + int parametersSize = statement.getParametersSize(); + if (parametersSize == 0) { statementLog("{conn-" + statement.getConnectionProxy().getId() + ", " + stmtId(statement) + "} executed. " + sql); return; } - List parameters = new ArrayList(parameterMap.size()); - for (JdbcParameter jdbcParam : parameterMap.values()) { + List parameters = new ArrayList(parametersSize); + for (int i = 0; i < parametersSize; ++i) { + JdbcParameter jdbcParam = statement.getParameter(i); parameters.add(jdbcParam.getValue()); } @@ -737,11 +737,16 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM buf.append(stmtId(statement)); buf.append("}"); buf.append(" Parameters : ["); - int parameterIndex = 0; - for (JdbcParameter parameter : statement.getParameters().values()) { - if (parameterIndex != 0) { + + for (int i = 0, parametersSize = statement.getParametersSize(); i < parametersSize; ++i) { + JdbcParameter parameter = statement.getParameter(i); + if (i != 0) { buf.append(", "); } + if (parameter == null) { + continue; + } + int sqlType = parameter.getSqlType(); Object value = parameter.getValue(); switch (sqlType) { @@ -752,7 +757,6 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM buf.append(String.valueOf(value)); break; } - parameterIndex++; } buf.append("]"); statementLog(buf.toString()); @@ -765,14 +769,16 @@ public abstract class LogFilter extends FilterEventAdapter implements LogFilterM buf.append(stmtId(statement)); buf.append("}"); buf.append(" Types : ["); - int parameterIndex = 0; - for (JdbcParameter parameter : statement.getParameters().values()) { - if (parameterIndex != 0) { + for (int i = 0, parametersSize = statement.getParametersSize(); i < parametersSize; ++i) { + JdbcParameter parameter = statement.getParameter(i); + if (i != 0) { buf.append(", "); } + if (parameter == null) { + continue; + } int sqlType = parameter.getSqlType(); buf.append(JdbcUtils.getTypeName(sqlType)); - parameterIndex++; } buf.append("]"); statementLog(buf.toString()); 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 ef41aed979..6dc6652e8a 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -1,1030 +1,1032 @@ -/* - * 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.filter.stat; - -import java.io.InputStream; -import java.io.Reader; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.NClob; -import java.sql.SQLException; -import java.sql.Savepoint; -import java.util.Date; -import java.util.Properties; - -import com.alibaba.druid.filter.Filter; -import com.alibaba.druid.filter.FilterChain; -import com.alibaba.druid.filter.FilterEventAdapter; -import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.pool.DruidPooledConnection; -import com.alibaba.druid.proxy.jdbc.CallableStatementProxy; -import com.alibaba.druid.proxy.jdbc.ClobProxy; -import com.alibaba.druid.proxy.jdbc.ConnectionProxy; -import com.alibaba.druid.proxy.jdbc.DataSourceProxy; -import com.alibaba.druid.proxy.jdbc.JdbcParameter; -import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy; -import com.alibaba.druid.proxy.jdbc.ResultSetProxy; -import com.alibaba.druid.proxy.jdbc.StatementExecuteType; -import com.alibaba.druid.proxy.jdbc.StatementProxy; -import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; -import com.alibaba.druid.stat.JdbcConnectionStat; -import com.alibaba.druid.stat.JdbcDataSourceStat; -import com.alibaba.druid.stat.JdbcResultSetStat; -import com.alibaba.druid.stat.JdbcSqlStat; -import com.alibaba.druid.stat.JdbcStatContext; -import com.alibaba.druid.stat.JdbcStatManager; -import com.alibaba.druid.stat.JdbcStatementStat; -import com.alibaba.druid.support.json.JSONWriter; -import com.alibaba.druid.support.logging.Log; -import com.alibaba.druid.support.logging.LogFactory; -import com.alibaba.druid.support.profile.Profiler; - -/** - * @author wenshao - */ -public class StatFilter extends FilterEventAdapter implements StatFilterMBean { - - private final static Log LOG = LogFactory.getLog(StatFilter.class); - - private static final String SYS_PROP_LOG_SLOW_SQL = "druid.stat.logSlowSql"; - private static final String SYS_PROP_SLOW_SQL_MILLIS = "druid.stat.slowSqlMillis"; - private static final String SYS_PROP_MERGE_SQL = "druid.stat.mergeSql"; - - 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_UPDATE_COUNT = "stat.updteCount"; - public final static String ATTR_TRANSACTION = "stat.tx"; - public final static String ATTR_RESULTSET_CLOSED = "stat.rs.closed"; - - // protected JdbcDataSourceStat dataSourceStat; - - @Deprecated - protected final JdbcStatementStat statementStat = JdbcStatManager.getInstance().getStatementStat(); - - @Deprecated - protected final JdbcResultSetStat resultSetStat = JdbcStatManager.getInstance().getResultSetStat(); - - private boolean connectionStackTraceEnable = false; - - // 3 seconds is slow sql - protected long slowSqlMillis = 3 * 1000; - - protected boolean logSlowSql = false; - - private String dbType; - - private boolean mergeSql = false; - - public StatFilter(){ - } - - public String getDbType() { - return dbType; - } - - public void setDbType(String dbType) { - this.dbType = dbType; - } - - public long getSlowSqlMillis() { - return slowSqlMillis; - } - - public void setSlowSqlMillis(long slowSqlMillis) { - this.slowSqlMillis = slowSqlMillis; - } - - public boolean isLogSlowSql() { - return logSlowSql; - } - - public void setLogSlowSql(boolean logSlowSql) { - this.logSlowSql = logSlowSql; - } - - public boolean isConnectionStackTraceEnable() { - return connectionStackTraceEnable; - } - - public void setConnectionStackTraceEnable(boolean connectionStackTraceEnable) { - this.connectionStackTraceEnable = connectionStackTraceEnable; - } - - public boolean isMergeSql() { - return mergeSql; - } - - public void setMergeSql(boolean mergeSql) { - this.mergeSql = mergeSql; - } - - @Deprecated - public String mergeSql(String sql) { - return this.mergeSql(sql, dbType); - } - - public String mergeSql(String sql, String dbType) { - if (!mergeSql) { - return sql; - } - - try { - sql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); - } catch (Exception e) { - LOG.error("merge sql error, dbType " + dbType + ", sql : \n" + sql, e); - } - - return sql; - } - - @Override - public synchronized void init(DataSourceProxy dataSource) { - if (this.dbType == null || this.dbType.trim().length() == 0) { - this.dbType = dataSource.getDbType(); - } - - configFromProperties(dataSource.getConnectProperties()); - configFromProperties(System.getProperties()); - } - - public void configFromProperties(Properties properties) { - if (properties == null) { - return; - } - - { - String property = properties.getProperty(SYS_PROP_MERGE_SQL); - if ("true".equals(property)) { - this.mergeSql = true; - } else if ("false".equals(property)) { - this.mergeSql = false; - } - } - - { - String property = properties.getProperty(SYS_PROP_SLOW_SQL_MILLIS); - if (property != null && property.trim().length() > 0) { - property = property.trim(); - try { - this.slowSqlMillis = Long.parseLong(property); - } catch (Exception e) { - LOG.error("property 'druid.stat.slowSqlMillis' format error"); - } - } - } - - { - String property = properties.getProperty(SYS_PROP_LOG_SLOW_SQL); - if ("true".equals(property)) { - this.logSlowSql = true; - } else if ("false".equals(property)) { - this.logSlowSql = false; - } - } - } - - public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException { - ConnectionProxy connection = null; - { - long startNano = System.nanoTime(); - long startTime = System.currentTimeMillis(); - - long nanoSpan; - long nowTime = System.currentTimeMillis(); - - JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); - dataSourceStat.getConnectionStat().beforeConnect(); - try { - connection = chain.connection_connect(info); - nanoSpan = System.nanoTime() - startNano; - } catch (SQLException ex) { - dataSourceStat.getConnectionStat().connectError(ex); - throw ex; - } - dataSourceStat.getConnectionStat().afterConnected(nanoSpan); - - 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()); - - dataSourceStat.getConnectionStat().setActiveCount(dataSourceStat.getConnections().size()); - } - } - return connection; - } - - @Override - public void connection_close(FilterChain chain, ConnectionProxy connection) throws SQLException { - if (connection.getCloseCount() == 0) { - long nowNano = System.nanoTime(); - - JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); - dataSourceStat.getConnectionStat().incrementConnectionCloseCount(); - - JdbcConnectionStat.Entry connectionInfo = getConnectionInfo(connection); - - long aliveNanoSpan = nowNano - connectionInfo.getEstablishNano(); - - JdbcConnectionStat.Entry existsConnection = dataSourceStat.getConnections().remove(connection.getId()); - if (existsConnection != null) { - dataSourceStat.getConnectionStat().afterClose(aliveNanoSpan); - } - } - - chain.connection_close(connection); - // duplicate close, C3P0等连接池,在某些情况下会关闭连接多次。 - } - - @Override - public void connection_commit(FilterChain chain, ConnectionProxy connection) throws SQLException { - chain.connection_commit(connection); - - JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); - dataSourceStat.getConnectionStat().incrementConnectionCommitCount(); - } - - @Override - public void connection_rollback(FilterChain chain, ConnectionProxy connection) throws SQLException { - chain.connection_rollback(connection); - - JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); - dataSourceStat.getConnectionStat().incrementConnectionRollbackCount(); - dataSourceStat.getConnectionStat().incrementConnectionRollbackCount(); - } - - @Override - public void connection_rollback(FilterChain chain, ConnectionProxy connection, Savepoint savepoint) - throws SQLException { - chain.connection_rollback(connection, savepoint); - - JdbcDataSourceStat dataSourceStat = connection.getDirectDataSource().getDataSourceStat(); - dataSourceStat.getConnectionStat().incrementConnectionRollbackCount(); - } - - @Override - public void statementCreateAfter(StatementProxy statement) { - JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); - dataSourceStat.getStatementStat().incrementCreateCounter(); - - super.statementCreateAfter(statement); - } - - @Override - public void statementPrepareCallAfter(CallableStatementProxy statement) { - JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); - dataSourceStat.getStatementStat().incrementPrepareCallCount(); - - JdbcSqlStat sqlStat = createSqlStat(statement, statement.getSql()); - statement.setSqlStat(sqlStat); - } - - @Override - public void statementPrepareAfter(PreparedStatementProxy statement) { - JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); - dataSourceStat.getStatementStat().incrementPrepareCounter(); - JdbcSqlStat sqlStat = createSqlStat(statement, statement.getSql()); - statement.setSqlStat(sqlStat); - } - - @Override - public void statement_close(FilterChain chain, StatementProxy statement) throws SQLException { - chain.statement_close(statement); - - JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); - dataSourceStat.getStatementStat().incrementStatementCloseCounter(); - JdbcStatContext context = JdbcStatManager.getInstance().getStatContext(); - if (context != null) { - context.setName(null); - context.setFile(null); - context.setSql(null); - } - } - - @Override - protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) { - internalBeforeStatementExecute(statement, sql); - } - - @Override - protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) { - internalAfterStatementExecute(statement, false, updateCount); - } - - @Override - protected void statementExecuteQueryBefore(StatementProxy statement, String sql) { - internalBeforeStatementExecute(statement, sql); - } - - @Override - protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) { - internalAfterStatementExecute(statement, true); - } - - @Override - protected void statementExecuteBefore(StatementProxy statement, String sql) { - internalBeforeStatementExecute(statement, sql); - } - - @Override - protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) { - internalAfterStatementExecute(statement, firstResult); - } - - @Override - protected void statementExecuteBatchBefore(StatementProxy statement) { - final String sql = statement.getBatchSql(); - - final int batchSize = statement.getBatchSqlList().size(); - JdbcSqlStat sqlStat = statement.getSqlStat(); - if (sqlStat == null || sqlStat.isRemoved()) { - sqlStat = createSqlStat(statement, sql); - statement.setSqlStat(sqlStat); - } - - if (sqlStat != null) { - sqlStat.addExecuteBatchCount(batchSize); - } - - internalBeforeStatementExecute(statement, sql); - - } - - @Override - protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) { - internalAfterStatementExecute(statement, false, result); - - } - - private final void internalBeforeStatementExecute(StatementProxy statement, String sql) { - JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); - dataSourceStat.getStatementStat().beforeExecute(); - - final ConnectionProxy connection = statement.getConnectionProxy(); - final JdbcConnectionStat.Entry connectionCounter = getConnectionInfo(connection); - - statement.setLastExecuteStartNano(); - - connectionCounter.setLastSql(sql); - - if (connectionStackTraceEnable) { - connectionCounter.setLastStatementStatckTrace(new Exception()); - } - - // //////////SQL - - JdbcSqlStat sqlStat = statement.getSqlStat(); - if (sqlStat == null || sqlStat.isRemoved()) { - sqlStat = createSqlStat(statement, sql); - statement.setSqlStat(sqlStat); - } - - JdbcStatContext statContext = JdbcStatManager.getInstance().getStatContext(); - if (statContext != null) { - sqlStat.setName(statContext.getName()); - sqlStat.setFile(statContext.getFile()); - } - - boolean inTransaction = false; - try { - inTransaction = !statement.getConnectionProxy().getAutoCommit(); - } catch (SQLException e) { - LOG.error("getAutoCommit error", e); - } - - if (sqlStat != null) { - sqlStat.setExecuteLastStartTime(System.currentTimeMillis()); - sqlStat.incrementRunningCount(); - - if (inTransaction) { - sqlStat.incrementInTransactionCount(); - } - } - - StatFilterContext.getInstance().executeBefore(sql, inTransaction); - - Profiler.enter(sql, Profiler.PROFILE_TYPE_SQL); - } - - private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult, - int... updateCountArray) { - final long nowNano = System.nanoTime(); - final long nanos = nowNano - statement.getLastExecuteStartNano(); - - JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); - dataSourceStat.getStatementStat().afterExecute(nanos); - - final JdbcSqlStat sqlStat = statement.getSqlStat(); - - if (sqlStat != null) { - sqlStat.incrementExecuteSuccessCount(); - - sqlStat.decrementRunningCount(); - sqlStat.addExecuteTime(statement.getLastExecuteType(), firstResult, nanos); - statement.setLastExecuteTimeNano(nanos); - if ((!statement.isFirstResultSet()) && statement.getLastExecuteType() == StatementExecuteType.Execute) { - try { - int updateCount = statement.getUpdateCount(); - sqlStat.addUpdateCount(updateCount); - } catch (SQLException e) { - LOG.error("getUpdateCount error", e); - } - } else { - for (int updateCount : updateCountArray) { - sqlStat.addUpdateCount(updateCount); - sqlStat.addFetchRowCount(0); - StatFilterContext.getInstance().addUpdateCount(updateCount); - } - } - - long millis = nanos / (1000 * 1000); - if (millis >= slowSqlMillis) { - String slowParameters = buildSlowParameters(statement); - sqlStat.setLastSlowParameters(slowParameters); - - if (logSlowSql) { - LOG.error("slow sql " + millis + " millis. \n" + statement.getLastExecuteSql() + "\n" - + slowParameters); - } - } - } - - String sql = statement.getLastExecuteSql(); - StatFilterContext.getInstance().executeAfter(sql, nanos, null); - - Profiler.release(nanos); - } - - @Override - protected void statement_executeErrorAfter(StatementProxy statement, String sql, Throwable error) { - - ConnectionProxy connection = statement.getConnectionProxy(); - JdbcConnectionStat.Entry connectionCounter = getConnectionInfo(connection); - - long nanos = System.nanoTime() - statement.getLastExecuteStartNano(); - - JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); - dataSourceStat.getStatementStat().error(error); - dataSourceStat.getStatementStat().afterExecute(nanos); - - connectionCounter.error(error); - - // SQL - JdbcSqlStat sqlStat = statement.getSqlStat(); - - if (sqlStat != null) { - sqlStat.error(error); - sqlStat.addExecuteTime(statement.getLastExecuteType(), statement.isFirstResultSet(), nanos); - statement.setLastExecuteTimeNano(nanos); - } - - StatFilterContext.getInstance().executeAfter(sql, nanos, error); - Profiler.release(nanos); - } - - private String buildSlowParameters(StatementProxy statement) { - JSONWriter out = new JSONWriter(); - - out.writeArrayStart(); - int index = 0; - for (JdbcParameter parameter : statement.getParameters().values()) { - if (index != 0) { - out.writeComma(); - } - - Object value = parameter.getValue(); - if (value == null) { - out.writeNull(); - } else if (value instanceof String) { - String text = (String) value; - if (text.length() > 100) { - out.writeString(text.substring(0, 97) + "..."); - } else { - out.writeString(text); - } - } else if (value instanceof Number) { - out.writeObject(value); - } else if (value instanceof java.util.Date) { - out.writeObject(value); - } else if (value instanceof Boolean) { - out.writeObject(value); - } else if (value instanceof InputStream) { - out.writeString(""); - } else if (value instanceof NClob) { - out.writeString(""); - } else if (value instanceof Clob) { - out.writeString(""); - } else if (value instanceof Blob) { - out.writeString(""); - } else { - out.writeString('<' + value.getClass().getName() + '>'); - } - index++; - } - out.writeArrayEnd(); - - return out.toString(); - } - - @Override - protected void resultSetOpenAfter(ResultSetProxy resultSet) { - JdbcDataSourceStat dataSourceStat = resultSet.getStatementProxy().getConnectionProxy().getDirectDataSource().getDataSourceStat(); - dataSourceStat.getResultSetStat().beforeOpen(); - - resultSet.setConstructNano(); - - StatFilterContext.getInstance().resultSet_open(); - } - - @Override - public void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException { - - long nanos = System.nanoTime() - resultSet.getConstructNano(); - - int fetchRowCount = resultSet.getFetchRowCount(); - - JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); - dataSourceStat.getResultSetStat().afterClose(nanos); - dataSourceStat.getResultSetStat().addFetchRowCount(fetchRowCount); - dataSourceStat.getResultSetStat().incrementCloseCounter(); - - StatFilterContext.getInstance().addFetchRowCount(fetchRowCount); - - String sql = resultSet.getSql(); - if (sql != null) { - JdbcSqlStat sqlStat = resultSet.getSqlStat(); - if (sqlStat != null && resultSet.getCloseCount() == 0) { - sqlStat.addFetchRowCount(fetchRowCount); - long stmtExecuteNano = resultSet.getStatementProxy().getLastExecuteTimeNano(); - sqlStat.addResultSetHoldTimeNano(stmtExecuteNano, nanos); - if (resultSet.getReadStringLength() > 0) { - sqlStat.addStringReadLength(resultSet.getReadStringLength()); - } - if (resultSet.getReadBytesLength() > 0) { - sqlStat.addReadBytesLength(resultSet.getReadBytesLength()); - } - if (resultSet.getOpenInputStreamCount() > 0) { - sqlStat.addInputStreamOpenCount(resultSet.getOpenInputStreamCount()); - } - if (resultSet.getOpenReaderCount() > 0) { - sqlStat.addReaderOpenCount(resultSet.getOpenReaderCount()); - } - } - } - - chain.resultSet_close(resultSet); - - StatFilterContext.getInstance().resultSet_close(nanos); - } - - public JdbcConnectionStat.Entry getConnectionInfo(ConnectionProxy connection) { - JdbcConnectionStat.Entry counter = (JdbcConnectionStat.Entry) connection.getAttributes().get(ATTR_NAME_CONNECTION_STAT); - - if (counter == null) { - String dataSourceName = connection.getDirectDataSource().getName(); - connection.getAttributes().put(ATTR_NAME_CONNECTION_STAT, - new JdbcConnectionStat.Entry(dataSourceName, connection.getId())); - counter = (JdbcConnectionStat.Entry) connection.getAttributes().get(ATTR_NAME_CONNECTION_STAT); - } - - return counter; - } - - public JdbcSqlStat createSqlStat(StatementProxy statement, String sql) { - DataSourceProxy dataSource = statement.getConnectionProxy().getDirectDataSource(); - JdbcDataSourceStat dataSourceStat = dataSource.getDataSourceStat(); - - JdbcStatContext context = JdbcStatManager.getInstance().getStatContext(); - String contextSql = context != null ? context.getSql() : null; - if (contextSql != null && contextSql.length() > 0) { - return dataSourceStat.createSqlStat(contextSql); - } else { - String dbType = this.dbType; - - if (dbType == null) { - dbType = dataSource.getDbType(); - } - - sql = mergeSql(sql, dbType); - return dataSourceStat.createSqlStat(sql); - } - } - - public static StatFilter getStatFilter(DataSourceProxy dataSource) { - for (Filter filter : dataSource.getProxyFilters()) { - if (filter instanceof StatFilter) { - return (StatFilter) filter; - } - } - - return null; - } - - @Override - public void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection conn) throws SQLException { - chain.dataSource_recycle(conn); - - long nanos = System.nanoTime() - conn.getConnectedTimeNano(); - - long millis = nanos / (1000L * 1000L); - - JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); - dataSourceStat.getConnectionHoldHistogram().record(millis); - - StatFilterContext.getInstance().pool_connection_close(nanos); - } - - @Override - public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource, - long maxWaitMillis) throws SQLException { - DruidPooledConnection conn = chain.dataSource_connect(dataSource, maxWaitMillis); - - if (conn != null) { - conn.setConnectedTimeNano(); - - StatFilterContext.getInstance().pool_connection_open(); - } - - return conn; - } - - @Override - public Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException { - Clob clob = chain.resultSet_getClob(resultSet, columnIndex); - - if (clob != null) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), resultSet, (ClobProxy) clob); - } - - return clob; - } - - @Override - public Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException { - Clob clob = chain.resultSet_getClob(resultSet, columnLabel); - - if (clob != null) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), resultSet, (ClobProxy) clob); - } - - return clob; - } - - @Override - public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, int parameterIndex) - throws SQLException { - Blob blob = chain.callableStatement_getBlob(statement, parameterIndex); - - if (blob != null) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, blob); - } - - return blob; - } - - @Override - public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, String parameterName) - throws SQLException { - Blob blob = chain.callableStatement_getBlob(statement, parameterName); - - if (blob != null) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, blob); - } - - return blob; - } - - @Override - public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { - Blob blob = chain.resultSet_getBlob(result, columnIndex); - - if (blob != null) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, blob); - } - - return blob; - } - - @Override - public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { - Blob blob = chain.resultSet_getBlob(result, columnLabel); - - if (blob != null) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, blob); - } - - return blob; - } - - @Override - public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, int parameterIndex) - throws SQLException { - Clob clob = chain.callableStatement_getClob(statement, parameterIndex); - - if (clob != null) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) clob); - } - - return clob; - } - - @Override - public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, String parameterName) - throws SQLException { - Clob clob = chain.callableStatement_getClob(statement, parameterName); - - if (clob != null) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) clob); - } - - return clob; - } - - @Override - public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { - Object obj = chain.resultSet_getObject(result, columnIndex); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); - } else if (obj instanceof String) { - result.addReadStringLength(((String) obj).length()); - } - - return obj; - } - - @Override - public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex, - java.util.Map> map) throws SQLException { - Object obj = chain.resultSet_getObject(result, columnIndex, map); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); - } else if (obj instanceof String) { - result.addReadStringLength(((String) obj).length()); - } - - return obj; - } - - @Override - public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { - Object obj = chain.resultSet_getObject(result, columnLabel); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); - } else if (obj instanceof String) { - result.addReadStringLength(((String) obj).length()); - } - - return obj; - } - - @Override - public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel, - java.util.Map> map) throws SQLException { - Object obj = chain.resultSet_getObject(result, columnLabel, map); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); - } else if (obj instanceof String) { - result.addReadStringLength(((String) obj).length()); - } - - return obj; - } - - @Override - public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex) - throws SQLException { - Object obj = chain.callableStatement_getObject(statement, parameterIndex); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); - } - - return obj; - } - - @Override - public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex, - java.util.Map> map) throws SQLException { - Object obj = chain.callableStatement_getObject(statement, parameterIndex, map); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); - } - - return obj; - } - - @Override - public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName) - throws SQLException { - Object obj = chain.callableStatement_getObject(statement, parameterName); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); - } - - return obj; - } - - @Override - public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, - String parameterName, java.util.Map> map) - throws SQLException { - Object obj = chain.callableStatement_getObject(statement, parameterName, map); - - if (obj instanceof Clob) { - clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); - } else if (obj instanceof Blob) { - blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); - } - - return obj; - } - - private void blobOpenAfter(JdbcDataSourceStat dataSourceStat, ResultSetProxy rs, Blob blob) { - blobOpenAfter(dataSourceStat, rs.getStatementProxy(), blob); - } - - private void clobOpenAfter(JdbcDataSourceStat dataSourceStat, ResultSetProxy rs, ClobProxy clob) { - clobOpenAfter(dataSourceStat, rs.getStatementProxy(), clob); - } - - private void blobOpenAfter(JdbcDataSourceStat dataSourceStat, StatementProxy stmt, Blob blob) { - dataSourceStat.incrementBlobOpenCount(); - - if (stmt != null) { - JdbcSqlStat sqlStat = stmt.getSqlStat(); - if (sqlStat != null) { - sqlStat.incrementBlobOpenCount(); - } - } - - StatFilterContext.getInstance().blob_open(); - } - - private void clobOpenAfter(JdbcDataSourceStat dataSourceStat, StatementProxy stmt, ClobProxy clob) { - dataSourceStat.incrementClobOpenCount(); - - if (stmt != null) { - JdbcSqlStat sqlStat = stmt.getSqlStat(); - if (sqlStat != null) { - sqlStat.incrementClobOpenCount(); - } - } - - StatFilterContext.getInstance().clob_open(); - } - - @Override - public String resultSet_getString(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { - String value = chain.resultSet_getString(result, columnIndex); - - if (value != null) { - result.addReadStringLength(value.length()); - } - - return value; - } - - @Override - public String resultSet_getString(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { - String value = chain.resultSet_getString(result, columnLabel); - - if (value != null) { - result.addReadStringLength(value.length()); - } - - return value; - } - - @Override - public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { - byte[] value = chain.resultSet_getBytes(result, columnIndex); - - if (value != null) { - result.addReadBytesLength(value.length); - } - - return value; - } - - @Override - public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { - byte[] value = chain.resultSet_getBytes(result, columnLabel); - - if (value != null) { - result.addReadBytesLength(value.length); - } - - return value; - } - - @Override - public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex) - throws SQLException { - InputStream input = chain.resultSet_getBinaryStream(result, columnIndex); - - if (input != null) { - result.incrementOpenInputStreamCount(); - } - - return input; - } - - @Override - public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel) - throws SQLException { - InputStream input = chain.resultSet_getBinaryStream(result, columnLabel); - - if (input != null) { - result.incrementOpenInputStreamCount(); - } - - return input; - } - - @Override - public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex) - throws SQLException { - InputStream input = chain.resultSet_getAsciiStream(result, columnIndex); - - if (input != null) { - result.incrementOpenInputStreamCount(); - } - - return input; - } - - @Override - public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel) - throws SQLException { - InputStream input = chain.resultSet_getAsciiStream(result, columnLabel); - - if (input != null) { - result.incrementOpenInputStreamCount(); - } - - return input; - } - - @Override - public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex) - throws SQLException { - Reader reader = chain.resultSet_getCharacterStream(result, columnIndex); - - if (reader != null) { - result.incrementOpenReaderCount(); - } - - return reader; - } - - @Override - public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel) - throws SQLException { - Reader reader = chain.resultSet_getCharacterStream(result, columnLabel); - - if (reader != null) { - result.incrementOpenReaderCount(); - } - - return reader; - } -} +/* + * 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.filter.stat; + +import java.io.InputStream; +import java.io.Reader; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.NClob; +import java.sql.SQLException; +import java.sql.Savepoint; +import java.util.Date; +import java.util.Properties; + +import com.alibaba.druid.filter.Filter; +import com.alibaba.druid.filter.FilterChain; +import com.alibaba.druid.filter.FilterEventAdapter; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.pool.DruidPooledConnection; +import com.alibaba.druid.proxy.jdbc.CallableStatementProxy; +import com.alibaba.druid.proxy.jdbc.ClobProxy; +import com.alibaba.druid.proxy.jdbc.ConnectionProxy; +import com.alibaba.druid.proxy.jdbc.DataSourceProxy; +import com.alibaba.druid.proxy.jdbc.JdbcParameter; +import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy; +import com.alibaba.druid.proxy.jdbc.ResultSetProxy; +import com.alibaba.druid.proxy.jdbc.StatementExecuteType; +import com.alibaba.druid.proxy.jdbc.StatementProxy; +import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils; +import com.alibaba.druid.stat.JdbcConnectionStat; +import com.alibaba.druid.stat.JdbcDataSourceStat; +import com.alibaba.druid.stat.JdbcResultSetStat; +import com.alibaba.druid.stat.JdbcSqlStat; +import com.alibaba.druid.stat.JdbcStatContext; +import com.alibaba.druid.stat.JdbcStatManager; +import com.alibaba.druid.stat.JdbcStatementStat; +import com.alibaba.druid.support.json.JSONWriter; +import com.alibaba.druid.support.logging.Log; +import com.alibaba.druid.support.logging.LogFactory; +import com.alibaba.druid.support.profile.Profiler; + +/** + * @author wenshao + */ +public class StatFilter extends FilterEventAdapter implements StatFilterMBean { + + private final static Log LOG = LogFactory.getLog(StatFilter.class); + + private static final String SYS_PROP_LOG_SLOW_SQL = "druid.stat.logSlowSql"; + private static final String SYS_PROP_SLOW_SQL_MILLIS = "druid.stat.slowSqlMillis"; + private static final String SYS_PROP_MERGE_SQL = "druid.stat.mergeSql"; + + 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_UPDATE_COUNT = "stat.updteCount"; + public final static String ATTR_TRANSACTION = "stat.tx"; + public final static String ATTR_RESULTSET_CLOSED = "stat.rs.closed"; + + // protected JdbcDataSourceStat dataSourceStat; + + @Deprecated + protected final JdbcStatementStat statementStat = JdbcStatManager.getInstance().getStatementStat(); + + @Deprecated + protected final JdbcResultSetStat resultSetStat = JdbcStatManager.getInstance().getResultSetStat(); + + private boolean connectionStackTraceEnable = false; + + // 3 seconds is slow sql + protected long slowSqlMillis = 3 * 1000; + + protected boolean logSlowSql = false; + + private String dbType; + + private boolean mergeSql = false; + + public StatFilter(){ + } + + public String getDbType() { + return dbType; + } + + public void setDbType(String dbType) { + this.dbType = dbType; + } + + public long getSlowSqlMillis() { + return slowSqlMillis; + } + + public void setSlowSqlMillis(long slowSqlMillis) { + this.slowSqlMillis = slowSqlMillis; + } + + public boolean isLogSlowSql() { + return logSlowSql; + } + + public void setLogSlowSql(boolean logSlowSql) { + this.logSlowSql = logSlowSql; + } + + public boolean isConnectionStackTraceEnable() { + return connectionStackTraceEnable; + } + + public void setConnectionStackTraceEnable(boolean connectionStackTraceEnable) { + this.connectionStackTraceEnable = connectionStackTraceEnable; + } + + public boolean isMergeSql() { + return mergeSql; + } + + public void setMergeSql(boolean mergeSql) { + this.mergeSql = mergeSql; + } + + @Deprecated + public String mergeSql(String sql) { + return this.mergeSql(sql, dbType); + } + + public String mergeSql(String sql, String dbType) { + if (!mergeSql) { + return sql; + } + + try { + sql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); + } catch (Exception e) { + LOG.error("merge sql error, dbType " + dbType + ", sql : \n" + sql, e); + } + + return sql; + } + + @Override + public synchronized void init(DataSourceProxy dataSource) { + if (this.dbType == null || this.dbType.trim().length() == 0) { + this.dbType = dataSource.getDbType(); + } + + configFromProperties(dataSource.getConnectProperties()); + configFromProperties(System.getProperties()); + } + + public void configFromProperties(Properties properties) { + if (properties == null) { + return; + } + + { + String property = properties.getProperty(SYS_PROP_MERGE_SQL); + if ("true".equals(property)) { + this.mergeSql = true; + } else if ("false".equals(property)) { + this.mergeSql = false; + } + } + + { + String property = properties.getProperty(SYS_PROP_SLOW_SQL_MILLIS); + if (property != null && property.trim().length() > 0) { + property = property.trim(); + try { + this.slowSqlMillis = Long.parseLong(property); + } catch (Exception e) { + LOG.error("property 'druid.stat.slowSqlMillis' format error"); + } + } + } + + { + String property = properties.getProperty(SYS_PROP_LOG_SLOW_SQL); + if ("true".equals(property)) { + this.logSlowSql = true; + } else if ("false".equals(property)) { + this.logSlowSql = false; + } + } + } + + public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException { + ConnectionProxy connection = null; + { + long startNano = System.nanoTime(); + long startTime = System.currentTimeMillis(); + + long nanoSpan; + long nowTime = System.currentTimeMillis(); + + JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); + dataSourceStat.getConnectionStat().beforeConnect(); + try { + connection = chain.connection_connect(info); + nanoSpan = System.nanoTime() - startNano; + } catch (SQLException ex) { + dataSourceStat.getConnectionStat().connectError(ex); + throw ex; + } + dataSourceStat.getConnectionStat().afterConnected(nanoSpan); + + 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()); + + dataSourceStat.getConnectionStat().setActiveCount(dataSourceStat.getConnections().size()); + } + } + return connection; + } + + @Override + public void connection_close(FilterChain chain, ConnectionProxy connection) throws SQLException { + if (connection.getCloseCount() == 0) { + long nowNano = System.nanoTime(); + + JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); + dataSourceStat.getConnectionStat().incrementConnectionCloseCount(); + + JdbcConnectionStat.Entry connectionInfo = getConnectionInfo(connection); + + long aliveNanoSpan = nowNano - connectionInfo.getEstablishNano(); + + JdbcConnectionStat.Entry existsConnection = dataSourceStat.getConnections().remove(connection.getId()); + if (existsConnection != null) { + dataSourceStat.getConnectionStat().afterClose(aliveNanoSpan); + } + } + + chain.connection_close(connection); + // duplicate close, C3P0等连接池,在某些情况下会关闭连接多次。 + } + + @Override + public void connection_commit(FilterChain chain, ConnectionProxy connection) throws SQLException { + chain.connection_commit(connection); + + JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); + dataSourceStat.getConnectionStat().incrementConnectionCommitCount(); + } + + @Override + public void connection_rollback(FilterChain chain, ConnectionProxy connection) throws SQLException { + chain.connection_rollback(connection); + + JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); + dataSourceStat.getConnectionStat().incrementConnectionRollbackCount(); + dataSourceStat.getConnectionStat().incrementConnectionRollbackCount(); + } + + @Override + public void connection_rollback(FilterChain chain, ConnectionProxy connection, Savepoint savepoint) + throws SQLException { + chain.connection_rollback(connection, savepoint); + + JdbcDataSourceStat dataSourceStat = connection.getDirectDataSource().getDataSourceStat(); + dataSourceStat.getConnectionStat().incrementConnectionRollbackCount(); + } + + @Override + public void statementCreateAfter(StatementProxy statement) { + JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); + dataSourceStat.getStatementStat().incrementCreateCounter(); + + super.statementCreateAfter(statement); + } + + @Override + public void statementPrepareCallAfter(CallableStatementProxy statement) { + JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); + dataSourceStat.getStatementStat().incrementPrepareCallCount(); + + JdbcSqlStat sqlStat = createSqlStat(statement, statement.getSql()); + statement.setSqlStat(sqlStat); + } + + @Override + public void statementPrepareAfter(PreparedStatementProxy statement) { + JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); + dataSourceStat.getStatementStat().incrementPrepareCounter(); + JdbcSqlStat sqlStat = createSqlStat(statement, statement.getSql()); + statement.setSqlStat(sqlStat); + } + + @Override + public void statement_close(FilterChain chain, StatementProxy statement) throws SQLException { + chain.statement_close(statement); + + JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); + dataSourceStat.getStatementStat().incrementStatementCloseCounter(); + JdbcStatContext context = JdbcStatManager.getInstance().getStatContext(); + if (context != null) { + context.setName(null); + context.setFile(null); + context.setSql(null); + } + } + + @Override + protected void statementExecuteUpdateBefore(StatementProxy statement, String sql) { + internalBeforeStatementExecute(statement, sql); + } + + @Override + protected void statementExecuteUpdateAfter(StatementProxy statement, String sql, int updateCount) { + internalAfterStatementExecute(statement, false, updateCount); + } + + @Override + protected void statementExecuteQueryBefore(StatementProxy statement, String sql) { + internalBeforeStatementExecute(statement, sql); + } + + @Override + protected void statementExecuteQueryAfter(StatementProxy statement, String sql, ResultSetProxy resultSet) { + internalAfterStatementExecute(statement, true); + } + + @Override + protected void statementExecuteBefore(StatementProxy statement, String sql) { + internalBeforeStatementExecute(statement, sql); + } + + @Override + protected void statementExecuteAfter(StatementProxy statement, String sql, boolean firstResult) { + internalAfterStatementExecute(statement, firstResult); + } + + @Override + protected void statementExecuteBatchBefore(StatementProxy statement) { + final String sql = statement.getBatchSql(); + + final int batchSize = statement.getBatchSqlList().size(); + JdbcSqlStat sqlStat = statement.getSqlStat(); + if (sqlStat == null || sqlStat.isRemoved()) { + sqlStat = createSqlStat(statement, sql); + statement.setSqlStat(sqlStat); + } + + if (sqlStat != null) { + sqlStat.addExecuteBatchCount(batchSize); + } + + internalBeforeStatementExecute(statement, sql); + + } + + @Override + protected void statementExecuteBatchAfter(StatementProxy statement, int[] result) { + internalAfterStatementExecute(statement, false, result); + + } + + private final void internalBeforeStatementExecute(StatementProxy statement, String sql) { + JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); + dataSourceStat.getStatementStat().beforeExecute(); + + final ConnectionProxy connection = statement.getConnectionProxy(); + final JdbcConnectionStat.Entry connectionCounter = getConnectionInfo(connection); + + statement.setLastExecuteStartNano(); + + connectionCounter.setLastSql(sql); + + if (connectionStackTraceEnable) { + connectionCounter.setLastStatementStatckTrace(new Exception()); + } + + // //////////SQL + + JdbcSqlStat sqlStat = statement.getSqlStat(); + if (sqlStat == null || sqlStat.isRemoved()) { + sqlStat = createSqlStat(statement, sql); + statement.setSqlStat(sqlStat); + } + + JdbcStatContext statContext = JdbcStatManager.getInstance().getStatContext(); + if (statContext != null) { + sqlStat.setName(statContext.getName()); + sqlStat.setFile(statContext.getFile()); + } + + boolean inTransaction = false; + try { + inTransaction = !statement.getConnectionProxy().getAutoCommit(); + } catch (SQLException e) { + LOG.error("getAutoCommit error", e); + } + + if (sqlStat != null) { + sqlStat.setExecuteLastStartTime(System.currentTimeMillis()); + sqlStat.incrementRunningCount(); + + if (inTransaction) { + sqlStat.incrementInTransactionCount(); + } + } + + StatFilterContext.getInstance().executeBefore(sql, inTransaction); + + Profiler.enter(sql, Profiler.PROFILE_TYPE_SQL); + } + + private final void internalAfterStatementExecute(StatementProxy statement, boolean firstResult, + int... updateCountArray) { + final long nowNano = System.nanoTime(); + final long nanos = nowNano - statement.getLastExecuteStartNano(); + + JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); + dataSourceStat.getStatementStat().afterExecute(nanos); + + final JdbcSqlStat sqlStat = statement.getSqlStat(); + + if (sqlStat != null) { + sqlStat.incrementExecuteSuccessCount(); + + sqlStat.decrementRunningCount(); + sqlStat.addExecuteTime(statement.getLastExecuteType(), firstResult, nanos); + statement.setLastExecuteTimeNano(nanos); + if ((!statement.isFirstResultSet()) && statement.getLastExecuteType() == StatementExecuteType.Execute) { + try { + int updateCount = statement.getUpdateCount(); + sqlStat.addUpdateCount(updateCount); + } catch (SQLException e) { + LOG.error("getUpdateCount error", e); + } + } else { + for (int updateCount : updateCountArray) { + sqlStat.addUpdateCount(updateCount); + sqlStat.addFetchRowCount(0); + StatFilterContext.getInstance().addUpdateCount(updateCount); + } + } + + long millis = nanos / (1000 * 1000); + if (millis >= slowSqlMillis) { + String slowParameters = buildSlowParameters(statement); + sqlStat.setLastSlowParameters(slowParameters); + + if (logSlowSql) { + LOG.error("slow sql " + millis + " millis. \n" + statement.getLastExecuteSql() + "\n" + + slowParameters); + } + } + } + + String sql = statement.getLastExecuteSql(); + StatFilterContext.getInstance().executeAfter(sql, nanos, null); + + Profiler.release(nanos); + } + + @Override + protected void statement_executeErrorAfter(StatementProxy statement, String sql, Throwable error) { + + ConnectionProxy connection = statement.getConnectionProxy(); + JdbcConnectionStat.Entry connectionCounter = getConnectionInfo(connection); + + long nanos = System.nanoTime() - statement.getLastExecuteStartNano(); + + JdbcDataSourceStat dataSourceStat = statement.getConnectionProxy().getDirectDataSource().getDataSourceStat(); + dataSourceStat.getStatementStat().error(error); + dataSourceStat.getStatementStat().afterExecute(nanos); + + connectionCounter.error(error); + + // SQL + JdbcSqlStat sqlStat = statement.getSqlStat(); + + if (sqlStat != null) { + sqlStat.error(error); + sqlStat.addExecuteTime(statement.getLastExecuteType(), statement.isFirstResultSet(), nanos); + statement.setLastExecuteTimeNano(nanos); + } + + StatFilterContext.getInstance().executeAfter(sql, nanos, error); + Profiler.release(nanos); + } + + private String buildSlowParameters(StatementProxy statement) { + JSONWriter out = new JSONWriter(); + + out.writeArrayStart(); + for (int i = 0, parametersSize = statement.getParametersSize(); i < parametersSize; ++i) { + JdbcParameter parameter = statement.getParameter(i); + if (i != 0) { + out.writeComma(); + } + if (parameter == null) { + continue; + } + + Object value = parameter.getValue(); + if (value == null) { + out.writeNull(); + } else if (value instanceof String) { + String text = (String) value; + if (text.length() > 100) { + out.writeString(text.substring(0, 97) + "..."); + } else { + out.writeString(text); + } + } else if (value instanceof Number) { + out.writeObject(value); + } else if (value instanceof java.util.Date) { + out.writeObject(value); + } else if (value instanceof Boolean) { + out.writeObject(value); + } else if (value instanceof InputStream) { + out.writeString(""); + } else if (value instanceof NClob) { + out.writeString(""); + } else if (value instanceof Clob) { + out.writeString(""); + } else if (value instanceof Blob) { + out.writeString(""); + } else { + out.writeString('<' + value.getClass().getName() + '>'); + } + } + out.writeArrayEnd(); + + return out.toString(); + } + + @Override + protected void resultSetOpenAfter(ResultSetProxy resultSet) { + JdbcDataSourceStat dataSourceStat = resultSet.getStatementProxy().getConnectionProxy().getDirectDataSource().getDataSourceStat(); + dataSourceStat.getResultSetStat().beforeOpen(); + + resultSet.setConstructNano(); + + StatFilterContext.getInstance().resultSet_open(); + } + + @Override + public void resultSet_close(FilterChain chain, ResultSetProxy resultSet) throws SQLException { + + long nanos = System.nanoTime() - resultSet.getConstructNano(); + + int fetchRowCount = resultSet.getFetchRowCount(); + + JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); + dataSourceStat.getResultSetStat().afterClose(nanos); + dataSourceStat.getResultSetStat().addFetchRowCount(fetchRowCount); + dataSourceStat.getResultSetStat().incrementCloseCounter(); + + StatFilterContext.getInstance().addFetchRowCount(fetchRowCount); + + String sql = resultSet.getSql(); + if (sql != null) { + JdbcSqlStat sqlStat = resultSet.getSqlStat(); + if (sqlStat != null && resultSet.getCloseCount() == 0) { + sqlStat.addFetchRowCount(fetchRowCount); + long stmtExecuteNano = resultSet.getStatementProxy().getLastExecuteTimeNano(); + sqlStat.addResultSetHoldTimeNano(stmtExecuteNano, nanos); + if (resultSet.getReadStringLength() > 0) { + sqlStat.addStringReadLength(resultSet.getReadStringLength()); + } + if (resultSet.getReadBytesLength() > 0) { + sqlStat.addReadBytesLength(resultSet.getReadBytesLength()); + } + if (resultSet.getOpenInputStreamCount() > 0) { + sqlStat.addInputStreamOpenCount(resultSet.getOpenInputStreamCount()); + } + if (resultSet.getOpenReaderCount() > 0) { + sqlStat.addReaderOpenCount(resultSet.getOpenReaderCount()); + } + } + } + + chain.resultSet_close(resultSet); + + StatFilterContext.getInstance().resultSet_close(nanos); + } + + public JdbcConnectionStat.Entry getConnectionInfo(ConnectionProxy connection) { + JdbcConnectionStat.Entry counter = (JdbcConnectionStat.Entry) connection.getAttributes().get(ATTR_NAME_CONNECTION_STAT); + + if (counter == null) { + String dataSourceName = connection.getDirectDataSource().getName(); + connection.getAttributes().put(ATTR_NAME_CONNECTION_STAT, + new JdbcConnectionStat.Entry(dataSourceName, connection.getId())); + counter = (JdbcConnectionStat.Entry) connection.getAttributes().get(ATTR_NAME_CONNECTION_STAT); + } + + return counter; + } + + public JdbcSqlStat createSqlStat(StatementProxy statement, String sql) { + DataSourceProxy dataSource = statement.getConnectionProxy().getDirectDataSource(); + JdbcDataSourceStat dataSourceStat = dataSource.getDataSourceStat(); + + JdbcStatContext context = JdbcStatManager.getInstance().getStatContext(); + String contextSql = context != null ? context.getSql() : null; + if (contextSql != null && contextSql.length() > 0) { + return dataSourceStat.createSqlStat(contextSql); + } else { + String dbType = this.dbType; + + if (dbType == null) { + dbType = dataSource.getDbType(); + } + + sql = mergeSql(sql, dbType); + return dataSourceStat.createSqlStat(sql); + } + } + + public static StatFilter getStatFilter(DataSourceProxy dataSource) { + for (Filter filter : dataSource.getProxyFilters()) { + if (filter instanceof StatFilter) { + return (StatFilter) filter; + } + } + + return null; + } + + @Override + public void dataSource_releaseConnection(FilterChain chain, DruidPooledConnection conn) throws SQLException { + chain.dataSource_recycle(conn); + + long nanos = System.nanoTime() - conn.getConnectedTimeNano(); + + long millis = nanos / (1000L * 1000L); + + JdbcDataSourceStat dataSourceStat = chain.getDataSource().getDataSourceStat(); + dataSourceStat.getConnectionHoldHistogram().record(millis); + + StatFilterContext.getInstance().pool_connection_close(nanos); + } + + @Override + public DruidPooledConnection dataSource_getConnection(FilterChain chain, DruidDataSource dataSource, + long maxWaitMillis) throws SQLException { + DruidPooledConnection conn = chain.dataSource_connect(dataSource, maxWaitMillis); + + if (conn != null) { + conn.setConnectedTimeNano(); + + StatFilterContext.getInstance().pool_connection_open(); + } + + return conn; + } + + @Override + public Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, int columnIndex) throws SQLException { + Clob clob = chain.resultSet_getClob(resultSet, columnIndex); + + if (clob != null) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), resultSet, (ClobProxy) clob); + } + + return clob; + } + + @Override + public Clob resultSet_getClob(FilterChain chain, ResultSetProxy resultSet, String columnLabel) throws SQLException { + Clob clob = chain.resultSet_getClob(resultSet, columnLabel); + + if (clob != null) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), resultSet, (ClobProxy) clob); + } + + return clob; + } + + @Override + public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, int parameterIndex) + throws SQLException { + Blob blob = chain.callableStatement_getBlob(statement, parameterIndex); + + if (blob != null) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, blob); + } + + return blob; + } + + @Override + public Blob callableStatement_getBlob(FilterChain chain, CallableStatementProxy statement, String parameterName) + throws SQLException { + Blob blob = chain.callableStatement_getBlob(statement, parameterName); + + if (blob != null) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, blob); + } + + return blob; + } + + @Override + public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { + Blob blob = chain.resultSet_getBlob(result, columnIndex); + + if (blob != null) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, blob); + } + + return blob; + } + + @Override + public Blob resultSet_getBlob(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { + Blob blob = chain.resultSet_getBlob(result, columnLabel); + + if (blob != null) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, blob); + } + + return blob; + } + + @Override + public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, int parameterIndex) + throws SQLException { + Clob clob = chain.callableStatement_getClob(statement, parameterIndex); + + if (clob != null) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) clob); + } + + return clob; + } + + @Override + public Clob callableStatement_getClob(FilterChain chain, CallableStatementProxy statement, String parameterName) + throws SQLException { + Clob clob = chain.callableStatement_getClob(statement, parameterName); + + if (clob != null) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) clob); + } + + return clob; + } + + @Override + public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { + Object obj = chain.resultSet_getObject(result, columnIndex); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); + } else if (obj instanceof String) { + result.addReadStringLength(((String) obj).length()); + } + + return obj; + } + + @Override + public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, int columnIndex, + java.util.Map> map) throws SQLException { + Object obj = chain.resultSet_getObject(result, columnIndex, map); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); + } else if (obj instanceof String) { + result.addReadStringLength(((String) obj).length()); + } + + return obj; + } + + @Override + public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { + Object obj = chain.resultSet_getObject(result, columnLabel); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); + } else if (obj instanceof String) { + result.addReadStringLength(((String) obj).length()); + } + + return obj; + } + + @Override + public Object resultSet_getObject(FilterChain chain, ResultSetProxy result, String columnLabel, + java.util.Map> map) throws SQLException { + Object obj = chain.resultSet_getObject(result, columnLabel, map); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), result, (Blob) obj); + } else if (obj instanceof String) { + result.addReadStringLength(((String) obj).length()); + } + + return obj; + } + + @Override + public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex) + throws SQLException { + Object obj = chain.callableStatement_getObject(statement, parameterIndex); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); + } + + return obj; + } + + @Override + public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, int parameterIndex, + java.util.Map> map) throws SQLException { + Object obj = chain.callableStatement_getObject(statement, parameterIndex, map); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); + } + + return obj; + } + + @Override + public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, String parameterName) + throws SQLException { + Object obj = chain.callableStatement_getObject(statement, parameterName); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); + } + + return obj; + } + + @Override + public Object callableStatement_getObject(FilterChain chain, CallableStatementProxy statement, + String parameterName, java.util.Map> map) + throws SQLException { + Object obj = chain.callableStatement_getObject(statement, parameterName, map); + + if (obj instanceof Clob) { + clobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (ClobProxy) obj); + } else if (obj instanceof Blob) { + blobOpenAfter(chain.getDataSource().getDataSourceStat(), statement, (Blob) obj); + } + + return obj; + } + + private void blobOpenAfter(JdbcDataSourceStat dataSourceStat, ResultSetProxy rs, Blob blob) { + blobOpenAfter(dataSourceStat, rs.getStatementProxy(), blob); + } + + private void clobOpenAfter(JdbcDataSourceStat dataSourceStat, ResultSetProxy rs, ClobProxy clob) { + clobOpenAfter(dataSourceStat, rs.getStatementProxy(), clob); + } + + private void blobOpenAfter(JdbcDataSourceStat dataSourceStat, StatementProxy stmt, Blob blob) { + dataSourceStat.incrementBlobOpenCount(); + + if (stmt != null) { + JdbcSqlStat sqlStat = stmt.getSqlStat(); + if (sqlStat != null) { + sqlStat.incrementBlobOpenCount(); + } + } + + StatFilterContext.getInstance().blob_open(); + } + + private void clobOpenAfter(JdbcDataSourceStat dataSourceStat, StatementProxy stmt, ClobProxy clob) { + dataSourceStat.incrementClobOpenCount(); + + if (stmt != null) { + JdbcSqlStat sqlStat = stmt.getSqlStat(); + if (sqlStat != null) { + sqlStat.incrementClobOpenCount(); + } + } + + StatFilterContext.getInstance().clob_open(); + } + + @Override + public String resultSet_getString(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { + String value = chain.resultSet_getString(result, columnIndex); + + if (value != null) { + result.addReadStringLength(value.length()); + } + + return value; + } + + @Override + public String resultSet_getString(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { + String value = chain.resultSet_getString(result, columnLabel); + + if (value != null) { + result.addReadStringLength(value.length()); + } + + return value; + } + + @Override + public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, int columnIndex) throws SQLException { + byte[] value = chain.resultSet_getBytes(result, columnIndex); + + if (value != null) { + result.addReadBytesLength(value.length); + } + + return value; + } + + @Override + public byte[] resultSet_getBytes(FilterChain chain, ResultSetProxy result, String columnLabel) throws SQLException { + byte[] value = chain.resultSet_getBytes(result, columnLabel); + + if (value != null) { + result.addReadBytesLength(value.length); + } + + return value; + } + + @Override + public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + InputStream input = chain.resultSet_getBinaryStream(result, columnIndex); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public InputStream resultSet_getBinaryStream(FilterChain chain, ResultSetProxy result, String columnLabel) + throws SQLException { + InputStream input = chain.resultSet_getBinaryStream(result, columnLabel); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + InputStream input = chain.resultSet_getAsciiStream(result, columnIndex); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public InputStream resultSet_getAsciiStream(FilterChain chain, ResultSetProxy result, String columnLabel) + throws SQLException { + InputStream input = chain.resultSet_getAsciiStream(result, columnLabel); + + if (input != null) { + result.incrementOpenInputStreamCount(); + } + + return input; + } + + @Override + public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, int columnIndex) + throws SQLException { + Reader reader = chain.resultSet_getCharacterStream(result, columnIndex); + + if (reader != null) { + result.incrementOpenReaderCount(); + } + + return reader; + } + + @Override + public Reader resultSet_getCharacterStream(FilterChain chain, ResultSetProxy result, String columnLabel) + throws SQLException { + Reader reader = chain.resultSet_getCharacterStream(result, columnLabel); + + if (reader != null) { + result.incrementOpenReaderCount(); + } + + return reader; + } +} diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java index 047cc463c5..f3ce56b77c 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/PreparedStatementProxyImpl.java @@ -1,593 +1,614 @@ -/* - * 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.proxy.jdbc; - -import java.io.InputStream; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.URL; -import java.sql.Array; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Date; -import java.sql.NClob; -import java.sql.ParameterMetaData; -import java.sql.PreparedStatement; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLXML; -import java.sql.Time; -import java.sql.Timestamp; -import java.sql.Types; -import java.util.Calendar; -import java.util.Map; -import java.util.TreeMap; - -import com.alibaba.druid.proxy.jdbc.JdbcParameter.TYPE; - -/** - * @author wenshao - */ -public class PreparedStatementProxyImpl extends StatementProxyImpl implements PreparedStatementProxy { - - protected final PreparedStatement statement; - protected final String sql; - protected final Map parameters = new TreeMap(); - - public PreparedStatementProxyImpl(ConnectionProxy connection, PreparedStatement statement, String sql, long id){ - super(connection, statement, id); - this.statement = statement; - this.sql = sql; - } - - public Map getParameters() { - return parameters; - } - - public String getSql() { - return this.sql; - } - - public PreparedStatement getRawObject() { - return this.statement; - } - - @Override - public void addBatch() throws SQLException { - createChain().preparedStatement_addBatch(this); - } - - @Override - public void clearParameters() throws SQLException { - createChain().preparedStatement_clearParameters(this); - } - - @Override - public String getBatchSql() { - return this.sql; - } - - @Override - public boolean execute() throws SQLException { - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.Execute; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - firstResultSet = createChain().preparedStatement_execute(this); - return firstResultSet; - } - - @Override - public ResultSet executeQuery() throws SQLException { - firstResultSet = true; - - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.ExecuteQuery; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - return createChain().preparedStatement_executeQuery(this); - } - - @Override - public int executeUpdate() throws SQLException { - firstResultSet = false; - - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.ExecuteUpdate; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - updateCount = createChain().preparedStatement_executeUpdate(this); - return updateCount; - } - - @Override - public ResultSetMetaData getMetaData() throws SQLException { - return createChain().preparedStatement_getMetaData(this); - } - - @Override - public ParameterMetaData getParameterMetaData() throws SQLException { - return createChain().preparedStatement_getParameterMetaData(this); - } - - @Override - public void setArray(int parameterIndex, Array x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.ARRAY, x)); - - createChain().preparedStatement_setArray(this, parameterIndex, x); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.AsciiInputStream, x)); - - createChain().preparedStatement_setAsciiStream(this, parameterIndex, x); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.AsciiInputStream, x, length)); - - createChain().preparedStatement_setAsciiStream(this, parameterIndex, x, length); - } - - @Override - public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.AsciiInputStream, x, length)); - - createChain().preparedStatement_setAsciiStream(this, parameterIndex, x, length); - } - - @Override - public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.DECIMAL, x)); - createChain().preparedStatement_setBigDecimal(this, parameterIndex, x); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x)); - - createChain().preparedStatement_setBinaryStream(this, parameterIndex, x); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x, length)); - - createChain().preparedStatement_setBinaryStream(this, parameterIndex, x, length); - } - - @Override - public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x, length)); - - createChain().preparedStatement_setBinaryStream(this, parameterIndex, x, length); - } - - @Override - public void setBlob(int parameterIndex, Blob x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x)); - - createChain().preparedStatement_setBlob(this, parameterIndex, x); - } - - @Override - public void setBlob(int parameterIndex, InputStream x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x)); - - createChain().preparedStatement_setBlob(this, parameterIndex, x); - } - - @Override - public void setBlob(int parameterIndex, InputStream x, long length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x, length)); - createChain().preparedStatement_setBlob(this, parameterIndex, x, length); - } - - @Override - public void setBoolean(int parameterIndex, boolean x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.BOOLEAN, x)); - createChain().preparedStatement_setBoolean(this, parameterIndex, x); - } - - @Override - public void setByte(int parameterIndex, byte x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.TINYINT, x)); - - createChain().preparedStatement_setByte(this, parameterIndex, x); - } - - @Override - public void setBytes(int parameterIndex, byte[] x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.BYTES, x)); - - createChain().preparedStatement_setBytes(this, parameterIndex, x); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.CharacterInputStream, x)); - - createChain().preparedStatement_setCharacterStream(this, parameterIndex, x); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader x, int length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.CharacterInputStream, x, length)); - - createChain().preparedStatement_setCharacterStream(this, parameterIndex, x, length); - } - - @Override - public void setCharacterStream(int parameterIndex, Reader x, long length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.CharacterInputStream, x, length)); - - createChain().preparedStatement_setCharacterStream(this, parameterIndex, x, length); - } - - @Override - public void setClob(int parameterIndex, Clob x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x)); - - createChain().preparedStatement_setClob(this, parameterIndex, x); - } - - @Override - public void setClob(int parameterIndex, Reader x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x)); - - createChain().preparedStatement_setClob(this, parameterIndex, x); - } - - @Override - public void setClob(int parameterIndex, Reader x, long length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x, length)); - - createChain().preparedStatement_setClob(this, parameterIndex, x, length); - } - - @Override - public void setDate(int parameterIndex, Date x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.DATE, x)); - - createChain().preparedStatement_setDate(this, parameterIndex, x); - } - - @Override - public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.DATE, x, cal)); - - createChain().preparedStatement_setDate(this, parameterIndex, x, cal); - } - - @Override - public void setDouble(int parameterIndex, double x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.DOUBLE, x)); - - createChain().preparedStatement_setDouble(this, parameterIndex, x); - } - - @Override - public void setFloat(int parameterIndex, float x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.FLOAT, x)); - - createChain().preparedStatement_setFloat(this, parameterIndex, x); - } - - @Override - public void setInt(int parameterIndex, int x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.INTEGER, x)); - - createChain().preparedStatement_setInt(this, parameterIndex, x); - } - - @Override - public void setLong(int parameterIndex, long x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.BIGINT, x)); - - createChain().preparedStatement_setLong(this, parameterIndex, x); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.NCharacterInputStream, x)); - - createChain().preparedStatement_setNCharacterStream(this, parameterIndex, x); - } - - @Override - public void setNCharacterStream(int parameterIndex, Reader x, long length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.NCharacterInputStream, x, length)); - - createChain().preparedStatement_setNCharacterStream(this, parameterIndex, x, length); - } - - @Override - public void setNClob(int parameterIndex, NClob x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x)); - - createChain().preparedStatement_setNClob(this, parameterIndex, x); - } - - @Override - public void setNClob(int parameterIndex, Reader x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x)); - - createChain().preparedStatement_setNClob(this, parameterIndex, x); - } - - @Override - public void setNClob(int parameterIndex, Reader x, long length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x, length)); - - createChain().preparedStatement_setNClob(this, parameterIndex, x, length); - } - - @Override - public void setNString(int parameterIndex, String x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.NVARCHAR, x)); - - createChain().preparedStatement_setNString(this, parameterIndex, x); - } - - @Override - public void setNull(int parameterIndex, int sqlType) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(sqlType, null)); - - createChain().preparedStatement_setNull(this, parameterIndex, sqlType); - } - - @Override - public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(sqlType, null)); - - createChain().preparedStatement_setNull(this, parameterIndex, sqlType, typeName); - } - - @Override - public void setObject(int parameterIndex, Object x) throws SQLException { - setObjectParameter(parameterIndex, x); - - createChain().preparedStatement_setObject(this, parameterIndex, x); - } - - private void setObjectParameter(int parameterIndex, Object x) { - if (x == null) { - setParameter(parameterIndex, new JdbcParameter(Types.OTHER, null)); - return; - } - - Class clazz = x.getClass(); - if (clazz == Byte.class) { - setParameter(parameterIndex, new JdbcParameter(Types.TINYINT, x)); - return; - } - - if (clazz == Short.class) { - setParameter(parameterIndex, new JdbcParameter(Types.SMALLINT, x)); - return; - } - - if (clazz == Integer.class) { - setParameter(parameterIndex, new JdbcParameter(Types.INTEGER, x)); - return; - } - - if (clazz == Long.class) { - setParameter(parameterIndex, new JdbcParameter(Types.BIGINT, x)); - return; - } - - if (clazz == String.class) { - setParameter(parameterIndex, new JdbcParameter(Types.VARCHAR, x)); - return; - } - - if (clazz == BigDecimal.class) { - setParameter(parameterIndex, new JdbcParameter(Types.DECIMAL, x)); - return; - } - - if (clazz == Float.class) { - setParameter(parameterIndex, new JdbcParameter(Types.FLOAT, x)); - return; - } - - if (clazz == Double.class) { - setParameter(parameterIndex, new JdbcParameter(Types.DOUBLE, x)); - return; - } - - if (clazz == java.sql.Date.class || clazz == java.util.Date.class) { - setParameter(parameterIndex, new JdbcParameter(Types.DATE, x)); - return; - } - - if (clazz == java.sql.Timestamp.class) { - setParameter(parameterIndex, new JdbcParameter(Types.TIMESTAMP, x)); - return; - } - - if (clazz == java.sql.Time.class) { - setParameter(parameterIndex, new JdbcParameter(Types.TIME, x)); - return; - } - - if (clazz == Boolean.class) { - setParameter(parameterIndex, new JdbcParameter(Types.BOOLEAN, x)); - return; - } - - if (clazz == byte[].class) { - setParameter(parameterIndex, new JdbcParameter(TYPE.BYTES, x)); - return; - } - - if (x instanceof InputStream) { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x)); - return; - } - - if (x instanceof Reader) { - setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.CharacterInputStream, x)); - return; - } - - if (x instanceof Clob) { - setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x)); - return; - } - - if (x instanceof NClob) { - setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x)); - return; - } - - if (x instanceof Blob) { - setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x)); - return; - } - - setParameter(parameterIndex, new JdbcParameter(Types.OTHER, null)); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(targetSqlType, x)); - - createChain().preparedStatement_setObject(this, parameterIndex, x, targetSqlType); - } - - @Override - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(targetSqlType, x, -1, null, scaleOrLength)); - - createChain().preparedStatement_setObject(this, parameterIndex, x, targetSqlType, scaleOrLength); - } - - @Override - public void setRef(int parameterIndex, Ref x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.REF, x)); - - createChain().preparedStatement_setRef(this, parameterIndex, x); - } - - @Override - public void setRowId(int parameterIndex, RowId x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.ROWID, x)); - - createChain().preparedStatement_setRowId(this, parameterIndex, x); - } - - @Override - public void setSQLXML(int parameterIndex, SQLXML x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.SQLXML, x)); - - createChain().preparedStatement_setSQLXML(this, parameterIndex, x); - } - - @Override - public void setShort(int parameterIndex, short x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.SMALLINT, x)); - - createChain().preparedStatement_setShort(this, parameterIndex, x); - } - - @Override - public void setString(int parameterIndex, String x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.VARCHAR, x)); - - createChain().preparedStatement_setString(this, parameterIndex, x); - } - - @Override - public void setTime(int parameterIndex, Time x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.TIME, x)); - - createChain().preparedStatement_setTime(this, parameterIndex, x); - } - - @Override - public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.TIME, x, cal)); - - createChain().preparedStatement_setTime(this, parameterIndex, x, cal); - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.TIMESTAMP, x)); - - createChain().preparedStatement_setTimestamp(this, parameterIndex, x); - } - - @Override - public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(Types.TIMESTAMP, x)); - - createChain().preparedStatement_setTimestamp(this, parameterIndex, x, cal); - } - - @Override - public void setURL(int parameterIndex, URL x) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.URL, x)); - - createChain().preparedStatement_setURL(this, parameterIndex, x); - } - - @Override - public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { - setParameter(parameterIndex, new JdbcParameter(TYPE.UnicodeStream, x, length)); - - createChain().preparedStatement_setUnicodeStream(this, parameterIndex, x, length); - } - - public void setParameter(int parameterIndex, JdbcParameter parameter) { - this.getParameters().put(parameterIndex, parameter); - } - - @Override - public String getLastExecuteSql() { - return this.sql; - } - - @SuppressWarnings("unchecked") - public T unwrap(Class iface) throws SQLException { - if (iface == PreparedStatementProxy.class) { - return (T) this; - } - - return super.unwrap(iface); - } - - public boolean isWrapperFor(Class iface) throws SQLException { - if (iface == PreparedStatementProxy.class) { - return true; - } - - return super.isWrapperFor(iface); - } -} +/* + * 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.proxy.jdbc; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.sql.Types; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Map; + +import com.alibaba.druid.proxy.jdbc.JdbcParameter.TYPE; + +/** + * @author wenshao + */ +public class PreparedStatementProxyImpl extends StatementProxyImpl implements PreparedStatementProxy { + + protected final PreparedStatement statement; + protected final String sql; + // protected final Map parameters = new TreeMap(); + private JdbcParameter[] parameters = new JdbcParameter[16]; + private int parametersSize = 0; + + public PreparedStatementProxyImpl(ConnectionProxy connection, PreparedStatement statement, String sql, long id){ + super(connection, statement, id); + this.statement = statement; + this.sql = sql; + } + + public Map getParameters() { + return null; + } + + void setParameter(int jdbcIndex, JdbcParameter parameter) { + int index = jdbcIndex - 1; + + if (jdbcIndex > parametersSize) { + parametersSize = jdbcIndex; + } + if (parametersSize >= parameters.length) { + parameters = Arrays.copyOf(parameters, parametersSize + 1); + } + parameters[index] = parameter; + } + + public int getParametersSize() { + return parametersSize; + } + + public JdbcParameter getParameter(int i) { + if (i > parametersSize) { + return null; + } + return this.parameters[i]; + } + + public String getSql() { + return this.sql; + } + + public PreparedStatement getRawObject() { + return this.statement; + } + + @Override + public void addBatch() throws SQLException { + createChain().preparedStatement_addBatch(this); + } + + @Override + public void clearParameters() throws SQLException { + createChain().preparedStatement_clearParameters(this); + } + + @Override + public String getBatchSql() { + return this.sql; + } + + @Override + public boolean execute() throws SQLException { + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.Execute; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + firstResultSet = createChain().preparedStatement_execute(this); + return firstResultSet; + } + + @Override + public ResultSet executeQuery() throws SQLException { + firstResultSet = true; + + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.ExecuteQuery; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + return createChain().preparedStatement_executeQuery(this); + } + + @Override + public int executeUpdate() throws SQLException { + firstResultSet = false; + + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.ExecuteUpdate; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + updateCount = createChain().preparedStatement_executeUpdate(this); + return updateCount; + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return createChain().preparedStatement_getMetaData(this); + } + + @Override + public ParameterMetaData getParameterMetaData() throws SQLException { + return createChain().preparedStatement_getParameterMetaData(this); + } + + @Override + public void setArray(int parameterIndex, Array x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.ARRAY, x)); + + createChain().preparedStatement_setArray(this, parameterIndex, x); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.AsciiInputStream, x)); + + createChain().preparedStatement_setAsciiStream(this, parameterIndex, x); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.AsciiInputStream, x, length)); + + createChain().preparedStatement_setAsciiStream(this, parameterIndex, x, length); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.AsciiInputStream, x, length)); + + createChain().preparedStatement_setAsciiStream(this, parameterIndex, x, length); + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.DECIMAL, x)); + createChain().preparedStatement_setBigDecimal(this, parameterIndex, x); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x)); + + createChain().preparedStatement_setBinaryStream(this, parameterIndex, x); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x, length)); + + createChain().preparedStatement_setBinaryStream(this, parameterIndex, x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x, length)); + + createChain().preparedStatement_setBinaryStream(this, parameterIndex, x, length); + } + + @Override + public void setBlob(int parameterIndex, Blob x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x)); + + createChain().preparedStatement_setBlob(this, parameterIndex, x); + } + + @Override + public void setBlob(int parameterIndex, InputStream x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x)); + + createChain().preparedStatement_setBlob(this, parameterIndex, x); + } + + @Override + public void setBlob(int parameterIndex, InputStream x, long length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x, length)); + createChain().preparedStatement_setBlob(this, parameterIndex, x, length); + } + + @Override + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.BOOLEAN, x)); + createChain().preparedStatement_setBoolean(this, parameterIndex, x); + } + + @Override + public void setByte(int parameterIndex, byte x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.TINYINT, x)); + + createChain().preparedStatement_setByte(this, parameterIndex, x); + } + + @Override + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.BYTES, x)); + + createChain().preparedStatement_setBytes(this, parameterIndex, x); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.CharacterInputStream, x)); + + createChain().preparedStatement_setCharacterStream(this, parameterIndex, x); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader x, int length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.CharacterInputStream, x, length)); + + createChain().preparedStatement_setCharacterStream(this, parameterIndex, x, length); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader x, long length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.CharacterInputStream, x, length)); + + createChain().preparedStatement_setCharacterStream(this, parameterIndex, x, length); + } + + @Override + public void setClob(int parameterIndex, Clob x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x)); + + createChain().preparedStatement_setClob(this, parameterIndex, x); + } + + @Override + public void setClob(int parameterIndex, Reader x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x)); + + createChain().preparedStatement_setClob(this, parameterIndex, x); + } + + @Override + public void setClob(int parameterIndex, Reader x, long length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x, length)); + + createChain().preparedStatement_setClob(this, parameterIndex, x, length); + } + + @Override + public void setDate(int parameterIndex, Date x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.DATE, x)); + + createChain().preparedStatement_setDate(this, parameterIndex, x); + } + + @Override + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.DATE, x, cal)); + + createChain().preparedStatement_setDate(this, parameterIndex, x, cal); + } + + @Override + public void setDouble(int parameterIndex, double x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.DOUBLE, x)); + + createChain().preparedStatement_setDouble(this, parameterIndex, x); + } + + @Override + public void setFloat(int parameterIndex, float x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.FLOAT, x)); + + createChain().preparedStatement_setFloat(this, parameterIndex, x); + } + + @Override + public void setInt(int parameterIndex, int x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.INTEGER, x)); + + createChain().preparedStatement_setInt(this, parameterIndex, x); + } + + @Override + public void setLong(int parameterIndex, long x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.BIGINT, x)); + + createChain().preparedStatement_setLong(this, parameterIndex, x); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.NCharacterInputStream, x)); + + createChain().preparedStatement_setNCharacterStream(this, parameterIndex, x); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader x, long length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.NCharacterInputStream, x, length)); + + createChain().preparedStatement_setNCharacterStream(this, parameterIndex, x, length); + } + + @Override + public void setNClob(int parameterIndex, NClob x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x)); + + createChain().preparedStatement_setNClob(this, parameterIndex, x); + } + + @Override + public void setNClob(int parameterIndex, Reader x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x)); + + createChain().preparedStatement_setNClob(this, parameterIndex, x); + } + + @Override + public void setNClob(int parameterIndex, Reader x, long length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x, length)); + + createChain().preparedStatement_setNClob(this, parameterIndex, x, length); + } + + @Override + public void setNString(int parameterIndex, String x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.NVARCHAR, x)); + + createChain().preparedStatement_setNString(this, parameterIndex, x); + } + + @Override + public void setNull(int parameterIndex, int sqlType) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(sqlType, null)); + + createChain().preparedStatement_setNull(this, parameterIndex, sqlType); + } + + @Override + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(sqlType, null)); + + createChain().preparedStatement_setNull(this, parameterIndex, sqlType, typeName); + } + + @Override + public void setObject(int parameterIndex, Object x) throws SQLException { + setObjectParameter(parameterIndex, x); + + createChain().preparedStatement_setObject(this, parameterIndex, x); + } + + private void setObjectParameter(int parameterIndex, Object x) { + if (x == null) { + setParameter(parameterIndex, new JdbcParameter(Types.OTHER, null)); + return; + } + + Class clazz = x.getClass(); + if (clazz == Byte.class) { + setParameter(parameterIndex, new JdbcParameter(Types.TINYINT, x)); + return; + } + + if (clazz == Short.class) { + setParameter(parameterIndex, new JdbcParameter(Types.SMALLINT, x)); + return; + } + + if (clazz == Integer.class) { + setParameter(parameterIndex, new JdbcParameter(Types.INTEGER, x)); + return; + } + + if (clazz == Long.class) { + setParameter(parameterIndex, new JdbcParameter(Types.BIGINT, x)); + return; + } + + if (clazz == String.class) { + setParameter(parameterIndex, new JdbcParameter(Types.VARCHAR, x)); + return; + } + + if (clazz == BigDecimal.class) { + setParameter(parameterIndex, new JdbcParameter(Types.DECIMAL, x)); + return; + } + + if (clazz == Float.class) { + setParameter(parameterIndex, new JdbcParameter(Types.FLOAT, x)); + return; + } + + if (clazz == Double.class) { + setParameter(parameterIndex, new JdbcParameter(Types.DOUBLE, x)); + return; + } + + if (clazz == java.sql.Date.class || clazz == java.util.Date.class) { + setParameter(parameterIndex, new JdbcParameter(Types.DATE, x)); + return; + } + + if (clazz == java.sql.Timestamp.class) { + setParameter(parameterIndex, new JdbcParameter(Types.TIMESTAMP, x)); + return; + } + + if (clazz == java.sql.Time.class) { + setParameter(parameterIndex, new JdbcParameter(Types.TIME, x)); + return; + } + + if (clazz == Boolean.class) { + setParameter(parameterIndex, new JdbcParameter(Types.BOOLEAN, x)); + return; + } + + if (clazz == byte[].class) { + setParameter(parameterIndex, new JdbcParameter(TYPE.BYTES, x)); + return; + } + + if (x instanceof InputStream) { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.BinaryInputStream, x)); + return; + } + + if (x instanceof Reader) { + setParameter(parameterIndex, new JdbcParameter(JdbcParameter.TYPE.CharacterInputStream, x)); + return; + } + + if (x instanceof Clob) { + setParameter(parameterIndex, new JdbcParameter(Types.CLOB, x)); + return; + } + + if (x instanceof NClob) { + setParameter(parameterIndex, new JdbcParameter(Types.NCLOB, x)); + return; + } + + if (x instanceof Blob) { + setParameter(parameterIndex, new JdbcParameter(Types.BLOB, x)); + return; + } + + setParameter(parameterIndex, new JdbcParameter(Types.OTHER, null)); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(targetSqlType, x)); + + createChain().preparedStatement_setObject(this, parameterIndex, x, targetSqlType); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(targetSqlType, x, -1, null, scaleOrLength)); + + createChain().preparedStatement_setObject(this, parameterIndex, x, targetSqlType, scaleOrLength); + } + + @Override + public void setRef(int parameterIndex, Ref x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.REF, x)); + + createChain().preparedStatement_setRef(this, parameterIndex, x); + } + + @Override + public void setRowId(int parameterIndex, RowId x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.ROWID, x)); + + createChain().preparedStatement_setRowId(this, parameterIndex, x); + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.SQLXML, x)); + + createChain().preparedStatement_setSQLXML(this, parameterIndex, x); + } + + @Override + public void setShort(int parameterIndex, short x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.SMALLINT, x)); + + createChain().preparedStatement_setShort(this, parameterIndex, x); + } + + @Override + public void setString(int parameterIndex, String x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.VARCHAR, x)); + + createChain().preparedStatement_setString(this, parameterIndex, x); + } + + @Override + public void setTime(int parameterIndex, Time x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.TIME, x)); + + createChain().preparedStatement_setTime(this, parameterIndex, x); + } + + @Override + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.TIME, x, cal)); + + createChain().preparedStatement_setTime(this, parameterIndex, x, cal); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.TIMESTAMP, x)); + + createChain().preparedStatement_setTimestamp(this, parameterIndex, x); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(Types.TIMESTAMP, x)); + + createChain().preparedStatement_setTimestamp(this, parameterIndex, x, cal); + } + + @Override + public void setURL(int parameterIndex, URL x) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.URL, x)); + + createChain().preparedStatement_setURL(this, parameterIndex, x); + } + + @Override + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + setParameter(parameterIndex, new JdbcParameter(TYPE.UnicodeStream, x, length)); + + createChain().preparedStatement_setUnicodeStream(this, parameterIndex, x, length); + } + + @Override + public String getLastExecuteSql() { + return this.sql; + } + + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == PreparedStatementProxy.class) { + return (T) this; + } + + return super.unwrap(iface); + } + + public boolean isWrapperFor(Class iface) throws SQLException { + if (iface == PreparedStatementProxy.class) { + return true; + } + + return super.isWrapperFor(iface); + } +} diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java index aa6a0d9b16..5e15c29e73 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java @@ -1,56 +1,59 @@ -/* - * 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.proxy.jdbc; - -import java.sql.Statement; -import java.util.List; -import java.util.Map; - -import com.alibaba.druid.stat.JdbcSqlStat; - -/** - * @author wenshao - */ -public interface StatementProxy extends Statement, WrapperProxy { - - ConnectionProxy getConnectionProxy(); - - Statement getRawObject(); - - List getBatchSqlList(); - - String getBatchSql(); - - JdbcSqlStat getSqlStat(); - - StatementExecuteType getLastExecuteType(); - - void setSqlStat(JdbcSqlStat sqlStat); - - String getLastExecuteSql(); - - long getLastExecuteStartNano(); - void setLastExecuteStartNano(long lastExecuteStartNano); - void setLastExecuteStartNano(); - - long getLastExecuteTimeNano(); - void setLastExecuteTimeNano(long nano); - void setLastExecuteTimeNano(); - - Map getParameters(); - - boolean isFirstResultSet(); -} +/* + * 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.proxy.jdbc; + +import java.sql.Statement; +import java.util.List; +import java.util.Map; + +import com.alibaba.druid.stat.JdbcSqlStat; + +/** + * @author wenshao + */ +public interface StatementProxy extends Statement, WrapperProxy { + + ConnectionProxy getConnectionProxy(); + + Statement getRawObject(); + + List getBatchSqlList(); + + String getBatchSql(); + + JdbcSqlStat getSqlStat(); + + StatementExecuteType getLastExecuteType(); + + void setSqlStat(JdbcSqlStat sqlStat); + + String getLastExecuteSql(); + + long getLastExecuteStartNano(); + void setLastExecuteStartNano(long lastExecuteStartNano); + void setLastExecuteStartNano(); + + long getLastExecuteTimeNano(); + void setLastExecuteTimeNano(long nano); + void setLastExecuteTimeNano(); + + Map getParameters(); + + int getParametersSize(); + JdbcParameter getParameter(int i); + + boolean isFirstResultSet(); +} diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java index c983019d18..db76323977 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java @@ -1,569 +1,579 @@ -/* - * 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.proxy.jdbc; - -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLWarning; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -import com.alibaba.druid.filter.FilterChainImpl; -import com.alibaba.druid.stat.JdbcSqlStat; - -/** - * @author wenshao - */ -public class StatementProxyImpl extends WrapperProxyImpl implements StatementProxy { - - private final ConnectionProxy connection; - private final Statement statement; - - protected String lastExecuteSql; - protected long lastExecuteStartNano; - protected long lastExecuteTimeNano; - - protected JdbcSqlStat sqlStat; - protected boolean firstResultSet; - - protected ArrayList batchSqlList; - - protected StatementExecuteType lastExecuteType; - - protected Integer updateCount = null; - - private FilterChainImpl filterChain = null; - - public StatementProxyImpl(ConnectionProxy connection, Statement statement, long id){ - super(statement, id); - this.connection = connection; - this.statement = statement; - } - - public ConnectionProxy getConnectionProxy() { - return connection; - } - - public Statement getRawObject() { - return this.statement; - } - - public FilterChainImpl createChain() { - FilterChainImpl chain = this.filterChain; - if (chain == null) { - chain = new FilterChainImpl(this.getConnectionProxy().getDirectDataSource()); - } else { - this.filterChain = null; - } - - return chain; - } - - public void recycleFilterChain(FilterChainImpl chain) { - chain.reset(); - this.filterChain = chain; - } - - @Override - public void addBatch(String sql) throws SQLException { - if (batchSqlList == null) { - batchSqlList = new ArrayList(); - } - - createChain().statement_addBatch(this, sql); - batchSqlList.add(sql); - } - - @Override - public void cancel() throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_cancel(this); - recycleFilterChain(chain); - } - - @Override - public void clearBatch() throws SQLException { - if (batchSqlList == null) { - batchSqlList = new ArrayList(); - } - - FilterChainImpl chain = createChain(); - chain.statement_clearBatch(this); - recycleFilterChain(chain); - batchSqlList.clear(); - } - - @Override - public void clearWarnings() throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_clearWarnings(this); - recycleFilterChain(chain); - } - - @Override - public void close() throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_close(this); - recycleFilterChain(chain); - } - - @Override - public boolean execute(String sql) throws SQLException { - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.Execute; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - firstResultSet = chain.statement_execute(this, sql); - recycleFilterChain(chain); - return firstResultSet; - } - - @Override - public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.Execute; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - firstResultSet = chain.statement_execute(this, sql, autoGeneratedKeys); - recycleFilterChain(chain); - return firstResultSet; - } - - @Override - public boolean execute(String sql, int[] columnIndexes) throws SQLException { - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.Execute; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - firstResultSet = chain.statement_execute(this, sql, columnIndexes); - recycleFilterChain(chain); - return firstResultSet; - } - - @Override - public boolean execute(String sql, String[] columnNames) throws SQLException { - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.Execute; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - firstResultSet = chain.statement_execute(this, sql, columnNames); - recycleFilterChain(chain); - return firstResultSet; - } - - @Override - public int[] executeBatch() throws SQLException { - firstResultSet = false; - lastExecuteType = StatementExecuteType.ExecuteBatch; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - int[] updateCounts = chain.statement_executeBatch(this); - recycleFilterChain(chain); - if (updateCounts != null && updateCounts.length == 1) { - updateCount = updateCounts[0]; - } - - return updateCounts; - } - - @Override - public ResultSet executeQuery(String sql) throws SQLException { - firstResultSet = true; - updateCount = null; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.ExecuteQuery; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - ResultSet resultSet = chain.statement_executeQuery(this, sql); - recycleFilterChain(chain); - return resultSet; - } - - @Override - public int executeUpdate(String sql) throws SQLException { - firstResultSet = false; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.ExecuteUpdate; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - updateCount = chain.statement_executeUpdate(this, sql); - recycleFilterChain(chain); - return updateCount; - } - - @Override - public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - firstResultSet = false; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.ExecuteUpdate; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - updateCount = chain.statement_executeUpdate(this, sql, autoGeneratedKeys); - recycleFilterChain(chain); - return updateCount; - } - - @Override - public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - firstResultSet = false; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.ExecuteUpdate; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - updateCount = chain.statement_executeUpdate(this, sql, columnIndexes); - recycleFilterChain(chain); - return updateCount; - } - - @Override - public int executeUpdate(String sql, String[] columnNames) throws SQLException { - firstResultSet = false; - lastExecuteSql = sql; - lastExecuteType = StatementExecuteType.ExecuteUpdate; - lastExecuteStartNano = -1L; - lastExecuteTimeNano = -1L; - - FilterChainImpl chain = createChain(); - updateCount = chain.statement_executeUpdate(this, sql, columnNames); - recycleFilterChain(chain); - return updateCount; - } - - @Override - public Connection getConnection() throws SQLException { - FilterChainImpl chain = createChain(); - Connection conn = chain.statement_getConnection(this); - recycleFilterChain(chain); - return conn; - } - - @Override - public int getFetchDirection() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getFetchDirection(this); - recycleFilterChain(chain); - return value; - } - - @Override - public int getFetchSize() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getFetchSize(this); - recycleFilterChain(chain); - return value; - } - - @Override - public ResultSet getGeneratedKeys() throws SQLException { - FilterChainImpl chain = createChain(); - ResultSet value = chain.statement_getGeneratedKeys(this); - recycleFilterChain(chain); - return value; - } - - @Override - public int getMaxFieldSize() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getMaxFieldSize(this); - recycleFilterChain(chain); - return value; - } - - @Override - public int getMaxRows() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getMaxRows(this); - recycleFilterChain(chain); - return value; - } - - @Override - public boolean getMoreResults() throws SQLException { - updateCount = null; - FilterChainImpl chain = createChain(); - boolean value = chain.statement_getMoreResults(this); - recycleFilterChain(chain); - return value; - } - - @Override - public boolean getMoreResults(int current) throws SQLException { - updateCount = null; - FilterChainImpl chain = createChain(); - boolean value = chain.statement_getMoreResults(this, current); - recycleFilterChain(chain); - return value; - } - - @Override - public int getQueryTimeout() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getQueryTimeout(this); - recycleFilterChain(chain); - return value; - } - - @Override - public ResultSet getResultSet() throws SQLException { - FilterChainImpl chain = createChain(); - ResultSet value = chain.statement_getResultSet(this); - recycleFilterChain(chain); - return value; - } - - @Override - public int getResultSetConcurrency() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getResultSetConcurrency(this); - recycleFilterChain(chain); - return value; - } - - @Override - public int getResultSetHoldability() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getResultSetHoldability(this); - recycleFilterChain(chain); - return value; - } - - @Override - public int getResultSetType() throws SQLException { - FilterChainImpl chain = createChain(); - int value = chain.statement_getResultSetType(this); - recycleFilterChain(chain); - return value; - } - - // bug fixed for oracle - @Override - public int getUpdateCount() throws SQLException { - if (updateCount == null) { - FilterChainImpl chain = createChain(); - updateCount = chain.statement_getUpdateCount(this); - recycleFilterChain(chain); - } - return updateCount; - } - - @Override - public SQLWarning getWarnings() throws SQLException { - FilterChainImpl chain = createChain(); - SQLWarning value = chain.statement_getWarnings(this); - recycleFilterChain(chain); - return value; - } - - @Override - public boolean isClosed() throws SQLException { - FilterChainImpl chain = createChain(); - boolean value = chain.statement_isClosed(this); - recycleFilterChain(chain); - return value; - } - - @Override - public boolean isPoolable() throws SQLException { - FilterChainImpl chain = createChain(); - boolean value = chain.statement_isPoolable(this); - recycleFilterChain(chain); - return value; - } - - @Override - public void setCursorName(String name) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setCursorName(this, name); - recycleFilterChain(chain); - } - - @Override - public void setEscapeProcessing(boolean enable) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setEscapeProcessing(this, enable); - recycleFilterChain(chain); - } - - @Override - public void setFetchDirection(int direction) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setFetchDirection(this, direction); - recycleFilterChain(chain); - } - - @Override - public void setFetchSize(int rows) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setFetchSize(this, rows); - recycleFilterChain(chain); - } - - @Override - public void setMaxFieldSize(int max) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setMaxFieldSize(this, max); - recycleFilterChain(chain); - } - - @Override - public void setMaxRows(int max) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setMaxRows(this, max); - recycleFilterChain(chain); - } - - @Override - public void setPoolable(boolean poolable) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setPoolable(this, poolable); - recycleFilterChain(chain); - } - - @Override - public void setQueryTimeout(int seconds) throws SQLException { - FilterChainImpl chain = createChain(); - chain.statement_setQueryTimeout(this, seconds); - recycleFilterChain(chain); - } - - @Override - public List getBatchSqlList() { - if (batchSqlList == null) { - batchSqlList = new ArrayList(); - } - - return batchSqlList; - } - - @Override - public String getBatchSql() { - List sqlList = getBatchSqlList(); - StringBuffer buf = new StringBuffer(); - for (String item : sqlList) { - if (buf.length() > 0) { - buf.append("\n;\n"); - } - buf.append(item); - } - return buf.toString(); - } - - public String getLastExecuteSql() { - return lastExecuteSql; - } - - public void closeOnCompletion() throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - public boolean isCloseOnCompletion() throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - - @Override - public Map getParameters() { - return Collections.emptyMap(); - } - - public JdbcSqlStat getSqlStat() { - return sqlStat; - } - - public void setSqlStat(JdbcSqlStat sqlStat) { - this.sqlStat = sqlStat; - } - - public long getLastExecuteTimeNano() { - return lastExecuteTimeNano; - } - - public void setLastExecuteTimeNano(long lastExecuteTimeNano) { - this.lastExecuteTimeNano = lastExecuteTimeNano; - } - - public void setLastExecuteTimeNano() { - if (this.lastExecuteTimeNano <= 0 && this.lastExecuteStartNano > 0) { - this.lastExecuteTimeNano = System.nanoTime() - this.lastExecuteStartNano; - } - } - - public long getLastExecuteStartNano() { - return lastExecuteStartNano; - } - - public void setLastExecuteStartNano(long lastExecuteStartNano) { - this.lastExecuteStartNano = lastExecuteStartNano; - this.lastExecuteTimeNano = -1L; - } - - public void setLastExecuteStartNano() { - if (lastExecuteStartNano <= 0) { - setLastExecuteStartNano(System.nanoTime()); - } - } - - public StatementExecuteType getLastExecuteType() { - return lastExecuteType; - } - - public boolean isFirstResultSet() { - return firstResultSet; - } - - @SuppressWarnings("unchecked") - public T unwrap(Class iface) throws SQLException { - if (iface == StatementProxy.class) { - return (T) this; - } - - return super.unwrap(iface); - } - - public boolean isWrapperFor(Class iface) throws SQLException { - if (iface == StatementProxy.class) { - return true; - } - - return super.isWrapperFor(iface); - } -} +/* + * 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.proxy.jdbc; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.Statement; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import com.alibaba.druid.filter.FilterChainImpl; +import com.alibaba.druid.stat.JdbcSqlStat; + +/** + * @author wenshao + */ +public class StatementProxyImpl extends WrapperProxyImpl implements StatementProxy { + + private final ConnectionProxy connection; + private final Statement statement; + + protected String lastExecuteSql; + protected long lastExecuteStartNano; + protected long lastExecuteTimeNano; + + protected JdbcSqlStat sqlStat; + protected boolean firstResultSet; + + protected ArrayList batchSqlList; + + protected StatementExecuteType lastExecuteType; + + protected Integer updateCount = null; + + private FilterChainImpl filterChain = null; + + public StatementProxyImpl(ConnectionProxy connection, Statement statement, long id){ + super(statement, id); + this.connection = connection; + this.statement = statement; + } + + public ConnectionProxy getConnectionProxy() { + return connection; + } + + public Statement getRawObject() { + return this.statement; + } + + public FilterChainImpl createChain() { + FilterChainImpl chain = this.filterChain; + if (chain == null) { + chain = new FilterChainImpl(this.getConnectionProxy().getDirectDataSource()); + } else { + this.filterChain = null; + } + + return chain; + } + + public void recycleFilterChain(FilterChainImpl chain) { + chain.reset(); + this.filterChain = chain; + } + + @Override + public void addBatch(String sql) throws SQLException { + if (batchSqlList == null) { + batchSqlList = new ArrayList(); + } + + createChain().statement_addBatch(this, sql); + batchSqlList.add(sql); + } + + @Override + public void cancel() throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_cancel(this); + recycleFilterChain(chain); + } + + @Override + public void clearBatch() throws SQLException { + if (batchSqlList == null) { + batchSqlList = new ArrayList(); + } + + FilterChainImpl chain = createChain(); + chain.statement_clearBatch(this); + recycleFilterChain(chain); + batchSqlList.clear(); + } + + @Override + public void clearWarnings() throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_clearWarnings(this); + recycleFilterChain(chain); + } + + @Override + public void close() throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_close(this); + recycleFilterChain(chain); + } + + @Override + public boolean execute(String sql) throws SQLException { + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.Execute; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + firstResultSet = chain.statement_execute(this, sql); + recycleFilterChain(chain); + return firstResultSet; + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.Execute; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + firstResultSet = chain.statement_execute(this, sql, autoGeneratedKeys); + recycleFilterChain(chain); + return firstResultSet; + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.Execute; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + firstResultSet = chain.statement_execute(this, sql, columnIndexes); + recycleFilterChain(chain); + return firstResultSet; + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.Execute; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + firstResultSet = chain.statement_execute(this, sql, columnNames); + recycleFilterChain(chain); + return firstResultSet; + } + + @Override + public int[] executeBatch() throws SQLException { + firstResultSet = false; + lastExecuteType = StatementExecuteType.ExecuteBatch; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + int[] updateCounts = chain.statement_executeBatch(this); + recycleFilterChain(chain); + if (updateCounts != null && updateCounts.length == 1) { + updateCount = updateCounts[0]; + } + + return updateCounts; + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + firstResultSet = true; + updateCount = null; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.ExecuteQuery; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + ResultSet resultSet = chain.statement_executeQuery(this, sql); + recycleFilterChain(chain); + return resultSet; + } + + @Override + public int executeUpdate(String sql) throws SQLException { + firstResultSet = false; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.ExecuteUpdate; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + updateCount = chain.statement_executeUpdate(this, sql); + recycleFilterChain(chain); + return updateCount; + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + firstResultSet = false; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.ExecuteUpdate; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + updateCount = chain.statement_executeUpdate(this, sql, autoGeneratedKeys); + recycleFilterChain(chain); + return updateCount; + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + firstResultSet = false; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.ExecuteUpdate; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + updateCount = chain.statement_executeUpdate(this, sql, columnIndexes); + recycleFilterChain(chain); + return updateCount; + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + firstResultSet = false; + lastExecuteSql = sql; + lastExecuteType = StatementExecuteType.ExecuteUpdate; + lastExecuteStartNano = -1L; + lastExecuteTimeNano = -1L; + + FilterChainImpl chain = createChain(); + updateCount = chain.statement_executeUpdate(this, sql, columnNames); + recycleFilterChain(chain); + return updateCount; + } + + @Override + public Connection getConnection() throws SQLException { + FilterChainImpl chain = createChain(); + Connection conn = chain.statement_getConnection(this); + recycleFilterChain(chain); + return conn; + } + + @Override + public int getFetchDirection() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getFetchDirection(this); + recycleFilterChain(chain); + return value; + } + + @Override + public int getFetchSize() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getFetchSize(this); + recycleFilterChain(chain); + return value; + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + FilterChainImpl chain = createChain(); + ResultSet value = chain.statement_getGeneratedKeys(this); + recycleFilterChain(chain); + return value; + } + + @Override + public int getMaxFieldSize() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getMaxFieldSize(this); + recycleFilterChain(chain); + return value; + } + + @Override + public int getMaxRows() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getMaxRows(this); + recycleFilterChain(chain); + return value; + } + + @Override + public boolean getMoreResults() throws SQLException { + updateCount = null; + FilterChainImpl chain = createChain(); + boolean value = chain.statement_getMoreResults(this); + recycleFilterChain(chain); + return value; + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + updateCount = null; + FilterChainImpl chain = createChain(); + boolean value = chain.statement_getMoreResults(this, current); + recycleFilterChain(chain); + return value; + } + + @Override + public int getQueryTimeout() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getQueryTimeout(this); + recycleFilterChain(chain); + return value; + } + + @Override + public ResultSet getResultSet() throws SQLException { + FilterChainImpl chain = createChain(); + ResultSet value = chain.statement_getResultSet(this); + recycleFilterChain(chain); + return value; + } + + @Override + public int getResultSetConcurrency() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getResultSetConcurrency(this); + recycleFilterChain(chain); + return value; + } + + @Override + public int getResultSetHoldability() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getResultSetHoldability(this); + recycleFilterChain(chain); + return value; + } + + @Override + public int getResultSetType() throws SQLException { + FilterChainImpl chain = createChain(); + int value = chain.statement_getResultSetType(this); + recycleFilterChain(chain); + return value; + } + + // bug fixed for oracle + @Override + public int getUpdateCount() throws SQLException { + if (updateCount == null) { + FilterChainImpl chain = createChain(); + updateCount = chain.statement_getUpdateCount(this); + recycleFilterChain(chain); + } + return updateCount; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + FilterChainImpl chain = createChain(); + SQLWarning value = chain.statement_getWarnings(this); + recycleFilterChain(chain); + return value; + } + + @Override + public boolean isClosed() throws SQLException { + FilterChainImpl chain = createChain(); + boolean value = chain.statement_isClosed(this); + recycleFilterChain(chain); + return value; + } + + @Override + public boolean isPoolable() throws SQLException { + FilterChainImpl chain = createChain(); + boolean value = chain.statement_isPoolable(this); + recycleFilterChain(chain); + return value; + } + + @Override + public void setCursorName(String name) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setCursorName(this, name); + recycleFilterChain(chain); + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setEscapeProcessing(this, enable); + recycleFilterChain(chain); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setFetchDirection(this, direction); + recycleFilterChain(chain); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setFetchSize(this, rows); + recycleFilterChain(chain); + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setMaxFieldSize(this, max); + recycleFilterChain(chain); + } + + @Override + public void setMaxRows(int max) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setMaxRows(this, max); + recycleFilterChain(chain); + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setPoolable(this, poolable); + recycleFilterChain(chain); + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + FilterChainImpl chain = createChain(); + chain.statement_setQueryTimeout(this, seconds); + recycleFilterChain(chain); + } + + @Override + public List getBatchSqlList() { + if (batchSqlList == null) { + batchSqlList = new ArrayList(); + } + + return batchSqlList; + } + + @Override + public String getBatchSql() { + List sqlList = getBatchSqlList(); + StringBuffer buf = new StringBuffer(); + for (String item : sqlList) { + if (buf.length() > 0) { + buf.append("\n;\n"); + } + buf.append(item); + } + return buf.toString(); + } + + public String getLastExecuteSql() { + return lastExecuteSql; + } + + public void closeOnCompletion() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + public boolean isCloseOnCompletion() throws SQLException { + throw new SQLFeatureNotSupportedException(); + } + + @Override + public Map getParameters() { + return Collections.emptyMap(); + } + + public JdbcSqlStat getSqlStat() { + return sqlStat; + } + + public void setSqlStat(JdbcSqlStat sqlStat) { + this.sqlStat = sqlStat; + } + + public long getLastExecuteTimeNano() { + return lastExecuteTimeNano; + } + + public void setLastExecuteTimeNano(long lastExecuteTimeNano) { + this.lastExecuteTimeNano = lastExecuteTimeNano; + } + + public void setLastExecuteTimeNano() { + if (this.lastExecuteTimeNano <= 0 && this.lastExecuteStartNano > 0) { + this.lastExecuteTimeNano = System.nanoTime() - this.lastExecuteStartNano; + } + } + + public long getLastExecuteStartNano() { + return lastExecuteStartNano; + } + + public void setLastExecuteStartNano(long lastExecuteStartNano) { + this.lastExecuteStartNano = lastExecuteStartNano; + this.lastExecuteTimeNano = -1L; + } + + public void setLastExecuteStartNano() { + if (lastExecuteStartNano <= 0) { + setLastExecuteStartNano(System.nanoTime()); + } + } + + public StatementExecuteType getLastExecuteType() { + return lastExecuteType; + } + + public boolean isFirstResultSet() { + return firstResultSet; + } + + @SuppressWarnings("unchecked") + public T unwrap(Class iface) throws SQLException { + if (iface == StatementProxy.class) { + return (T) this; + } + + return super.unwrap(iface); + } + + public boolean isWrapperFor(Class iface) throws SQLException { + if (iface == StatementProxy.class) { + return true; + } + + return super.isWrapperFor(iface); + } + + @Override + public int getParametersSize() { + return 0; + } + + @Override + public JdbcParameter getParameter(int i) { + return null; + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/pool/PreparedStatementProxyImplTest.java b/src/test/java/com/alibaba/druid/bvt/pool/PreparedStatementProxyImplTest.java index 5e0da955d0..2aa429e7df 100644 --- a/src/test/java/com/alibaba/druid/bvt/pool/PreparedStatementProxyImplTest.java +++ b/src/test/java/com/alibaba/druid/bvt/pool/PreparedStatementProxyImplTest.java @@ -37,40 +37,40 @@ public class PreparedStatementProxyImplTest extends TestCase { stmt.setObject(3, (int) 1); stmt.setObject(4, (long) 1); stmt.setObject(5, (float) 1); - + stmt.setObject(6, (double) 1); stmt.setObject(7, new BigDecimal(1)); stmt.setObject(8, true); stmt.setObject(9, "xxx"); stmt.setObject(10, new java.sql.Date(System.currentTimeMillis())); - + stmt.setObject(11, new java.util.Date(System.currentTimeMillis())); stmt.setObject(12, new java.sql.Timestamp(System.currentTimeMillis())); stmt.setObject(13, new java.sql.Time(System.currentTimeMillis())); - + stmt.execute(); - + PreparedStatementProxy stmtProxy = stmt.unwrap(PreparedStatementProxy.class); Assert.assertNotNull(stmtProxy); - - Assert.assertEquals(Types.TINYINT, stmtProxy.getParameters().get(1).getSqlType()); - Assert.assertEquals(Types.SMALLINT, stmtProxy.getParameters().get(2).getSqlType()); - Assert.assertEquals(Types.INTEGER, stmtProxy.getParameters().get(3).getSqlType()); - Assert.assertEquals(Types.BIGINT, stmtProxy.getParameters().get(4).getSqlType()); - Assert.assertEquals(Types.FLOAT, stmtProxy.getParameters().get(5).getSqlType()); - - Assert.assertEquals(Types.DOUBLE, stmtProxy.getParameters().get(6).getSqlType()); - Assert.assertEquals(Types.DECIMAL, stmtProxy.getParameters().get(7).getSqlType()); - Assert.assertEquals(Types.BOOLEAN, stmtProxy.getParameters().get(8).getSqlType()); - Assert.assertEquals(Types.VARCHAR, stmtProxy.getParameters().get(9).getSqlType()); - Assert.assertEquals(Types.DATE, stmtProxy.getParameters().get(10).getSqlType()); - Assert.assertEquals(Types.DATE, stmtProxy.getParameters().get(11).getSqlType()); - Assert.assertEquals(Types.TIMESTAMP, stmtProxy.getParameters().get(12).getSqlType()); - Assert.assertEquals(Types.TIME, stmtProxy.getParameters().get(13).getSqlType()); - + Assert.assertEquals(Types.TINYINT, stmtProxy.getParameter(0).getSqlType()); + Assert.assertEquals(Types.SMALLINT, stmtProxy.getParameter(1).getSqlType()); + Assert.assertEquals(Types.INTEGER, stmtProxy.getParameter(2).getSqlType()); + Assert.assertEquals(Types.BIGINT, stmtProxy.getParameter(3).getSqlType()); + Assert.assertEquals(Types.FLOAT, stmtProxy.getParameter(4).getSqlType()); + + Assert.assertEquals(Types.DOUBLE, stmtProxy.getParameter(5).getSqlType()); + Assert.assertEquals(Types.DECIMAL, stmtProxy.getParameter(6).getSqlType()); + Assert.assertEquals(Types.BOOLEAN, stmtProxy.getParameter(7).getSqlType()); + Assert.assertEquals(Types.VARCHAR, stmtProxy.getParameter(8).getSqlType()); + Assert.assertEquals(Types.DATE, stmtProxy.getParameter(9).getSqlType()); + + Assert.assertEquals(Types.DATE, stmtProxy.getParameter(10).getSqlType()); + Assert.assertEquals(Types.TIMESTAMP, stmtProxy.getParameter(11).getSqlType()); + Assert.assertEquals(Types.TIME, stmtProxy.getParameter(12).getSqlType()); + stmt.close(); - + conn.close(); } }