]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4925 Intercept parameters to format SQL string
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 6 Feb 2014 10:10:30 +0000 (11:10 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 6 Feb 2014 13:58:56 +0000 (14:58 +0100)
sonar-core/src/main/java/org/sonar/core/persistence/profiling/ProfilingPreparedStatementHandler.java
sonar-core/src/main/java/org/sonar/core/persistence/profiling/ProfilingStatementHandler.java
sonar-core/src/test/java/org/sonar/core/persistence/profiling/PersistenceProfilingTest.java

index 8785e517b4cd198b7872214dabd237c636461627..8550e7bfe197059da3e91b8a8ca6dd4482a63565 100644 (file)
  */
 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
@@ -41,8 +53,18 @@ class ProfilingPreparedStatementHandler implements InvocationHandler {
     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);
     }
index 0ba978796a6a37e683a67172c7bb28d77295e13f..89d91c0db816820a39e8a862ca0fa46c0eec8086 100644 (file)
@@ -28,6 +28,7 @@ import java.sql.Statement;
 class ProfilingStatementHandler implements InvocationHandler {
 
   private static final SqlProfiling PROFILING = new SqlProfiling();
+
   private final Statement statement;
 
   ProfilingStatementHandler(Statement statement) {
index b21a3a2a41b3f33026e21f52a48be7841eae95ea..9faec0790e3295a1e5926e7121a3b96342b247f9 100644 (file)
@@ -30,9 +30,12 @@ import org.slf4j.LoggerFactory;
 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;
@@ -60,9 +63,15 @@ public class PersistenceProfilingTest {
     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);
@@ -77,7 +86,12 @@ public class PersistenceProfilingTest {
     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();
@@ -85,9 +99,9 @@ public class PersistenceProfilingTest {
     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);
   }
 }