]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6044 Stop storing distribution of issue-related measures by rule
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 3 Feb 2015 11:20:09 +0000 (12:20 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Wed, 4 Feb 2015 14:12:54 +0000 (15:12 +0100)
12 files changed:
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecorator.java
plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SeverityUtils.java
plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/CountUnresolvedIssuesDecoratorTest.java
server/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java
server/sonar-server/src/main/java/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssues.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest.java [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/execute.xml [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/execute_nothing.xml [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/schema.sql [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/774_remove_rule_measures_on_issues.rb [new file with mode: 0644]
sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql

index d775ba8ec4c1a5a8937d45216c79c92d85e07f62..1b2758732f977425e0dc2170d228c40ad75ef566 100644 (file)
@@ -30,14 +30,16 @@ import org.sonar.api.measures.*;
 import org.sonar.api.resources.Project;
 import org.sonar.api.resources.Resource;
 import org.sonar.api.resources.ResourceUtils;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rules.RulePriority;
+import org.sonar.api.rule.Severity;
 import org.sonar.batch.components.Period;
 import org.sonar.batch.components.TimeMachineConfiguration;
 
 import javax.annotation.Nullable;
 
-import java.util.*;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
 
 /**
  * Computes metrics related to number of issues.
@@ -88,18 +90,15 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
       Collection<Issue> issues = issuable.issues();
       boolean shouldSaveNewMetrics = shouldSaveNewMetrics(context);
 
-      Multiset<RulePriority> severityBag = HashMultiset.create();
-      Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity = Maps.newHashMap();
-      ListMultimap<RulePriority, Issue> issuesPerSeverity = ArrayListMultimap.create();
+      Multiset<String> severityBag = HashMultiset.create();
+      ListMultimap<String, Issue> issuesPerSeverity = ArrayListMultimap.create();
       int countOpen = 0;
       int countReopened = 0;
       int countConfirmed = 0;
 
       for (Issue issue : issues) {
-        severityBag.add(RulePriority.valueOf(issue.severity()));
-        Multiset<RuleKey> rulesBag = initRules(rulesPerSeverity, RulePriority.valueOf(issue.severity()));
-        rulesBag.add(issue.ruleKey());
-        issuesPerSeverity.put(RulePriority.valueOf(issue.severity()), issue);
+        severityBag.add(issue.severity());
+        issuesPerSeverity.put(issue.severity(), issue);
 
         if (Issue.STATUS_OPEN.equals(issue.status())) {
           countOpen++;
@@ -110,11 +109,9 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
         }
       }
 
-      for (RulePriority ruleSeverity : RulePriority.values()) {
-        saveIssuesForSeverity(context, ruleSeverity, severityBag);
-        saveIssuesPerRules(context, ruleSeverity, rulesPerSeverity);
-        saveNewIssuesForSeverity(context, ruleSeverity, issuesPerSeverity, shouldSaveNewMetrics);
-        saveNewIssuesPerRule(context, ruleSeverity, issues, shouldSaveNewMetrics);
+      for (String severity : Severity.ALL) {
+        saveIssuesForSeverity(context, severity, severityBag);
+        saveNewIssuesForSeverity(context, severity, issuesPerSeverity, shouldSaveNewMetrics);
       }
 
       saveTotalIssues(context, issues);
@@ -141,16 +138,16 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
     }
   }
 
-  private void saveIssuesForSeverity(DecoratorContext context, RulePriority ruleSeverity, Multiset<RulePriority> severitiesBag) {
-    Metric metric = SeverityUtils.severityToIssueMetric(ruleSeverity);
+  private void saveIssuesForSeverity(DecoratorContext context, String severity, Multiset<String> severitiesBag) {
+    Metric metric = SeverityUtils.severityToIssueMetric(severity);
     if (context.getMeasure(metric) == null) {
       Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.metric(metric));
-      int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(ruleSeverity);
+      int sum = MeasureUtils.sum(true, children).intValue() + severitiesBag.count(severity);
       context.saveMeasure(metric, (double) sum);
     }
   }
 
-  private void saveNewIssuesForSeverity(DecoratorContext context, RulePriority severity, ListMultimap<RulePriority, Issue> issuesPerSeverities, boolean shouldSaveNewMetrics) {
+  private void saveNewIssuesForSeverity(DecoratorContext context, String severity, ListMultimap<String, Issue> issuesPerSeverities, boolean shouldSaveNewMetrics) {
     if (shouldSaveNewMetrics) {
       Metric metric = SeverityUtils.severityToNewMetricIssue(severity);
       Measure measure = new Measure(metric);
@@ -158,66 +155,6 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
     }
   }
 
-  private void saveIssuesPerRules(DecoratorContext context, RulePriority severity, Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity) {
-    Metric metric = SeverityUtils.severityToIssueMetric(severity);
-
-    Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rules(metric));
-    for (Measure child : children) {
-      RuleMeasure childRuleMeasure = (RuleMeasure) child;
-      RuleKey ruleKey = childRuleMeasure.ruleKey();
-      if (ruleKey != null && MeasureUtils.hasValue(childRuleMeasure)) {
-        Multiset<RuleKey> rulesBag = initRules(rulesPerSeverity, severity);
-        rulesBag.add(ruleKey, childRuleMeasure.getIntValue());
-      }
-    }
-
-    Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
-    if (rulesBag != null) {
-      for (Multiset.Entry<RuleKey> entry : rulesBag.entrySet()) {
-        RuleMeasure measure = RuleMeasure.createForRule(metric, entry.getElement(), (double) entry.getCount());
-        measure.setSeverity(severity);
-        context.saveMeasure(measure);
-      }
-    }
-  }
-
-  private void saveNewIssuesPerRule(DecoratorContext context, RulePriority severity, Collection<Issue> issues, boolean shouldSaveNewMetrics) {
-    if (shouldSaveNewMetrics) {
-      Metric metric = SeverityUtils.severityToNewMetricIssue(severity);
-      ListMultimap<RuleKey, Measure> childMeasuresPerRuleKeys = ArrayListMultimap.create();
-      ListMultimap<RuleKey, Issue> issuesPerRuleKeys = ArrayListMultimap.create();
-      Set<RuleKey> ruleKeys = Sets.newHashSet();
-
-      Collection<Measure> children = context.getChildrenMeasures(MeasuresFilters.rules(metric));
-      for (Measure child : children) {
-        RuleMeasure childRuleMeasure = (RuleMeasure) child;
-        RuleKey ruleKey = childRuleMeasure.ruleKey();
-        if (ruleKey != null) {
-          childMeasuresPerRuleKeys.put(ruleKey, childRuleMeasure);
-          ruleKeys.add(ruleKey);
-        }
-      }
-
-      for (Issue issue : issues) {
-        if (RulePriority.valueOf(issue.severity()).equals(severity)) {
-          ruleKeys.add(issue.ruleKey());
-          issuesPerRuleKeys.put(issue.ruleKey(), issue);
-        }
-      }
-
-      for (RuleKey ruleKey : ruleKeys) {
-        RuleMeasure measure = RuleMeasure.createForRule(metric, ruleKey, null);
-        measure.setSeverity(severity);
-        for (Period period : timeMachineConfiguration.periods()) {
-          int variationIndex = period.getIndex();
-          double sum = MeasureUtils.sumOnVariation(true, variationIndex, childMeasuresPerRuleKeys.get(ruleKey)) + countIssues(issuesPerRuleKeys.get(ruleKey), period);
-          measure.setVariation(variationIndex, sum);
-        }
-        context.saveMeasure(measure);
-      }
-    }
-  }
-
   private void saveNewIssues(DecoratorContext context, Measure measure, Collection<Issue> issues) {
     for (Period period : timeMachineConfiguration.periods()) {
       int variationIndex = period.getIndex();
@@ -240,15 +177,6 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
     return sum;
   }
 
-  private Multiset<RuleKey> initRules(Map<RulePriority, Multiset<RuleKey>> rulesPerSeverity, RulePriority severity) {
-    Multiset<RuleKey> rulesBag = rulesPerSeverity.get(severity);
-    if (rulesBag == null) {
-      rulesBag = HashMultiset.create();
-      rulesPerSeverity.put(severity, rulesBag);
-    }
-    return rulesBag;
-  }
-
   private int countIssues(Collection<Issue> issues, Period period) {
     // SONAR-3647 Use real snapshot date and not target date in order to stay consistent with other measure variations
     Date datePlusOneSecond = period.getDate() != null ? DateUtils.addSeconds(period.getDate(), 1) : null;
@@ -257,9 +185,6 @@ public class CountUnresolvedIssuesDecorator implements Decorator {
 
   @VisibleForTesting
   int countIssuesAfterDate(Collection<Issue> issues, @Nullable Date date) {
-    if (issues == null) {
-      return 0;
-    }
     int count = 0;
     for (Issue issue : issues) {
       if (isAfter(issue, date)) {
index e1a1d5ba19c4bbb21effbbd1c2684eae79b73088..ed6b9551e16d908515b8da009ddb9cb910a24792 100644 (file)
@@ -21,46 +21,44 @@ package org.sonar.plugins.core.issue;
 
 import org.sonar.api.measures.CoreMetrics;
 import org.sonar.api.measures.Metric;
-import org.sonar.api.rules.RulePriority;
+import org.sonar.api.rule.Severity;
 
 final class SeverityUtils {
   private SeverityUtils() {
     // only static methods
   }
 
-  static Metric severityToIssueMetric(RulePriority severity) {
-    Metric metric;
-    if (severity.equals(RulePriority.BLOCKER)) {
-      metric = CoreMetrics.BLOCKER_VIOLATIONS;
-    } else if (severity.equals(RulePriority.CRITICAL)) {
-      metric = CoreMetrics.CRITICAL_VIOLATIONS;
-    } else if (severity.equals(RulePriority.MAJOR)) {
-      metric = CoreMetrics.MAJOR_VIOLATIONS;
-    } else if (severity.equals(RulePriority.MINOR)) {
-      metric = CoreMetrics.MINOR_VIOLATIONS;
-    } else if (severity.equals(RulePriority.INFO)) {
-      metric = CoreMetrics.INFO_VIOLATIONS;
-    } else {
-      throw new IllegalArgumentException("Unsupported severity: " + severity);
+  static Metric severityToIssueMetric(String severity) {
+    switch (severity) {
+      case Severity.BLOCKER:
+        return CoreMetrics.BLOCKER_VIOLATIONS;
+      case Severity.CRITICAL:
+        return CoreMetrics.CRITICAL_VIOLATIONS;
+      case Severity.MAJOR:
+        return CoreMetrics.MAJOR_VIOLATIONS;
+      case Severity.MINOR:
+        return CoreMetrics.MINOR_VIOLATIONS;
+      case Severity.INFO:
+        return CoreMetrics.INFO_VIOLATIONS;
+      default:
+        throw new IllegalArgumentException("Unsupported severity: " + severity);
     }
-    return metric;
   }
 
-  static Metric severityToNewMetricIssue(RulePriority severity) {
-    Metric metric;
-    if (severity.equals(RulePriority.BLOCKER)) {
-      metric = CoreMetrics.NEW_BLOCKER_VIOLATIONS;
-    } else if (severity.equals(RulePriority.CRITICAL)) {
-      metric = CoreMetrics.NEW_CRITICAL_VIOLATIONS;
-    } else if (severity.equals(RulePriority.MAJOR)) {
-      metric = CoreMetrics.NEW_MAJOR_VIOLATIONS;
-    } else if (severity.equals(RulePriority.MINOR)) {
-      metric = CoreMetrics.NEW_MINOR_VIOLATIONS;
-    } else if (severity.equals(RulePriority.INFO)) {
-      metric = CoreMetrics.NEW_INFO_VIOLATIONS;
-    } else {
-      throw new IllegalArgumentException("Unsupported severity: " + severity);
+  static Metric severityToNewMetricIssue(String severity) {
+    switch (severity) {
+      case Severity.BLOCKER:
+        return CoreMetrics.NEW_BLOCKER_VIOLATIONS;
+      case Severity.CRITICAL:
+        return CoreMetrics.NEW_CRITICAL_VIOLATIONS;
+      case Severity.MAJOR:
+        return CoreMetrics.NEW_MAJOR_VIOLATIONS;
+      case Severity.MINOR:
+        return CoreMetrics.NEW_MINOR_VIOLATIONS;
+      case Severity.INFO:
+        return CoreMetrics.NEW_INFO_VIOLATIONS;
+      default:
+        throw new IllegalArgumentException("Unsupported severity: " + severity);
     }
-    return metric;
   }
 }
index be9b8ae586c1625c6b0848c48fa3493bb36413df..054f2b5f02fea97731aae9ec39e3a6ec908b79bf 100644 (file)
@@ -39,7 +39,6 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
 import org.sonar.api.rules.Rule;
 import org.sonar.api.rules.RulePriority;
-import org.sonar.api.test.IsRuleMeasure;
 import org.sonar.batch.components.Period;
 import org.sonar.batch.components.TimeMachineConfiguration;
 
@@ -185,40 +184,11 @@ public class CountUnresolvedIssuesDecoratorTest {
     verify(context).saveMeasure(CoreMetrics.INFO_VIOLATIONS, 0.0);
   }
 
-  @Test
-  public void should_count_issues_per_rule() {
-    List<Issue> issues = newArrayList();
-    issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
-    issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
-    issues.add(new DefaultIssue().setRuleKey(ruleA2.ruleKey()).setSeverity(RulePriority.MAJOR.name()));
-    when(issuable.issues()).thenReturn(issues);
-
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0)));
-    verify(context, never()).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA1, 0.0)));
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MAJOR_VIOLATIONS, ruleA2, 1.0)));
-  }
-
-  @Test
-  public void same_rule_should_have_different_severities() {
-    List<Issue> issues = newArrayList();
-    issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
-    issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.CRITICAL.name()));
-    issues.add(new DefaultIssue().setRuleKey(ruleA1.ruleKey()).setSeverity(RulePriority.MINOR.name()));
-    when(issuable.issues()).thenReturn(issues);
-
-    decorator.decorate(resource, context);
-
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.CRITICAL_VIOLATIONS, ruleA1, 2.0)));
-    verify(context).saveMeasure(argThat(new IsRuleMeasure(CoreMetrics.MINOR_VIOLATIONS, ruleA1, 1.0)));
-  }
-
   @Test
   public void should_count_issues_after_date() {
     List<Issue> issues = createIssuesForNewMetrics();
 
-    assertThat(decorator.countIssuesAfterDate(null, fiveDaysAgo)).isEqualTo(0);
+    assertThat(decorator.countIssuesAfterDate(Collections.<Issue>emptyList(), fiveDaysAgo)).isEqualTo(0);
     assertThat(decorator.countIssuesAfterDate(issues, fiveDaysAgo)).isEqualTo(1); // 1 rightNow
     assertThat(decorator.countIssuesAfterDate(issues, tenDaysAgo)).isEqualTo(3); // 1 rightNow + 2 fiveDaysAgo
     assertThat(decorator.countIssuesAfterDate(issues, sameSecond)).isEqualTo(0); // 0
@@ -251,18 +221,6 @@ public class CountUnresolvedIssuesDecoratorTest {
     verify(context).saveMeasure(argThat(new IsVariationMeasure(CoreMetrics.NEW_INFO_VIOLATIONS, 0.0, 0.0)));
   }
 
-  @Test
-  public void should_save_rule_new_issues() {
-    when(issuable.issues()).thenReturn(createIssuesForNewMetrics());
-
-    decorator.decorate(resource, context);
-
-    // remember : period1 is 5daysAgo, period2 is 10daysAgo
-    verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_CRITICAL_VIOLATIONS, ruleA1, 1.0, 1.0)));
-    verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MAJOR_VIOLATIONS, ruleA2, 0.0, 1.0)));
-    verify(context).saveMeasure(argThat(new IsVariationRuleMeasure(CoreMetrics.NEW_MINOR_VIOLATIONS, ruleB1, 0.0, 1.0)));
-  }
-
   @Test
   public void should_not_save_new_issues_if_measure_already_computed() {
     when(context.getMeasure(CoreMetrics.NEW_VIOLATIONS)).thenReturn(new Measure());
index f2cb0d801f11a57307fd4b849fe903d3deb0de7c..03703c13776de810864097d644f971276e674d24 100644 (file)
@@ -84,6 +84,7 @@ public interface DatabaseMigrations {
     FeedIssueChangesLongDates.class,
     FeedAnalysisReportsLongDates.class,
     UpdateProjectsModuleUuidPath.class,
-    FeedIssueComponentUuids.class
+    FeedIssueComponentUuids.class,
+    RemoveRuleMeasuresOnIssues.class
     );
 }
diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssues.java b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssues.java
new file mode 100644 (file)
index 0000000..cba9594
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.db.migrations.v51;
+
+import com.google.common.base.Joiner;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.BaseDataChange;
+import org.sonar.server.db.migrations.Select;
+import org.sonar.server.db.migrations.Upsert;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.List;
+
+public class RemoveRuleMeasuresOnIssues extends BaseDataChange {
+
+  public RemoveRuleMeasuresOnIssues(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    List<Long> metricIds = context
+      .prepareSelect("SELECT m.id FROM metrics m WHERE m.name IN ( " +
+        "'blocker_violations', 'critical_violations', 'major_violations', 'minor_violations', 'info_violations', " +
+        "'new_blocker_violations', 'new_critical_violations', 'new_major_violations', 'new_minor_violations', 'new_info_violations')")
+      .list(Select.LONG_READER);
+    if (!metricIds.isEmpty()) {
+      String sql = "DELETE FROM project_measures pm WHERE pm.metric_id IN (";
+      String[] parameters = new String[metricIds.size()];
+      Arrays.fill(parameters, "?");
+      sql += Joiner.on(",").join(parameters);
+      sql += ")";
+      Upsert delete = context.prepareUpsert(sql);
+      for (int index = 0; index < metricIds.size(); index++) {
+        delete.setLong(index + 1, metricIds.get(index));
+      }
+      delete.execute().commit();
+    }
+  }
+
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest.java b/server/sonar-server/src/test/java/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest.java
new file mode 100644 (file)
index 0000000..7cf7fb9
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+package org.sonar.server.db.migrations.v51;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.core.persistence.DbTester;
+import org.sonar.server.db.migrations.DatabaseMigration;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RemoveRuleMeasuresOnIssuesTest {
+
+  @ClassRule
+  public static DbTester db = new DbTester().schema(RemoveRuleMeasuresOnIssuesTest.class, "schema.sql");
+
+  DatabaseMigration migration;
+
+  @Before
+  public void setUp() throws Exception {
+    db.executeUpdateSql("TRUNCATE TABLE metrics");
+    db.executeUpdateSql("TRUNCATE TABLE project_measures");
+    migration = new RemoveRuleMeasuresOnIssues(db.database());
+  }
+
+  @Test
+  public void execute() throws Exception {
+    db.prepareDbUnit(getClass(), "execute.xml");
+
+    migration.execute();
+
+    assertThat(db.countRowsOfTable("project_measures")).isEqualTo(0);
+  }
+
+  @Test
+  public void execute_nothing() throws Exception {
+    db.prepareDbUnit(getClass(), "execute_nothing.xml");
+
+    migration.execute();
+
+    db.assertDbUnit(getClass(), "execute_nothing.xml", "project_measures");
+  }
+
+}
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/execute.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/execute.xml
new file mode 100644 (file)
index 0000000..15ba1a5
--- /dev/null
@@ -0,0 +1,25 @@
+<dataset>
+
+  <metrics id="1" name="blocker_violations"/>
+  <metrics id="2" name="critical_violations"/>
+  <metrics id="3" name="major_violations"/>
+  <metrics id="4" name="minor_violations"/>
+  <metrics id="5" name="info_violations"/>
+  <metrics id="6" name="new_blocker_violations"/>
+  <metrics id="7" name="new_critical_violations"/>
+  <metrics id="8" name="new_major_violations"/>
+  <metrics id="9" name="new_minor_violations"/>
+  <metrics id="10" name="new_info_violations"/>
+
+  <project_measures id="1" metric_id="1"/>
+  <project_measures id="2" metric_id="2"/>
+  <project_measures id="3" metric_id="3"/>
+  <project_measures id="4" metric_id="4"/>
+  <project_measures id="5" metric_id="5"/>
+  <project_measures id="6" metric_id="6"/>
+  <project_measures id="7" metric_id="7"/>
+  <project_measures id="8" metric_id="8"/>
+  <project_measures id="9" metric_id="9"/>
+  <project_measures id="10" metric_id="10"/>
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/execute_nothing.xml b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/execute_nothing.xml
new file mode 100644 (file)
index 0000000..331e7db
--- /dev/null
@@ -0,0 +1,18 @@
+<dataset>
+
+  <!-- These measures should not be removed -->
+
+  <metrics id="1" name="violations"/>
+  <metrics id="2" name="new_violations"/>
+
+  <project_measures id="1" metric_id="1"
+                    alert_status="[null]" alert_text="[null]" characteristic_id="[null]" description="[null]" measure_data="[null]" measure_date="[null]" person_id="[null]"
+                    project_id="[null]" rule_id="[null]" rule_priority="[null]" rules_category_id="[null]" snapshot_id="[null]" tendency="[null]" text_value="[null]" url="[null]"
+                    value="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+  <project_measures id="2" metric_id="2"
+                    alert_status="[null]" alert_text="[null]" characteristic_id="[null]" description="[null]" measure_data="[null]" measure_date="[null]" person_id="[null]"
+                    project_id="[null]" rule_id="[null]" rule_priority="[null]" rules_category_id="[null]" snapshot_id="[null]" tendency="[null]" text_value="[null]" url="[null]"
+                    value="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"/>
+
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/schema.sql b/server/sonar-server/src/test/resources/org/sonar/server/db/migrations/v51/RemoveRuleMeasuresOnIssuesTest/schema.sql
new file mode 100644 (file)
index 0000000..99d523f
--- /dev/null
@@ -0,0 +1,44 @@
+CREATE TABLE "PROJECT_MEASURES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "VALUE" DOUBLE,
+  "METRIC_ID" INTEGER NOT NULL,
+  "SNAPSHOT_ID" INTEGER,
+  "RULE_ID" INTEGER,
+  "RULES_CATEGORY_ID" INTEGER,
+  "TEXT_VALUE" VARCHAR(4000),
+  "TENDENCY" INTEGER,
+  "MEASURE_DATE" TIMESTAMP,
+  "PROJECT_ID" INTEGER,
+  "ALERT_STATUS" VARCHAR(5),
+  "ALERT_TEXT" VARCHAR(4000),
+  "URL" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(4000),
+  "RULE_PRIORITY" INTEGER,
+  "CHARACTERISTIC_ID" INTEGER,
+  "PERSON_ID" INTEGER,
+  "VARIATION_VALUE_1" DOUBLE,
+  "VARIATION_VALUE_2" DOUBLE,
+  "VARIATION_VALUE_3" DOUBLE,
+  "VARIATION_VALUE_4" DOUBLE,
+  "VARIATION_VALUE_5" DOUBLE,
+  "MEASURE_DATA" BINARY(167772150)
+);
+
+CREATE TABLE "METRICS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(64) NOT NULL,
+  "DESCRIPTION" VARCHAR(255),
+  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
+  "DOMAIN" VARCHAR(64),
+  "SHORT_NAME" VARCHAR(64),
+  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
+  "VAL_TYPE" VARCHAR(8),
+  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
+  "ENABLED" BOOLEAN DEFAULT TRUE,
+  "ORIGIN" VARCHAR(3),
+  "WORST_VALUE" DOUBLE,
+  "BEST_VALUE" DOUBLE,
+  "OPTIMIZED_BEST_VALUE" BOOLEAN,
+  "HIDDEN" BOOLEAN,
+  "DELETE_HISTORICAL_DATA" BOOLEAN
+);
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/774_remove_rule_measures_on_issues.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/774_remove_rule_measures_on_issues.rb
new file mode 100644 (file)
index 0000000..4d6b179
--- /dev/null
@@ -0,0 +1,30 @@
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+#
+
+#
+# SonarQube 5.1
+# SONAR-6044
+#
+class RemoveRuleMeasuresOnIssues < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.server.db.migrations.v51.RemoveRuleMeasuresOnIssues')
+  end
+end
index fbb2b1be49f8487f77397d1a4a1a6093a7a00147..e4ae4e1364dd0d8b77317003a6c97ad41daa6e99 100644 (file)
@@ -33,7 +33,7 @@ import java.util.List;
  */
 public class DatabaseVersion implements BatchComponent, ServerComponent {
 
-  public static final int LAST_VERSION = 773;
+  public static final int LAST_VERSION = 774;
 
   /**
    * List of all the tables.n
index 5fa95735f7c746f4c471188e01ea1398261dd017..0c3b77d2bcf2acad6de0739518ceb7f4cd1136d4 100644 (file)
@@ -302,6 +302,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('770');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('771');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('772');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('773');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('774');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null);
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;