*/
package org.sonar.core.persistence.profiling;
+import org.apache.commons.lang.StringUtils;
+import com.google.common.collect.Lists;
import org.sonar.core.profiling.StopWatch;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
+import java.util.List;
class ProfilingPreparedStatementHandler implements InvocationHandler {
+ private static final String PARAM_PREFIX = "<";
+ private static final String PARAM_SUFFIX = ">";
+ private static final String PARAM_SEPARATOR = ", ";
private static final SqlProfiling PROFILING = new SqlProfiling();
+
private final PreparedStatement statement;
+ private final List<Object> arguments;
private final String sql;
ProfilingPreparedStatementHandler(PreparedStatement statement, String sql) {
this.statement = statement;
this.sql = sql;
+ this.arguments = Lists.newArrayList();
+ for (int argCount = 0; argCount < StringUtils.countMatches(sql, "?"); argCount ++) {
+ arguments.add("!");
+ }
}
@Override
if (method.getName().startsWith("execute")) {
StopWatch watch = PROFILING.start();
Object result = method.invoke(statement, args);
- PROFILING.stop(watch, sql);
+ StringBuilder sqlBuilder = new StringBuilder().append(sql);
+ if (!arguments.isEmpty()) {
+ sqlBuilder.append(" - parameters are: ");
+ for (Object arg: arguments) {
+ sqlBuilder.append(PARAM_PREFIX).append(arg).append(PARAM_SUFFIX).append(PARAM_SEPARATOR);
+ }
+ }
+ PROFILING.stop(watch, StringUtils.removeEnd(sqlBuilder.toString(), PARAM_SEPARATOR));
return result;
+ } else if (method.getName().startsWith("set") && args.length > 1) {
+ arguments.set((Integer) args[0] - 1, args[1]);
+ return method.invoke(statement, args);
} else {
return method.invoke(statement, args);
}
import org.sonar.api.config.Settings;
import org.sonar.core.profiling.Profiling;
+import java.io.ByteArrayInputStream;
import java.sql.Connection;
+import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.Statement;
+import java.sql.Timestamp;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
when(originDataSource.getConnection()).thenReturn(connection);
String sql = "select 'polop' from dual;";
+ String sqlWithParams = "insert into polop (col1, col2, col3, col4) values (?, ?, ?, ?, ?);";
+ int param1 = 42;
+ String param2 = "plouf";
+ Date param3 = new Date(System.currentTimeMillis());
+ Timestamp param4 = new Timestamp(System.currentTimeMillis());
+ byte[] param5 = "blob".getBytes("UTF-8");
PreparedStatement preparedStatement = mock(PreparedStatement.class);
- when(connection.prepareStatement(sql)).thenReturn(preparedStatement);
+ when(connection.prepareStatement(sqlWithParams)).thenReturn(preparedStatement);
when(preparedStatement.execute()).thenReturn(true);
Statement statement = mock(Statement.class);
assertThat(resultDataSource).isInstanceOf(ProfilingDataSource.class);
assertThat(resultDataSource.getUrl()).isNull();
assertThat(resultDataSource.getConnection().getClientInfo()).isNull();
- PreparedStatement preparedStatementProxy = resultDataSource.getConnection().prepareStatement(sql);
+ PreparedStatement preparedStatementProxy = resultDataSource.getConnection().prepareStatement(sqlWithParams);
+ preparedStatementProxy.setInt(1, param1);
+ preparedStatementProxy.setString(2, param2);
+ preparedStatementProxy.setDate(3, param3);
+ preparedStatementProxy.setTimestamp(4, param4);
+ preparedStatementProxy.setBlob(5, new ByteArrayInputStream(param5));
assertThat(preparedStatementProxy.getConnection()).isNull();
assertThat(preparedStatementProxy.execute()).isTrue();
final Statement statementProxy = resultDataSource.getConnection().createStatement();
assertThat(statementProxy.execute(sql)).isTrue();
assertThat(appender.list).hasSize(2);
- for (ILoggingEvent event: appender.list) {
- assertThat(event.getLevel()).isEqualTo(Level.INFO);
- assertThat(event.getFormattedMessage()).contains(sql);
- }
+ assertThat(appender.list.get(0).getLevel()).isEqualTo(Level.INFO);
+ assertThat(appender.list.get(0).getFormattedMessage()).contains(sqlWithParams).contains(" - parameters are: ").contains(Integer.toString(param1)).contains(param2);
+ assertThat(appender.list.get(1).getLevel()).isEqualTo(Level.INFO);
+ assertThat(appender.list.get(1).getFormattedMessage()).contains(sql);
}
}