import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.DbIdsRepository;
import org.sonar.server.computation.component.Developer;
public class MeasureToMeasureDto {
private final DbIdsRepository dbIdsRepository;
+ private final AnalysisMetadataHolder analysisMetadataHolder;
- public MeasureToMeasureDto(DbIdsRepository dbIdsRepository) {
+ public MeasureToMeasureDto(DbIdsRepository dbIdsRepository, AnalysisMetadataHolder analysisMetadataHolder) {
this.dbIdsRepository = dbIdsRepository;
+ this.analysisMetadataHolder = analysisMetadataHolder;
}
@Nonnull
MeasureDto out = new MeasureDto();
out.setMetricId(metric.getId());
out.setComponentUuid(component.getUuid());
+ out.setAnalysisUuid(analysisMetadataHolder.getUuid());
out.setSnapshotId(dbIdsRepository.getSnapshotId(component));
if (measure.hasVariations()) {
setVariations(out, measure.getVariations());
@Rule
public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+ private static final String AN_ANALYSIS_UUID = "a1";
private static final String FILE_COMPONENT_KEY = "file cpt key";
private static final ReportComponent FILE_COMPONENT = ReportComponent.builder(Component.Type.FILE, 1).setKey(FILE_COMPONENT_KEY).build();
private static final ReportComponent OTHER_COMPONENT = ReportComponent.builder(Component.Type.FILE, 2).setKey("some other key").build();
return new MeasureDto()
.setComponentUuid(componentUuid)
.setSnapshotId(snapshotId)
+ .setAnalysisUuid(AN_ANALYSIS_UUID)
.setData(SOME_DATA)
.setMetricId(metricId);
}
import org.junit.Test;
import org.junit.runner.RunWith;
import org.sonar.db.measure.MeasureDto;
+import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.Developer;
import org.sonar.server.computation.component.DumbDeveloper;
private static final MetricImpl SOME_DOUBLE_METRIC = new MetricImpl(4, "4", "4", Metric.MetricType.FLOAT);
private static final MetricImpl SOME_STRING_METRIC = new MetricImpl(5, "5", "5", Metric.MetricType.STRING);
private static final MetricImpl SOME_LEVEL_METRIC = new MetricImpl(6, "6", "6", Metric.MetricType.LEVEL);
-
- static final Component SOME_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid_1").build();
+ private static final String ANALYSIS_UUID = "a1";
+ private static final Component SOME_COMPONENT = ReportComponent.builder(Component.Type.PROJECT, 1).setUuid("uuid_1").build();
@Rule
public MutableDbIdsRepositoryRule dbIdsRepository = MutableDbIdsRepositoryRule.create(SOME_COMPONENT);
- MeasureToMeasureDto underTest = new MeasureToMeasureDto(dbIdsRepository);
+ @Rule
+ public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
+
+ MeasureToMeasureDto underTest = new MeasureToMeasureDto(dbIdsRepository, analysisMetadataHolder);
@Before
public void setUp() throws Exception {
dbIdsRepository.setComponentId(SOME_COMPONENT, SOME_COMPONENT_ID);
dbIdsRepository.setSnapshotId(SOME_COMPONENT, SOME_SNAPSHOT_ID);
+ analysisMetadataHolder.setUuid(ANALYSIS_UUID);
}
@Test(expected = NullPointerException.class)
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.rule.RuleDto;
+import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule;
import org.sonar.server.computation.batch.TreeRootHolderRule;
import org.sonar.server.computation.component.Component;
import org.sonar.server.computation.component.Developer;
private static final long INTERMEDIATE_1_SNAPSHOT_ID = 4L;
private static final long INTERMEDIATE_2_SNAPSHOT_ID = 5L;
private static final long LEAF_SNAPSHOT_ID = 6L;
+ private static final String ANALYSIS_UUID = "a1";
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
@Rule
public MutableDbIdsRepositoryRule dbIdsRepository = MutableDbIdsRepositoryRule.create(treeRootHolder);
+ @Rule
+ public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
+
DbClient dbClient = dbTester.getDbClient();
RuleDto rule;
ComponentDto rootDto;
@Before
public void setUp() {
- underTest = new PersistMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(dbIdsRepository), treeRootHolder, measureRepository);
+ underTest = new PersistMeasuresStep(dbClient, metricRepository, new MeasureToMeasureDto(dbIdsRepository, analysisMetadataHolder), treeRootHolder, measureRepository);
+ analysisMetadataHolder.setUuid(ANALYSIS_UUID);
}
private void setupReportComponents() {
public class ReportComputeMeasureVariationsStepTest {
- static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
- static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
- static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
- static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
- static final Metric NEW_DEBT = new MetricImpl(5, "new_debt", "new_debt", Metric.MetricType.WORK_DUR);
+ private static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+ private static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+ private static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+ private static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+ private static final Metric NEW_DEBT = new MetricImpl(5, "new_debt", "new_debt", Metric.MetricType.WORK_DUR);
+ private static final String ANALYSIS_UUID = "a1";
+ private static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
+ private static final int PROJECT_REF = 1;
+ private static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, PROJECT_REF).setUuid(PROJECT_DTO.uuid()).build();
- static final ComponentDto PROJECT_DTO = ComponentTesting.newProjectDto();
-
- static final int PROJECT_REF = 1;
- static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, PROJECT_REF).setUuid(PROJECT_DTO.uuid()).build();
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
}
private static MeasureDto newMeasureDto(int metricId, String componentUuid, long snapshotId, double value) {
- return new MeasureDto().setMetricId(metricId).setComponentUuid(componentUuid).setSnapshotId(snapshotId).setValue(value);
+ return new MeasureDto()
+ .setMetricId(metricId)
+ .setComponentUuid(componentUuid)
+ .setSnapshotId(snapshotId)
+ .setAnalysisUuid(ANALYSIS_UUID)
+ .setValue(value);
}
private static Period newPeriod(int index, SnapshotDto snapshotDto) {
public class ViewsComputeMeasureVariationsStepTest {
- static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
- static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
- static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
- static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
-
- static final ComponentDto VIEW_DTO = ComponentTesting.newView();
-
- static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+ private static final Metric ISSUES_METRIC = new MetricImpl(1, "violations", "violations", Metric.MetricType.INT);
+ private static final Metric DEBT_METRIC = new MetricImpl(2, "sqale_index", "sqale_index", Metric.MetricType.WORK_DUR);
+ private static final Metric FILE_COMPLEXITY_METRIC = new MetricImpl(3, "file_complexity", "file_complexity", Metric.MetricType.FLOAT);
+ private static final Metric BUILD_BREAKER_METRIC = new MetricImpl(4, "build_breaker", "build_breaker", Metric.MetricType.BOOL);
+ private static final ComponentDto VIEW_DTO = ComponentTesting.newView();
+ private static final Component VIEW = ViewsComponent.builder(Component.Type.VIEW, 1).setUuid(VIEW_DTO.uuid()).build();
+ private static final String ANALYSIS_UUID = "a1";
@Rule
public DbTester dbTester = DbTester.create(System2.INSTANCE);
}
private static MeasureDto newMeasureDto(int metricId, String componentUuid, long snapshotId, double value) {
- return new MeasureDto().setMetricId(metricId).setComponentUuid(componentUuid).setSnapshotId(snapshotId).setValue(value);
+ return new MeasureDto()
+ .setMetricId(metricId)
+ .setComponentUuid(componentUuid)
+ .setSnapshotId(snapshotId)
+ .setAnalysisUuid(ANALYSIS_UUID)
+ .setValue(value);
}
private static Period newPeriod(int index, SnapshotDto snapshotDto) {
VALUE="60"
METRIC_ID="1"
SNAPSHOT_ID="1000"
+ analysis_uuid="u1000"
text_value="[null]"
project_id="[null]"
person_id="[null]"/>
VALUE="80"
METRIC_ID="2"
SNAPSHOT_ID="1000"
+ analysis_uuid="u1000"
text_value="[null]"
project_id="[null]"
person_id="[null]"/>
VALUE="20"
METRIC_ID="1"
SNAPSHOT_ID="1001"
+ analysis_uuid="u1000"
text_value="[null]"
project_id="[null]"
person_id="[null]"/>
VALUE="70"
METRIC_ID="2"
SNAPSHOT_ID="1001"
+ analysis_uuid="u1000"
text_value="[null]"
project_id="[null]"
person_id="[null]"/>
<dataset>
- <project_measures id="1" snapshot_id="1000" metric_id="10" value="[null]"
+ <project_measures id="1"
+ snapshot_id="1000"
+ analysis_uuid="u1000"
+ metric_id="10"
+ value="[null]"
text_value="<duplications><g><b s="1" l="5" r="PROJECT_KEY:file"/><b s="6" l="10" r="PROJECT_KEY:file">"
- measure_data="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]" />
+ measure_data="[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" snapshot_id="1000" metric_id="10" value="[null]"
+ <project_measures id="2"
+ snapshot_id="1000"
+ analysis_uuid="u1000"
+ metric_id="10"
+ value="[null]"
text_value="<duplications><g><b s="1" l="5" r="PROJECT_KEY:file"/><b s="6" l="10" r="PROJECT_KEY:file">"
- measure_data="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]" />
+ measure_data="[null]"
+ variation_value_1="[null]"
+ variation_value_2="[null]"
+ variation_value_3="[null]"
+ variation_value_4="[null]"
+ variation_value_5="[null]"/>
</dataset>
<dataset>
- <metrics id="1" name="duplications_data" val_type="DATA" description="Duplications details" short_name="Duplications details" domain="Duplication"
- qualitative="[false]" enabled="[true]" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="[false]"/>
+ <metrics id="1"
+ name="duplications_data"
+ val_type="DATA"
+ description="Duplications details"
+ short_name="Duplications details"
+ domain="Duplication"
+ qualitative="[false]"
+ enabled="[true]"
+ worst_value="[null]"
+ optimized_best_value="[null]"
+ best_value="[null]"
+ direction="0"
+ hidden="[false]"/>
</dataset>
<dataset>
- <project_measures snapshot_id="1000" metric_id="10" value="6.0" project_id="[null]" text_value="[null]"
- measure_data="[null]" variation_value_1="[null]" variation_value_2="[null]"
- variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- alert_status="[null]" alert_text="[null]" description="[null]" person_id="[null]"/>
+ <project_measures snapshot_id="1000"
+ analysis_uuid="u1000"
+ metric_id="10"
+ value="6.0"
+ project_id="[null]"
+ text_value="[null]"
+ measure_data="[null]"
+ variation_value_1="[null]"
+ variation_value_2="[null]"
+ variation_value_3="[null]"
+ variation_value_4="[null]"
+ variation_value_5="[null]"
+ alert_status="[null]"
+ alert_text="[null]"
+ description="[null]"
+ person_id="[null]"/>
</dataset>
<dataset>
- <project_measures snapshot_id="1000" metric_id="10" value="3.0" project_id="[null]" text_value="[null]"
- measure_data="[null]" variation_value_1="[null]" variation_value_2="[null]"
- variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
- alert_status="[null]" alert_text="[null]" description="[null]" person_id="[null]"/>
+ <project_measures snapshot_id="1000"
+ analysis_uuid="u1000"
+ metric_id="10"
+ value="3.0"
+ project_id="[null]"
+ text_value="[null]"
+ measure_data="[null]"
+ variation_value_1="[null]"
+ variation_value_2="[null]"
+ variation_value_3="[null]"
+ variation_value_4="[null]"
+ variation_value_5="[null]"
+ alert_status="[null]"
+ alert_text="[null]"
+ description="[null]"
+ person_id="[null]"/>
</dataset>
metric_id="1"
value="500"
snapshot_id="101"
+ analysis_uuid="u101"
person_id="[null]"
variation_value_1="[null]"
variation_value_2="[null]"
metric_id="1"
value="300"
snapshot_id="101"
+ analysis_uuid="u101"
person_id="30000"
variation_value_1="[null]"
variation_value_2="[null]"
metric_id="1"
value="200"
snapshot_id="101"
+ analysis_uuid="u101"
person_id="40000"
variation_value_1="[null]"
variation_value_2="[null]"
metric_id="1"
value="500"
snapshot_id="101"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="1"
value="510"
snapshot_id="101"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="1"
value="510"
snapshot_id="102"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="1"
value="500"
snapshot_id="103"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="1"
value="10"
snapshot_id="104"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="2"
value="[null]"
snapshot_id="101"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="3"
value="12.3"
snapshot_id="101"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="1"
value="5000"
snapshot_id="110"
+ analysis_uuid="u110"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="2"
value="[null]"
snapshot_id="110"
+ analysis_uuid="u110"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="5"
value="510"
snapshot_id="101"
+ analysis_uuid="u101"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
metric_id="5"
value="5000"
snapshot_id="110"
+ analysis_uuid="u110"
url="[null]"
variation_value_1="[null]"
variation_value_2="[null]"
metric_id="5"
value="5000"
snapshot_id="120"
+ analysis_uuid="u120"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
--- /dev/null
+#
+# 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 6.0
+#
+class AddAnalysisUuidColumnToMeasures < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.db.version.v60.AddAnalysisUuidColumnToMeasures')
+ end
+end
--- /dev/null
+#
+# 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 6.0
+#
+class PopulateAnalysisUuidOnMeasures < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.db.version.v60.PopulateAnalysisUuidOnMeasures')
+ end
+end
--- /dev/null
+#
+# 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 6.0
+#
+class CleanMeasuresWithNullAnalysisUuid < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.db.version.v60.CleanMeasuresWithNullAnalysisUuid')
+ end
+end
--- /dev/null
+#
+# 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 6.0
+#
+class MakeAnalysisUuidNotNullOnMeasures < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnMeasures')
+ end
+end
private String description;
private String componentUuid;
private Long snapshotId;
+ private String analysisUuid;
private Integer metricId;
private Long developerId;
return this;
}
+ public String getAnalysisUuid() {
+ return analysisUuid;
+ }
+
+ public MeasureDto setAnalysisUuid(String s) {
+ this.analysisUuid = s;
+ return this;
+ }
+
/**
* @deprecated in 5.5. Does nothing. Kept for compatibility with developer cockpit plugin, version 1.10
*/
.add("description", description)
.add("componentUuid", componentUuid)
.add("snapshotId", snapshotId)
+ .add("analysisUuid", analysisUuid)
.add("metricId", metricId)
.add("developerId", developerId)
.add("metricKey", metricKey)
public class DatabaseVersion {
- public static final int LAST_VERSION = 1_257;
+ public static final int LAST_VERSION = 1_261;
/**
* The minimum supported version which can be upgraded. Lower
import org.sonar.db.version.v60.AddAnalysisUuidColumnToCeActivity;
import org.sonar.db.version.v60.AddAnalysisUuidColumnToDuplicationsIndex;
import org.sonar.db.version.v60.AddAnalysisUuidColumnToEvents;
+import org.sonar.db.version.v60.AddAnalysisUuidColumnToMeasures;
import org.sonar.db.version.v60.AddComponentUuidColumnToDuplicationsIndex;
import org.sonar.db.version.v60.AddComponentUuidColumnToMeasures;
import org.sonar.db.version.v60.AddComponentUuidColumnsToSnapshots;
import org.sonar.db.version.v60.CleanOrphanRowsInProjects;
import org.sonar.db.version.v60.CleanOrphanRowsInResourceIndex;
import org.sonar.db.version.v60.CleanOrphanRowsInSnapshots;
+import org.sonar.db.version.v60.CleanMeasuresWithNullAnalysisUuid;
import org.sonar.db.version.v60.DeleteOrphanDuplicationsIndexRowsWithoutAnalysis;
import org.sonar.db.version.v60.DeleteOrphanDuplicationsIndexRowsWithoutComponent;
import org.sonar.db.version.v60.DeleteOrphanMeasuresWithoutComponent;
import org.sonar.db.version.v60.DropUnusedMeasuresColumns;
import org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnDuplicationsIndex;
import org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnEvents;
+import org.sonar.db.version.v60.MakeAnalysisUuidNotNullOnMeasures;
import org.sonar.db.version.v60.MakeComponentUuidColumnsNotNullOnSnapshots;
import org.sonar.db.version.v60.MakeComponentUuidNotNullOnDuplicationsIndex;
import org.sonar.db.version.v60.MakeComponentUuidNotNullOnMeasures;
import org.sonar.db.version.v60.PopulateAnalysisUuidColumnOnCeActivity;
import org.sonar.db.version.v60.PopulateAnalysisUuidOfDuplicationsIndex;
import org.sonar.db.version.v60.PopulateAnalysisUuidOnEvents;
+import org.sonar.db.version.v60.PopulateAnalysisUuidOnMeasures;
import org.sonar.db.version.v60.PopulateComponentUuidColumnsOfSnapshots;
import org.sonar.db.version.v60.PopulateComponentUuidOfDuplicationsIndex;
import org.sonar.db.version.v60.PopulateComponentUuidOfMeasures;
// PROJECTS.UUID_PATH
AddUuidPathColumnToProjects.class,
PopulateUuidPathColumnOnProjects.class,
- MakeUuidPathColumnNotNullOnProjects.class);
+ MakeUuidPathColumnNotNullOnProjects.class,
+
+ // PROJECT_MEASURES.ANALYSIS_UUID
+ AddAnalysisUuidColumnToMeasures.class,
+ PopulateAnalysisUuidOnMeasures.class,
+ CleanMeasuresWithNullAnalysisUuid.class,
+ MakeAnalysisUuidNotNullOnMeasures.class
+ );
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.AddColumnsBuilder;
+import org.sonar.db.version.DdlChange;
+
+import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE;
+import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class AddAnalysisUuidColumnToMeasures extends DdlChange {
+
+ private static final String TABLE_MEASURES = "project_measures";
+
+ public AddAnalysisUuidColumnToMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AddColumnsBuilder(getDatabase().getDialect(), TABLE_MEASURES)
+ .addColumn(newVarcharColumnDefBuilder().setColumnName("analysis_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(true).build())
+ .build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.BaseDataChange;
+import org.sonar.db.version.MassUpdate;
+
+public class CleanMeasuresWithNullAnalysisUuid extends BaseDataChange {
+
+ public CleanMeasuresWithNullAnalysisUuid(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("select id from project_measures where analysis_uuid is null");
+ massUpdate.update("delete from project_measures where id=?");
+ massUpdate.rowPluralName("measures");
+ massUpdate.execute((row, update) -> {
+ update.setLong(1, row.getLong(1));
+ return true;
+ });
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.AlterColumnsBuilder;
+import org.sonar.db.version.DdlChange;
+
+import static org.sonar.db.version.VarcharColumnDef.UUID_VARCHAR_SIZE;
+import static org.sonar.db.version.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class MakeAnalysisUuidNotNullOnMeasures extends DdlChange {
+
+ private static final String TABLE_MEASURES = "project_measures";
+
+ public MakeAnalysisUuidNotNullOnMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ context.execute(new AlterColumnsBuilder(getDatabase().getDialect(), TABLE_MEASURES)
+ .updateColumn(newVarcharColumnDefBuilder().setColumnName("analysis_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(false).build())
+ .build());
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.BaseDataChange;
+import org.sonar.db.version.MassUpdate;
+import org.sonar.db.version.Select;
+import org.sonar.db.version.SqlStatement;
+
+public class PopulateAnalysisUuidOnMeasures extends BaseDataChange {
+
+ public PopulateAnalysisUuidOnMeasures(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("select distinct m.snapshot_id, root_snapshots.uuid " +
+ "from project_measures m " +
+ "inner join snapshots s on m.snapshot_id=s.id " +
+ "inner join snapshots root_snapshots on s.root_snapshot_id=root_snapshots.id " +
+ "where m.analysis_uuid is null");
+ massUpdate.update("update project_measures set analysis_uuid=? where snapshot_id=? and analysis_uuid is null");
+ massUpdate.rowPluralName("measures");
+ massUpdate.execute(this::handle);
+ }
+
+ private boolean handle(Select.Row row, SqlStatement update) throws SQLException {
+ long snapshotId = row.getLong(1);
+ String analysisUuid = row.getString(2);
+
+ update.setString(1, analysisUuid);
+ update.setLong(2, snapshotId);
+
+ return true;
+ }
+
+}
pm.person_id as developerId,
pm.component_uuid as componentUuid,
pm.snapshot_id as snapshotId,
+ pm.analysis_uuid as analysisUuid,
pm.value as value,
pm.text_value as textValue,
pm.alert_status as alertStatus,
<insert id="insert" parameterType="Measure" useGeneratedKeys="false">
INSERT INTO project_measures (
- value, metric_id, component_uuid, snapshot_id, text_value, alert_status, alert_text, description,
- person_id, variation_value_1, variation_value_2, variation_value_3, variation_value_4,
- variation_value_5, measure_data)
+ value,
+ metric_id,
+ component_uuid,
+ snapshot_id,
+ analysis_uuid,
+ text_value,
+ alert_status,
+ alert_text,
+ description,
+ person_id,
+ variation_value_1,
+ variation_value_2,
+ variation_value_3,
+ variation_value_4,
+ variation_value_5,
+ measure_data)
VALUES (
- #{value, jdbcType=DOUBLE}, #{metricId, jdbcType=INTEGER}, #{componentUuid, jdbcType=VARCHAR},
+ #{value, jdbcType=DOUBLE},
+ #{metricId, jdbcType=INTEGER},
+ #{componentUuid, jdbcType=VARCHAR},
#{snapshotId, jdbcType=INTEGER},
+ #{analysisUuid, jdbcType=VARCHAR},
#{textValue, jdbcType=VARCHAR},
- #{alertStatus, jdbcType=VARCHAR}, #{alertText, jdbcType=VARCHAR},
+ #{alertStatus, jdbcType=VARCHAR},
+ #{alertText, jdbcType=VARCHAR},
#{description, jdbcType=VARCHAR},
- #{developerId, jdbcType=INTEGER}, #{variation1, jdbcType=DOUBLE}, #{variation2, jdbcType=DOUBLE},
+ #{developerId, jdbcType=INTEGER},
+ #{variation1, jdbcType=DOUBLE},
+ #{variation2, jdbcType=DOUBLE},
#{variation3, jdbcType=DOUBLE},
- #{variation4, jdbcType=DOUBLE}, #{variation5, jdbcType=DOUBLE}, #{dataValue, jdbcType=BINARY}
+ #{variation4, jdbcType=DOUBLE},
+ #{variation5, jdbcType=DOUBLE},
+ #{dataValue, jdbcType=BINARY}
)
</insert>
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1255');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1256');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1257');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1258');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1259');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1260');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1261');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT) VALUES (1, 'admin', 'Administrator', '', 'admin', 'sonarqube', true, 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482');
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
"VALUE" DOUBLE,
"METRIC_ID" INTEGER NOT NULL,
"COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
"SNAPSHOT_ID" INTEGER,
"TEXT_VALUE" VARCHAR(4000),
"ALERT_STATUS" VARCHAR(5),
.setValue(value)
.setComponentUuid(componentDto.uuid())
.setSnapshotId(snapshotDto.getId())
+ .setAnalysisUuid("u1")
.setDeveloperId(developerId);
dbClient.measureDao().insert(dbSession, measureDto);
dbSession.commit();
underTest.insert(dbSession, new MeasureDto()
.setSnapshotId(2L)
+ .setAnalysisUuid("u2")
.setMetricId(3)
.setDeveloperId(23L)
.setComponentUuid("FILE1")
underTest.insert(dbSession, new MeasureDto()
.setSnapshotId(2L)
+ .setAnalysisUuid("u2")
.setMetricId(3)
.setComponentUuid("COMPONENT_1")
.setValue(2.0d),
new MeasureDto()
.setSnapshotId(3L)
+ .setAnalysisUuid("u2")
.setMetricId(4)
.setComponentUuid("COMPONENT_2")
.setValue(4.0d));
.setMetricId(metricDto.getId())
.setMetricKey(metricDto.getKey())
.setComponentUuid(snapshot.getComponentUuid())
- .setSnapshotId(snapshot.getId());
+ .setSnapshotId(snapshot.getId())
+ .setAnalysisUuid(snapshot.getUuid());
}
}
public void verify_count_of_added_MigrationStep_types() {
ComponentContainer container = new ComponentContainer();
new MigrationStepModule().configure(container);
- assertThat(container.size()).isEqualTo(113);
+ assertThat(container.size()).isEqualTo(117);
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+
+public class AddAnalysisUuidColumnToMeasuresTest {
+
+ private static final String TABLE = "project_measures";
+
+ @Rule
+ public DbTester db = DbTester.createForSchema(System2.INSTANCE, AddAnalysisUuidColumnToMeasuresTest.class, "old_measures.sql");
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private AddAnalysisUuidColumnToMeasures underTest = new AddAnalysisUuidColumnToMeasures(db.database());
+
+ @Test
+ public void migration_adds_column_to_empty_table() throws SQLException {
+ underTest.execute();
+
+ verifyAddedColumn();
+ }
+
+ @Test
+ public void migration_adds_column_to_populated_table() throws SQLException {
+ for (int i = 0; i < 9; i++) {
+ db.executeInsert(
+ TABLE,
+ "metric_id", valueOf(i),
+ "value", valueOf(i + 10),
+ "snapshot_id", valueOf(i + 100),
+ "component_uuid", valueOf(i + 1_000)
+ );
+ }
+ db.commit();
+
+ underTest.execute();
+
+ verifyAddedColumn();
+ }
+
+ @Test
+ public void migration_is_not_reentrant() throws SQLException {
+ underTest.execute();
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Fail to execute ");
+ underTest.execute();
+ }
+
+ private void verifyAddedColumn() {
+ db.assertColumnDefinition(TABLE, "analysis_uuid", Types.VARCHAR, 50, true);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CleanMeasuresWithNullAnalysisUuidTest {
+
+ private static final String TABLE_MEASURES = "project_measures";
+
+ @Rule
+ public DbTester db = DbTester.createForSchema(System2.INSTANCE, CleanMeasuresWithNullAnalysisUuidTest.class,
+ "in_progress_measures.sql");
+
+ private CleanMeasuresWithNullAnalysisUuid underTest = new CleanMeasuresWithNullAnalysisUuid(db.database());
+
+ @Test
+ public void migration_has_no_effect_on_empty_table() throws SQLException {
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable(TABLE_MEASURES)).isEqualTo(0);
+ }
+
+ @Test
+ public void migration_deletes_rows_with_null_analysis_uuid() throws SQLException {
+ insertMeasure(1, "U1");
+ insertMeasure(2, "U1");
+ insertMeasure(3, null);
+ db.commit();
+
+ underTest.execute();
+
+ assertThat(idsOfRows()).containsOnly(1L, 2L);
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ insertMeasure(1, "U1");
+ insertMeasure(2, null);
+ db.commit();
+
+ underTest.execute();
+ assertThat(idsOfRows()).containsOnly(1L);
+
+ underTest.execute();
+ assertThat(idsOfRows()).containsOnly(1L);
+ }
+
+ private void insertMeasure(long id, @Nullable String analysisUuid) {
+ db.executeInsert(
+ TABLE_MEASURES,
+ "ID", valueOf(id),
+ "SNAPSHOT_ID", valueOf(id + 10),
+ "METRIC_ID", valueOf(id + 100),
+ "VALUE", valueOf(id + 200),
+ "COMPONENT_UUID", valueOf(id + 300),
+ "ANALYSIS_UUID", analysisUuid);
+ }
+
+ private List<Long> idsOfRows() {
+ return db.select("select ID from project_measures").stream().map(map -> (Long) map.get("ID")).collect(Collectors.toList());
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+
+
+public class MakeAnalysisUuidNotNullOnMeasuresTest {
+
+ private static final String TABLE_MEASURES = "project_measures";
+
+ @Rule
+ public DbTester db = DbTester.createForSchema(System2.INSTANCE, MakeAnalysisUuidNotNullOnMeasuresTest.class,
+ "in_progress_measures.sql");
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ private MakeAnalysisUuidNotNullOnMeasures underTest = new MakeAnalysisUuidNotNullOnMeasures(db.database());
+
+ @Test
+ public void migration_makes_analysis_uuid_not_nullable_on_empty_table() throws SQLException {
+ underTest.execute();
+
+ verifyColumnDefinitions();
+ }
+
+ @Test
+ public void migration_makes_analysis_uuid_not_nullable_on_populated_table() throws SQLException {
+ insertMeasure(1, "U1");
+ insertMeasure(2, "U2");
+
+ underTest.execute();
+
+ verifyColumnDefinitions();
+ }
+
+ @Test
+ public void migration_fails_if_some_uuid_columns_are_null() throws SQLException {
+ insertMeasure(2, null);
+
+ expectedException.expect(IllegalStateException.class);
+ expectedException.expectMessage("Fail to execute");
+
+ underTest.execute();
+ }
+
+ private void insertMeasure(long id, @Nullable String analysisUuid) {
+ db.executeInsert(
+ TABLE_MEASURES,
+ "ID", valueOf(id),
+ "SNAPSHOT_ID", valueOf(id + 10),
+ "METRIC_ID", valueOf(id + 100),
+ "VALUE", valueOf(id + 200),
+ "COMPONENT_UUID", valueOf(id + 300),
+ "ANALYSIS_UUID", analysisUuid);
+ }
+
+ private void verifyColumnDefinitions() {
+ db.assertColumnDefinition(TABLE_MEASURES, "analysis_uuid", Types.VARCHAR, 50, false);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program 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.
+ *
+ * This program 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.db.version.v60;
+
+import java.sql.SQLException;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+
+import static java.lang.String.valueOf;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class PopulateAnalysisUuidOnMeasuresTest {
+
+ private static final String TABLE_MEASURES = "project_measures";
+ private static final String TABLE_SNAPSHOTS = "snapshots";
+
+ @Rule
+ public DbTester db = DbTester.createForSchema(System2.INSTANCE, PopulateAnalysisUuidOnMeasuresTest.class,
+ "old_measures.sql");
+
+ private PopulateAnalysisUuidOnMeasures underTest = new PopulateAnalysisUuidOnMeasures(db.database());
+
+ @Test
+ public void migration_has_no_effect_on_empty_tables() throws SQLException {
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable(TABLE_MEASURES)).isEqualTo(0);
+ }
+
+ @Test
+ public void migration_populates_analysis_uuids() throws SQLException {
+ insertSnapshot(1, "U1", Qualifiers.PROJECT, 1);
+ insertSnapshot(2, "U2", Qualifiers.DIRECTORY, 1);
+ insertSnapshot(3, "U3", Qualifiers.FILE, 1);
+ insertMeasure(21, 1);
+ insertMeasure(22, 2);
+ insertMeasure(23, 3);
+ db.commit();
+
+ underTest.execute();
+
+ verifyAnalysisUuid(21, "U1");
+ verifyAnalysisUuid(22, "U1");
+ verifyAnalysisUuid(23, "U1");
+ }
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ insertSnapshot(1, "U1", Qualifiers.PROJECT, 1);
+ insertMeasure(21, 1);
+
+ underTest.execute();
+ verifyAnalysisUuid(21, "U1");
+
+ underTest.execute();
+ verifyAnalysisUuid(21, "U1");
+ }
+
+ private void verifyAnalysisUuid(int measureId, @Nullable String expectedAnalysisUuid) {
+ Map<String, Object> rows = db.selectFirst("select analysis_uuid as \"analysisUuid\" from project_measures where id=" + measureId);
+ assertThat(rows.get("analysisUuid")).isEqualTo(expectedAnalysisUuid);
+ }
+
+ private String insertSnapshot(long id, String uuid, String qualifier, long rootSnapshotId) {
+ db.executeInsert(
+ TABLE_SNAPSHOTS,
+ "ID", valueOf(id),
+ "UUID", uuid,
+ "COMPONENT_UUID", valueOf(id + 10),
+ "ROOT_COMPONENT_UUID", valueOf(id + 10),
+ "ROOT_SNAPSHOT_ID", valueOf(rootSnapshotId),
+ "QUALIFIER", qualifier);
+ return uuid;
+ }
+
+ private void insertMeasure(long id, long snapshotId) {
+ db.executeInsert(
+ TABLE_MEASURES,
+ "ID", valueOf(id),
+ "SNAPSHOT_ID", valueOf(snapshotId),
+ "METRIC_ID", valueOf(id + 100),
+ "VALUE", valueOf(id + 200),
+ "COMPONENT_UUID", valueOf(id + 300));
+ }
+}
<project_measures
id="1"
snapshot_id="2"
+ analysis_uuid="u2"
metric_id="3"
component_uuid="FILE1"
person_id="23"
VALUE="60"
METRIC_ID="1"
SNAPSHOT_ID="1000"
+ analysis_uuid="u1000"
person_id="[null]"
component_uuid="ABCD"/>
VALUE="80"
METRIC_ID="2"
SNAPSHOT_ID="1000"
+ analysis_uuid="u1000"
person_id="[null]"
component_uuid="ABCD"/>
VALUE="20"
METRIC_ID="1"
SNAPSHOT_ID="1001"
+ analysis_uuid="u1000"
person_id="[null]"
component_uuid="BCDE"/>
VALUE="70"
METRIC_ID="2"
SNAPSHOT_ID="1001"
+ analysis_uuid="u1000"
person_id="[null]"
component_uuid="BCDE"/>
VALUE="5"
METRIC_ID="1"
SNAPSHOT_ID="1002"
+ analysis_uuid="u1000"
person_id="[null]"
component_uuid="CDEF"/>
VALUE="60"
METRIC_ID="2"
SNAPSHOT_ID="1002"
+ analysis_uuid="u1000"
person_id="[null]"
component_uuid="CDEF"/>
VALUE="60"
METRIC_ID="1"
SNAPSHOT_ID="1000"
+ analysis_uuid="u1000"
person_id="[null]"
component_uuid="ABCD"/>
VALUE="20"
METRIC_ID="1"
SNAPSHOT_ID="1000"
+ analysis_uuid="u1000"
person_id="20"
component_uuid="ABCD"/>
VALUE="40"
METRIC_ID="1"
SNAPSHOT_ID="1000"
+ analysis_uuid="u1000"
person_id="21"
component_uuid="ABCD"/>
<project_measures id="20"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="10"
value="[null]"
text_value="0123456789012345678901234567890123456789"
component_uuid="FILE1"/>
<project_measures id="21"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="11"
value="[null]"
text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1"
component_uuid="FILE1"/>
<project_measures id="22"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="12"
value="10"
text_value="[null]"
<project_measures id="20"
component_uuid="ABCD"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="10"
value="[null]"
text_value="0123456789012345678901234567890123456789"
<project_measures id="21"
component_uuid="ABCD"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="11"
value="[null]"
text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1"
<project_measures id="22"
component_uuid="ABCD"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="12"
value="10"
text_value="[null]"
<project_measures id="20"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="10"
value="[null]"
text_value="0123456789012345678901234567890123456789"
component_uuid="1"/>
<project_measures id="21"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="11"
value="[null]"
text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1"
component_uuid="1"/>
<project_measures id="22"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="12"
value="10"
text_value="[null]"
<!--measures for developer 333-->
<project_measures id="30"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="10"
value="[null]"
text_value="0123456789012345678901234567890123456789"
component_uuid="1"/>
<project_measures id="31"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="11"
value="[null]"
text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1"
component_uuid="1"/>
<project_measures id="32"
snapshot_id="5"
+ analysis_uuid="u5"
metric_id="12"
value="10"
text_value="[null]"
VALUE="10.0"
METRIC_ID="1"
SNAPSHOT_ID="1"
+ analysis_uuid="u1"
person_id="[null]"
text_value="[null]"
component_uuid="1"
VALUE="10.0"
METRIC_ID="1"
SNAPSHOT_ID="1"
+ analysis_uuid="u1"
person_id="[null]"
text_value="[null]"
component_uuid="1"
VALUE="10.0"
METRIC_ID="1"
SNAPSHOT_ID="5"
+ analysis_uuid="u5"
person_id="[null]"
text_value="[null]"
component_uuid="5"
<dataset>
- <metrics id="1" delete_historical_data="[null]"
- name="ncloc" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]"
- worst_value="[null]" optimized_best_value="[null]" best_value="[null]"
- direction="0" hidden="[false]"/>
+ <metrics id="1"
+ delete_historical_data="[null]"
+ name="ncloc"
+ val_type="INT"
+ description="[null]"
+ domain="[null]"
+ short_name=""
+ enabled="[true]"
+ worst_value="[null]"
+ optimized_best_value="[null]"
+ best_value="[null]"
+ direction="0"
+ hidden="[false]"/>
- <metrics id="2" delete_historical_data="[true]"
- name="coverage" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]"
- worst_value="0" optimized_best_value="[true]" best_value="100"
- direction="1" hidden="[false]"/>
+ <metrics id="2"
+ delete_historical_data="[true]"
+ name="coverage"
+ val_type="INT"
+ description="[null]"
+ domain="[null]"
+ short_name=""
+ enabled="[true]"
+ worst_value="0"
+ optimized_best_value="[true]"
+ best_value="100"
+ direction="1"
+ hidden="[false]"/>
<snapshots id="1"
uuid="u1"
- project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- status="P" islast="[true]" purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000"
- build_date="1228222680000" version="[null]" path="[null]"/>
+ project_id="1"
+ parent_snapshot_id="[null]"
+ root_project_id="1"
+ root_snapshot_id="[null]"
+ status="P"
+ islast="[true]"
+ purge_status="[null]"
+ period1_mode="[null]"
+ period1_param="[null]"
+ period1_date="[null]"
+ period2_mode="[null]"
+ period2_param="[null]"
+ period2_date="[null]"
+ period3_mode="[null]"
+ period3_param="[null]"
+ period3_date="[null]"
+ period4_mode="[null]"
+ period4_param="[null]"
+ period4_date="[null]"
+ period5_mode="[null]"
+ period5_param="[null]"
+ period5_date="[null]"
+ depth="[null]"
+ scope="PRJ"
+ qualifier="TRK"
+ created_at="1228222680000"
+ build_date="1228222680000"
+ version="[null]"
+ path="[null]"/>
<!-- do not delete standard measure -->
<project_measures id="1"
snapshot_id="1"
+ analysis_uuid="u1"
metric_id="1"
component_uuid="1"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
+ variation_value_1="[null]"
+ variation_value_2="[null]"
+ variation_value_3="[null]"
variation_value_4="[null]"
- variation_value_5="[null]" alert_text="[null]" value="10.0"
+ variation_value_5="[null]"
+ alert_text="[null]"
+ value="10.0"
person_id="[null]"
- text_value="[null]" alert_status="[null]"
- description="[null]" measure_data="[null]"/>
+ text_value="[null]"
+ alert_status="[null]"
+ description="[null]"
+ measure_data="[null]"/>
</dataset>
<dataset>
- <metrics id="1" delete_historical_data="[null]"
- name="ncloc" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]"
- worst_value="[null]" optimized_best_value="[null]" best_value="[null]"
- direction="0" hidden="[false]"/>
+ <metrics id="1"
+ delete_historical_data="[null]"
+ name="ncloc"
+ val_type="INT"
+ description="[null]"
+ domain="[null]"
+ short_name=""
+ enabled="[true]"
+ worst_value="[null]"
+ optimized_best_value="[null]"
+ best_value="[null]"
+ direction="0"
+ hidden="[false]"/>
- <metrics id="2" delete_historical_data="[true]"
- name="coverage" val_type="INT" description="[null]" domain="[null]" short_name="" enabled="[true]"
- worst_value="0" optimized_best_value="[true]" best_value="100"
- direction="1" hidden="[false]"/>
+ <metrics id="2"
+ delete_historical_data="[true]"
+ name="coverage"
+ val_type="INT"
+ description="[null]"
+ domain="[null]"
+ short_name=""
+ enabled="[true]"
+ worst_value="0"
+ optimized_best_value="[true]"
+ best_value="100"
+ direction="1"
+ hidden="[false]"/>
<snapshots id="1"
uuid="u1"
parent_snapshot_id="[null]"
root_component_uuid="uuid_1"
root_snapshot_id="[null]"
- status="P" islast="[true]"
+ status="P"
+ islast="[true]"
purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000"
- build_date="1228222680000" version="[null]" path="[null]"/>
+ period1_mode="[null]"
+ period1_param="[null]"
+ period1_date="[null]"
+ period2_mode="[null]"
+ period2_param="[null]"
+ period2_date="[null]"
+ period3_mode="[null]"
+ period3_param="[null]"
+ period3_date="[null]"
+ period4_mode="[null]"
+ period4_param="[null]"
+ period4_date="[null]"
+ period5_mode="[null]"
+ period5_param="[null]"
+ period5_date="[null]"
+ depth="[null]"
+ scope="PRJ"
+ qualifier="TRK"
+ created_at="1228222680000"
+ build_date="1228222680000"
+ version="[null]"
+ path="[null]"/>
<!-- do not delete standard measure -->
<project_measures id="1"
component_uuid="1"
- snapshot_id="1" metric_id="1"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
+ snapshot_id="1"
+ analysis_uuid="u1"
+ metric_id="1"
+ variation_value_1="[null]"
+ variation_value_2="[null]"
+ variation_value_3="[null]"
variation_value_4="[null]"
- variation_value_5="[null]" alert_text="[null]" value="10.0"
+ variation_value_5="[null]"
+ alert_text="[null]"
+ value="10.0"
person_id="[null]"
- text_value="[null]" alert_status="[null]"
- description="[null]" measure_data="[null]"/>
+ text_value="[null]"
+ alert_status="[null]"
+ description="[null]"
+ measure_data="[null]"/>
<!-- delete measure on metrics that are flagged with delete_historical_data=true -->
<project_measures id="6"
component_uuid="1"
- snapshot_id="1" metric_id="2"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
+ snapshot_id="1"
+ analysis_uuid="u1"
+ metric_id="2"
+ variation_value_1="[null]"
+ variation_value_2="[null]"
+ variation_value_3="[null]"
variation_value_4="[null]"
- variation_value_5="[null]" alert_text="[null]" value="10.0"
+ variation_value_5="[null]"
+ alert_text="[null]"
+ value="10.0"
person_id="[null]"
- text_value="[null]" alert_status="[null]"
- description="[null]" measure_data="[null]"/>
+ text_value="[null]"
+ alert_status="[null]"
+ description="[null]"
+ measure_data="[null]"/>
<!-- delete measure on developers -->
<project_measures id="7"
component_uuid="1"
- snapshot_id="1" metric_id="2"
- variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
+ snapshot_id="1"
+ analysis_uuid="u1"
+ metric_id="2"
+ variation_value_1="[null]"
+ variation_value_2="[null]"
+ variation_value_3="[null]"
person_id="123456"
variation_value_4="[null]"
- variation_value_5="[null]" alert_text="[null]" value="10.0"
- text_value="[null]" tendency="[null]" measure_date="[null]" alert_status="[null]"
- description="[null]" measure_data="[null]"/>
+ variation_value_5="[null]"
+ alert_text="[null]"
+ value="10.0"
+ text_value="[null]"
+ tendency="[null]"
+ measure_date="[null]"
+ alert_status="[null]"
+ description="[null]"
+ measure_data="[null]"/>
</dataset>
<project_measures ID="1"
component_uuid="1"
SNAPSHOT_ID="1"
+ analysis_uuid="u1"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
<project_measures ID="2"
component_uuid="2"
SNAPSHOT_ID="2"
+ analysis_uuid="u2"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
<project_measures ID="1"
component_uuid="1"
SNAPSHOT_ID="1"
+ analysis_uuid="u1"
variation_value_1="[null]"
variation_value_2="[null]"
variation_value_3="[null]"
<project_measures ID="2"
component_uuid="2"
SNAPSHOT_ID="2"
+ analysis_uuid="u2"
characteristic_id="[null]"
variation_value_1="[null]"
variation_value_2="[null]"
--- /dev/null
+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,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "SNAPSHOT_ID" INTEGER,
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "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)
+ );
--- /dev/null
+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,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "SNAPSHOT_ID" INTEGER,
+ // NULLABLE at that time
+ "ANALYSIS_UUID" VARCHAR(50),
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "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)
+ );
--- /dev/null
+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,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "SNAPSHOT_ID" INTEGER,
+ // NULLABLE at that time
+ "ANALYSIS_UUID" VARCHAR(50),
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "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)
+ );
--- /dev/null
+CREATE TABLE "SNAPSHOTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "UUID" VARCHAR(50) NOT NULL,
+ "CREATED_AT" BIGINT,
+ "BUILD_DATE" BIGINT,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "PARENT_SNAPSHOT_ID" INTEGER,
+ "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+ "PURGE_STATUS" INTEGER,
+ "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10),
+ "ROOT_SNAPSHOT_ID" INTEGER,
+ "VERSION" VARCHAR(500),
+ "PATH" VARCHAR(500),
+ "DEPTH" INTEGER,
+ "ROOT_COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "PERIOD1_MODE" VARCHAR(100),
+ "PERIOD1_PARAM" VARCHAR(100),
+ "PERIOD1_DATE" BIGINT,
+ "PERIOD2_MODE" VARCHAR(100),
+ "PERIOD2_PARAM" VARCHAR(100),
+ "PERIOD2_DATE" BIGINT,
+ "PERIOD3_MODE" VARCHAR(100),
+ "PERIOD3_PARAM" VARCHAR(100),
+ "PERIOD3_DATE" BIGINT,
+ "PERIOD4_MODE" VARCHAR(100),
+ "PERIOD4_PARAM" VARCHAR(100),
+ "PERIOD4_DATE" BIGINT,
+ "PERIOD5_MODE" VARCHAR(100),
+ "PERIOD5_PARAM" VARCHAR(100),
+ "PERIOD5_DATE" BIGINT
+);
+
+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,
+ "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+ "SNAPSHOT_ID" INTEGER,
+ // NULLABLE at that time
+ "ANALYSIS_UUID" VARCHAR(50),
+ "TEXT_VALUE" VARCHAR(4000),
+ "ALERT_STATUS" VARCHAR(5),
+ "ALERT_TEXT" VARCHAR(4000),
+ "DESCRIPTION" VARCHAR(4000),
+ "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)
+ );