]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7688 table PROJECT_MEASURES should use component UUID
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Mon, 13 Jun 2016 09:54:01 +0000 (11:54 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 14 Jun 2016 19:19:14 +0000 (21:19 +0200)
52 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/measure/MeasureToMeasureDto.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureRepositoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/measure/MeasureToMeasureDtoTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistMeasuresStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ReportComputeMeasureVariationsStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/ViewsComputeMeasureVariationsStepTest.java
server/sonar-server/src/test/resources/org/sonar/server/computation/measure/MeasureRepositoryImplTest/shared.xml
server/sonar-server/src/test/resources/org/sonar/server/measure/MeasureFilterExecutorTest/ignore_person_measures.xml
server/sonar-server/src/test/resources/org/sonar/server/measure/MeasureFilterExecutorTest/ignore_quality_model_measures.xml
server/sonar-server/src/test/resources/org/sonar/server/measure/MeasureFilterExecutorTest/shared.xml
server/sonar-server/src/test/resources/org/sonar/server/measure/MeasureFilterExecutorTest/sort_by_alert.xml
server/sonar-web/src/main/webapp/WEB-INF/app/models/project_measure.rb
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1214_add_component_uuid_to_measures.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1215_populate_component_uuid_of_measures.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1216_delete_orphan_measures_without_component.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1217_make_component_uuid_not_null_on_measures.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1218_drop_project_id_column_from_measures.rb [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/measure/MeasureDto.java
sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java
sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java
sonar-db/src/main/java/org/sonar/db/version/v60/AddComponentUuidColumnToMeasures.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponent.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/DropProjectIdColumnFromMeasures.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasures.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/PopulateComponentUuidOfMeasures.java [new file with mode: 0644]
sonar-db/src/main/resources/org/sonar/db/measure/MeasureMapper.xml
sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql
sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl
sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
sonar-db/src/test/java/org/sonar/db/measure/MeasureTesting.java
sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java
sonar-db/src/test/java/org/sonar/db/version/v60/AddComponentUuidColumnToMeasuresTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponentTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/DropProjectIdColumnFromMeasuresTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasuresTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/PopulateComponentUuidOfMeasuresTest.java [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml
sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml
sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/select_by_snapshot_and_metric_keys.xml
sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml
sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/with_some_measures_for_developer.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot-result.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot-result.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteWastedMeasuresWhenPurgingSnapshot.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot-result.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot.xml
sonar-db/src/test/resources/org/sonar/db/version/v60/AddComponentUuidColumnToMeasuresTest/project_measures_5.6.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponentTest/in_progress_project_measures.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasuresTest/in_progress_project_measures.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateComponentUuidOfMeasuresTest/in_progress_measures_with_projects.sql [new file with mode: 0644]

index 355a08eb7f06ef84733b0c9cbaae33484870d157..bcee6b62bca43dae5eb58c66b82df1c84de49de0 100644 (file)
@@ -39,7 +39,7 @@ public class MeasureToMeasureDto {
   public MeasureDto toMeasureDto(Measure measure, Metric metric, Component component) {
     MeasureDto out = new MeasureDto();
     out.setMetricId(metric.getId());
-    out.setComponentId(dbIdsRepository.getComponentId(component));
+    out.setComponentUuid(component.getUuid());
     out.setSnapshotId(dbIdsRepository.getSnapshotId(component));
     if (measure.hasVariations()) {
       setVariations(out, measure.getVariations());
index 8f21d3669aeebe684b3f8db1c26d4240fab955d4..42530009c89aea949b1e7ff6dac88d48c9e799f9 100644 (file)
@@ -34,13 +34,11 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
-import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.rule.RuleDto;
 import org.sonar.scanner.protocol.output.ScannerReport;
 import org.sonar.scanner.protocol.output.ScannerReport.Measure.StringValue;
 import org.sonar.server.computation.batch.BatchReportReader;
@@ -84,10 +82,9 @@ public class MeasureRepositoryImplTest {
   private final Metric metric2 = mock(Metric.class);
   private static final long LAST_SNAPSHOT_ID = 123;
   private static final long OTHER_SNAPSHOT_ID = 369;
-  private static final long COMPONENT_ID = 567;
+  private static final String COMPONENT_UUID = "UUID1";
   private static final Measure SOME_MEASURE = Measure.newMeasureBuilder().create("some value");
   private static final String SOME_DATA = "some data";
-  private static final RuleDto SOME_RULE = RuleDto.createFor(RuleKey.of("A", "1")).setId(963);
 
   private ReportMetricValidator reportMetricValidator = mock(ReportMetricValidator.class);
 
@@ -143,8 +140,8 @@ public class MeasureRepositoryImplTest {
   @Test
   public void getBaseMeasure_returns_Measure_if_measure_of_last_snapshot_only_in_DB() {
     dbTester.prepareDbUnit(getClass(), "shared.xml");
-    dbClient.measureDao().insert(dbSession, createMeasureDto(METRIC_ID_1, LAST_SNAPSHOT_ID));
-    dbClient.measureDao().insert(dbSession, createMeasureDto(METRIC_ID_2, OTHER_SNAPSHOT_ID));
+    dbClient.measureDao().insert(dbSession, createMeasureDto(METRIC_ID_1, FILE_COMPONENT.getUuid(), LAST_SNAPSHOT_ID));
+    dbClient.measureDao().insert(dbSession, createMeasureDto(METRIC_ID_2, FILE_COMPONENT.getUuid(), OTHER_SNAPSHOT_ID));
     dbSession.commit();
 
     // metric 1 is associated to snapshot with "last=true"
@@ -419,9 +416,9 @@ public class MeasureRepositoryImplTest {
     assertThat(rawMeasures.get(METRIC_KEY_2)).containsOnly(Measure.newMeasureBuilder().create("some value"));
   }
 
-  private static MeasureDto createMeasureDto(int metricId, long snapshotId) {
+  private static MeasureDto createMeasureDto(int metricId, String componentUuid, long snapshotId) {
     return new MeasureDto()
-      .setComponentId(COMPONENT_ID)
+      .setComponentUuid(componentUuid)
       .setSnapshotId(snapshotId)
       .setData(SOME_DATA)
       .setMetricId(metricId);
index 6269fa2e6598e965d503cc96ff9a12509c0e54ad..ea336c32f8fe4bbe3b05c38214239345a1474b37 100644 (file)
@@ -134,7 +134,7 @@ public class MeasureToMeasureDtoTest {
   public void toMeasureDto_set_componentId_and_snapshotId_from_method_arguments(Measure measure, Metric metric) {
     MeasureDto measureDto = underTest.toMeasureDto(measure, metric, SOME_COMPONENT);
 
-    assertThat(measureDto.getComponentId()).isEqualTo(SOME_COMPONENT_ID);
+    assertThat(measureDto.getComponentUuid()).isEqualTo(SOME_COMPONENT.getUuid());
     assertThat(measureDto.getSnapshotId()).isEqualTo(SOME_SNAPSHOT_ID);
   }
 
index f62a579d8d50b5641e2d8871c7e85aafbe5c5d8e..37d66d469c3c1c94e3d2c21ed299654211e99746 100644 (file)
@@ -26,7 +26,6 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.measures.Metric;
 import org.sonar.api.utils.System2;
-import org.sonar.core.util.Uuids;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.db.component.ComponentDto;
@@ -108,13 +107,13 @@ public class PersistMeasuresStepTest extends BaseStepTest {
   }
 
   private void setupReportComponents() {
-    Component project = ReportComponent.builder(PROJECT, ROOT_REF)
+    Component project = ReportComponent.builder(PROJECT, ROOT_REF).setUuid("root-uuid")
       .addChildren(
-        ReportComponent.builder(MODULE, INTERMEDIATE_1_REF)
+        ReportComponent.builder(MODULE, INTERMEDIATE_1_REF).setUuid("intermediate1-uuid")
           .addChildren(
-            ReportComponent.builder(DIRECTORY, INTERMEDIATE_2_REF)
+            ReportComponent.builder(DIRECTORY, INTERMEDIATE_2_REF).setUuid("intermediate2-uuid")
               .addChildren(
-                ReportComponent.builder(FILE, LEAF_REF)
+                ReportComponent.builder(FILE, LEAF_REF).setUuid("leaf-uuid")
                   .build())
               .build())
           .build())
@@ -125,13 +124,13 @@ public class PersistMeasuresStepTest extends BaseStepTest {
   }
 
   private void setupViewsComponents() {
-    Component view = ViewsComponent.builder(VIEW, ROOT_REF)
+    Component view = ViewsComponent.builder(VIEW, ROOT_REF).setUuid("root-uuid")
       .addChildren(
-        ViewsComponent.builder(SUBVIEW, INTERMEDIATE_1_REF)
+        ViewsComponent.builder(SUBVIEW, INTERMEDIATE_1_REF).setUuid("intermediate1-uuid")
           .addChildren(
-            ViewsComponent.builder(SUBVIEW, INTERMEDIATE_2_REF)
+            ViewsComponent.builder(SUBVIEW, INTERMEDIATE_2_REF).setUuid("intermediate2-uuid")
               .addChildren(
-                ViewsComponent.builder(PROJECT_VIEW, LEAF_REF)
+                ViewsComponent.builder(PROJECT_VIEW, LEAF_REF).setUuid("leaf-uuid")
                   .build())
               .build())
           .build())
@@ -142,10 +141,10 @@ public class PersistMeasuresStepTest extends BaseStepTest {
   }
 
   private void setupDbIds() {
-    rootDto = addComponent("root-key");
-    intermediate1Dto = addComponent("intermediate1-key");
-    intermediate2Dto = addComponent("intermediate2-key");
-    leafDto = addComponent("leaf-key");
+    rootDto = addComponent("root-key", "root-uuid");
+    intermediate1Dto = addComponent("intermediate1-key", "intermediate1-uuid");
+    intermediate2Dto = addComponent("intermediate2-key", "intermediate2-uuid");
+    leafDto = addComponent("leaf-key", "leaf-uuid");
 
     setDbIds(ROOT_REF, rootDto.getId(), ROOT_SNAPSHOT_ID);
     setDbIds(INTERMEDIATE_1_REF, intermediate1Dto.getId(), INTERMEDIATE_1_SNAPSHOT_ID);
@@ -195,7 +194,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
 
     Map<String, Object> dto = dtos.get(0);
     assertThat(dto.get("snapshotId")).isEqualTo(ROOT_SNAPSHOT_ID);
-    assertThat(dto.get("componentId")).isEqualTo(rootDto.getId());
+    assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
     assertThat(dto.get("metricId")).isEqualTo((long) stringMetricId);
     assertThat(dto.get("value")).isNull();
     assertThat(dto.get("textValue")).isEqualTo("measure-data");
@@ -203,7 +202,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
 
     dto = dtos.get(1);
     assertThat(dto.get("snapshotId")).isEqualTo(INTERMEDIATE_1_SNAPSHOT_ID);
-    assertThat(dto.get("componentId")).isEqualTo(intermediate1Dto.getId());
+    assertThat(dto.get("componentUuid")).isEqualTo(intermediate1Dto.uuid());
     assertThat(dto.get("metricId")).isEqualTo((long) intMetricId);
     assertValue(dto, 12d);
     assertThat(dto.get("textValue")).isNull();
@@ -211,7 +210,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
 
     dto = dtos.get(2);
     assertThat(dto.get("snapshotId")).isEqualTo(INTERMEDIATE_2_SNAPSHOT_ID);
-    assertThat(dto.get("componentId")).isEqualTo(intermediate2Dto.getId());
+    assertThat(dto.get("componentUuid")).isEqualTo(intermediate2Dto.uuid());
     assertThat(dto.get("metricId")).isEqualTo((long) longMetricId);
     assertValue(dto, 9635d);
     assertThat(dto.get("textValue")).isNull();
@@ -219,7 +218,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
 
     dto = dtos.get(3);
     assertThat(dto.get("snapshotId")).isEqualTo(LEAF_SNAPSHOT_ID);
-    assertThat(dto.get("componentId")).isEqualTo(leafDto.getId());
+    assertThat(dto.get("componentUuid")).isEqualTo(leafDto.uuid());
     assertThat(dto.get("metricId")).isEqualTo((long) doubleMetricId);
     assertValue(dto, 123.1d);
     assertThat(dto.get("textValue")).isNull();
@@ -325,7 +324,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
 
     Map<String, Object> dto = dtos.get(0);
     assertThat(dto.get("snapshotId")).isEqualTo(ROOT_SNAPSHOT_ID);
-    assertThat(dto.get("componentId")).isEqualTo(rootDto.getId());
+    assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
     assertThat(dto.get("textValue")).isEqualTo("0=1;2=10");
   }
 
@@ -346,7 +345,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
 
     Map<String, Object> dto = dtos.get(0);
     assertThat(dto.get("snapshotId")).isEqualTo(ROOT_SNAPSHOT_ID);
-    assertThat(dto.get("componentId")).isEqualTo(rootDto.getId());
+    assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
     assertThat(dto.get("textValue")).isEqualTo("0=1;2=10");
   }
 
@@ -367,7 +366,7 @@ public class PersistMeasuresStepTest extends BaseStepTest {
 
     Map<String, Object> dto = dtos.get(0);
     assertThat(dto.get("snapshotId")).isEqualTo(ROOT_SNAPSHOT_ID);
-    assertThat(dto.get("componentId")).isEqualTo(rootDto.getId());
+    assertThat(dto.get("componentUuid")).isEqualTo(rootDto.uuid());
     assertThat(dto.get("textValue")).isEqualTo("0=1;2=10");
   }
 
@@ -391,8 +390,8 @@ public class PersistMeasuresStepTest extends BaseStepTest {
     assertThat(dto.get("developerId")).isEqualTo(10L);
   }
 
-  private ComponentDto addComponent(String key) {
-    ComponentDto componentDto = new ComponentDto().setKey(key).setUuid(Uuids.create());
+  private ComponentDto addComponent(String key, String uuid) {
+    ComponentDto componentDto = new ComponentDto().setKey(key).setUuid(uuid);
     dbClient.componentDao().insert(dbTester.getSession(), componentDto);
     return componentDto;
   }
@@ -404,16 +403,16 @@ public class PersistMeasuresStepTest extends BaseStepTest {
   private List<Map<String, Object>> selectSnapshots() {
     return dbTester
       .select(
-        "SELECT snapshot_id as \"snapshotId\", project_id as \"componentId\", metric_id as \"metricId\",  person_id as \"developerId\", "
-          +
-          "value as \"value\", text_value as \"textValue\", " +
-          "variation_value_1 as \"variation_value_1\", " +
-          "variation_value_2 as \"variation_value_2\", " +
-          "variation_value_3 as \"variation_value_3\", " +
-          "variation_value_4 as \"variation_value_4\", " +
-          "variation_value_5 as \"variation_value_5\"" +
-          "FROM project_measures " +
-          "ORDER by snapshot_id asc");
+        "SELECT snapshot_id as \"snapshotId\", component_uuid as \"componentUuid\", metric_id as \"metricId\", person_id as \"developerId\", "
+        +
+        "value as \"value\", text_value as \"textValue\", " +
+        "variation_value_1 as \"variation_value_1\", " +
+        "variation_value_2 as \"variation_value_2\", " +
+        "variation_value_3 as \"variation_value_3\", " +
+        "variation_value_4 as \"variation_value_4\", " +
+        "variation_value_5 as \"variation_value_5\"" +
+        "FROM project_measures " +
+        "ORDER by snapshot_id asc");
   }
 
   @Override
index fd583d31ead14e9935abf1d18a2b6c97b910c861..a30a26cd2ac69a2812938e5846f3d8b30772a058 100644 (file)
@@ -98,7 +98,7 @@ public class ReportComputeMeasureVariationsStepTest {
   public void do_nothing_when_no_raw_measure() {
     SnapshotDto period1ProjectSnapshot = newSnapshotForProject(PROJECT_DTO);
     dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 60d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
@@ -126,14 +126,14 @@ public class ReportComputeMeasureVariationsStepTest {
     // Project
     SnapshotDto period1ProjectSnapshot = newSnapshotForProject(PROJECT_DTO);
     dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 60d));
 
     // Directory
     ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
     dbClient.componentDao().insert(session, directoryDto);
     SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
     dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.uuid(), period1DirectorySnapshot.getId(), 10d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
@@ -156,14 +156,14 @@ public class ReportComputeMeasureVariationsStepTest {
     // Project
     SnapshotDto period1ProjectSnapshot = newSnapshotForProject(PROJECT_DTO);
     dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 60d));
 
     // Directory
     ComponentDto directoryDto = ComponentTesting.newDirectory(PROJECT_DTO, "dir");
     dbClient.componentDao().insert(session, directoryDto);
     SnapshotDto period1DirectorySnapshot = createForComponent(directoryDto, period1ProjectSnapshot);
     dbClient.snapshotDao().insert(session, period1DirectorySnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.getId(), period1DirectorySnapshot.getId(), 10d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), directoryDto.uuid(), period1DirectorySnapshot.getId(), 10d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
@@ -188,8 +188,8 @@ public class ReportComputeMeasureVariationsStepTest {
     SnapshotDto currentProjectSnapshot = newSnapshotForProject(PROJECT_DTO).setCreatedAt(2000_000_000L);
     dbClient.snapshotDao().insert(session, past1ProjectSnapshot);
     dbClient.snapshotDao().insert(session, currentProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), past1ProjectSnapshot.getId(), 60d));
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), currentProjectSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), past1ProjectSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), currentProjectSnapshot.getId(), 60d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, past1ProjectSnapshot));
@@ -219,11 +219,11 @@ public class ReportComputeMeasureVariationsStepTest {
     dbClient.snapshotDao().insert(session, period1ProjectSnapshot, period2ProjectSnapshot, period3ProjectSnapshot, period4ProjectSnapshot, period5ProjectSnapshot);
 
     dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 0d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period2ProjectSnapshot.getId(), 20d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period3ProjectSnapshot.getId(), 40d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period4ProjectSnapshot.getId(), 80d),
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period5ProjectSnapshot.getId(), 100d));
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 0d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period2ProjectSnapshot.getId(), 20d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period3ProjectSnapshot.getId(), 40d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period4ProjectSnapshot.getId(), 80d),
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period5ProjectSnapshot.getId(), 100d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot),
@@ -254,10 +254,10 @@ public class ReportComputeMeasureVariationsStepTest {
     SnapshotDto period1ProjectSnapshot = newSnapshotForProject(PROJECT_DTO);
     dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
     dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d),
-      newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 10d),
-      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 2d),
-      newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 1d));
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 60d),
+      newMeasureDto(DEBT_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 10d),
+      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 2d),
+      newMeasureDto(BUILD_BREAKER_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 1d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
@@ -284,7 +284,7 @@ public class ReportComputeMeasureVariationsStepTest {
     SnapshotDto period1ProjectSnapshot = newSnapshotForProject(PROJECT_DTO);
     dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
     dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+      newMeasureDto(ISSUES_METRIC.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 60d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
@@ -305,7 +305,7 @@ public class ReportComputeMeasureVariationsStepTest {
   public void does_not_update_existing_variations() throws Exception {
     SnapshotDto period1ProjectSnapshot = newSnapshotForProject(PROJECT_DTO);
     dbClient.snapshotDao().insert(session, period1ProjectSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(NEW_DEBT.getId(), PROJECT_DTO.getId(), period1ProjectSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(NEW_DEBT.getId(), PROJECT_DTO.uuid(), period1ProjectSnapshot.getId(), 60d));
     session.commit();
     periodsHolder.setPeriods(newPeriod(1, period1ProjectSnapshot));
     treeRootHolder.setRoot(PROJECT);
@@ -318,8 +318,8 @@ public class ReportComputeMeasureVariationsStepTest {
     assertThat(measureRepository.getRawMeasure(PROJECT, NEW_DEBT).get().getVariations().getVariation1()).isEqualTo(10d);
   }
 
-  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
-    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+  private static MeasureDto newMeasureDto(int metricId, String componentUuid, long snapshotId, double value) {
+    return new MeasureDto().setMetricId(metricId).setComponentUuid(componentUuid).setSnapshotId(snapshotId).setValue(value);
   }
 
   private static Period newPeriod(int index, SnapshotDto snapshotDto) {
index 493c6dfbd24e45a58fafa60ccf2243b613105696..4f5cef4e49c9c3ec272ea80bb6e0bb44f8fff165 100644 (file)
@@ -98,7 +98,7 @@ public class ViewsComputeMeasureVariationsStepTest {
   public void do_nothing_when_no_raw_measure() {
     SnapshotDto period1ViewSnapshot = newSnapshotForView(VIEW_DTO);
     dbClient.snapshotDao().insert(session, period1ViewSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period1ViewSnapshot.getId(), 60d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
@@ -126,14 +126,14 @@ public class ViewsComputeMeasureVariationsStepTest {
     // View
     SnapshotDto period1ViewSnapshot = newSnapshotForView(VIEW_DTO);
     dbClient.snapshotDao().insert(session, period1ViewSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period1ViewSnapshot.getId(), 60d));
 
     // SubView
     ComponentDto subviewDto = ComponentTesting.newSubView(VIEW_DTO, "dir", "key");
     dbClient.componentDao().insert(session, subviewDto);
     SnapshotDto period1SubviewSnapshot = createForComponent(subviewDto, period1ViewSnapshot);
     dbClient.snapshotDao().insert(session, period1SubviewSnapshot);
-    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.getId(), period1SubviewSnapshot.getId(), 10d));
+    dbClient.measureDao().insert(session, newMeasureDto(ISSUES_METRIC.getId(), subviewDto.uuid(), period1SubviewSnapshot.getId(), 10d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot));
@@ -161,11 +161,11 @@ public class ViewsComputeMeasureVariationsStepTest {
     dbClient.snapshotDao().insert(session, period1ViewSnapshot, period2ViewSnapshot, period3ViewSnapshot, period4ViewSnapshot, period5ViewSnapshot);
 
     dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 0d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period2ViewSnapshot.getId(), 20d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period3ViewSnapshot.getId(), 40d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period4ViewSnapshot.getId(), 80d),
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period5ViewSnapshot.getId(), 100d));
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period1ViewSnapshot.getId(), 0d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period2ViewSnapshot.getId(), 20d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period3ViewSnapshot.getId(), 40d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period4ViewSnapshot.getId(), 80d),
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period5ViewSnapshot.getId(), 100d));
     session.commit();
 
     periodsHolder.setPeriods(newPeriod(1, period1ViewSnapshot),
@@ -196,10 +196,10 @@ public class ViewsComputeMeasureVariationsStepTest {
     SnapshotDto period1ViewSnapshot = newSnapshotForProject(VIEW_DTO);
     dbClient.snapshotDao().insert(session, period1ViewSnapshot);
     dbClient.measureDao().insert(session,
-      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 60d),
-      newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 10d),
-      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 2d),
-      newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.getId(), period1ViewSnapshot.getId(), 1d)
+      newMeasureDto(ISSUES_METRIC.getId(), VIEW_DTO.uuid(), period1ViewSnapshot.getId(), 60d),
+      newMeasureDto(DEBT_METRIC.getId(), VIEW_DTO.uuid(), period1ViewSnapshot.getId(), 10d),
+      newMeasureDto(FILE_COMPLEXITY_METRIC.getId(), VIEW_DTO.uuid(), period1ViewSnapshot.getId(), 2d),
+      newMeasureDto(BUILD_BREAKER_METRIC.getId(), VIEW_DTO.uuid(), period1ViewSnapshot.getId(), 1d)
       );
     session.commit();
 
@@ -222,8 +222,8 @@ public class ViewsComputeMeasureVariationsStepTest {
     assertThat(measureRepository.getRawMeasure(VIEW, BUILD_BREAKER_METRIC).get().getVariations().getVariation1()).isEqualTo(-1d);
   }
 
-  private static MeasureDto newMeasureDto(int metricId, long projectId, long snapshotId, double value) {
-    return new MeasureDto().setMetricId(metricId).setComponentId(projectId).setSnapshotId(snapshotId).setValue(value);
+  private static MeasureDto newMeasureDto(int metricId, String componentUuid, long snapshotId, double value) {
+    return new MeasureDto().setMetricId(metricId).setComponentUuid(componentUuid).setSnapshotId(snapshotId).setValue(value);
   }
 
   private static Period newPeriod(int index, SnapshotDto snapshotDto) {
index 0234c9b213f4e896af591a6698913ec1a88e5aa1..87081a4e2d11fcc28043a9f8705b732cdc4409be 100644 (file)
@@ -1,7 +1,7 @@
 <dataset>
-    <projects id="567" uuid="uuid_567" kee="file cpt key" enabled="[true]"/>
-    <snapshots id="123" component_uuid="uuid_567" root_component_uuid="uuid_567" islast="[true]"/>
-    <snapshots id="369" component_uuid="uuid_567" root_component_uuid="uuid_567" islast="[false]"/>
+    <projects id="567" uuid="uuid_1" kee="file cpt key" enabled="[true]"/>
+    <snapshots id="123" component_uuid="uuid_1" root_component_uuid="uuid_1" islast="[true]"/>
+    <snapshots id="369" component_uuid="uuid_1" root_component_uuid="uuid_1" islast="[false]"/>
     <metrics id="1" name="metric 1"  />
     <metrics id="2" name="metric 2" />
 </dataset>
index 9ba1f33cfe7cf4d60d3b6a080155e01f3c2a206a..18a411ee2f80333cde55053e47bd9e2f6beaf4ca 100644 (file)
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
+                    text_value="[null]"
+                    component_uuid="ABCD"
+                    alert_status="[null]"
+                    description="[null]"/>
 
   <!-- details of the measure by person -->
   <project_measures id="1002" metric_id="1" value="300" snapshot_id="101" person_id="30000"
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
+                    text_value="[null]"
+                    component_uuid="ABCD"
+                    alert_status="[null]"
+                    description="[null]"/>
 
   <project_measures id="1003" metric_id="1" value="200" snapshot_id="101" person_id="40000"
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
+                    text_value="[null]"
+                    component_uuid="ABCD"
+                    alert_status="[null]"
+                    description="[null]"/>
 
 </dataset>
index c99bd38bfc0efc772615a1dbdb8a67db4701e2e9..f5befccaa1f88b4678ed0b5d89d57e1f967ceba1 100644 (file)
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]" person_id="[null]"/>
+                    text_value="[null]"
+                    component_uuid="ABCD"
+                    alert_status="[null]" description="[null]"
+                    person_id="[null]"/>
 
   <!-- details of the measure by model characteristic -->
   <!--project_measures id="1002" metric_id="1" value="300" snapshot_id="101" characteristic_id="30000"
                     url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
                     rule_priority="[null]" alert_text="[null]" RULES_CATEGORY_ID="[null]"
-                    text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
+                    RULE_ID="[null]" text_value="[null]"
+                    component_uuid="ABCD"
                     alert_status="[null]" description="[null]" person_id="[null]"/>-->
 
   <!--project_measures id="1003" metric_id="1" value="200" snapshot_id="101" characteristic_id="40000"
                     url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
-                    rule_priority="[null]" alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    alert_text="[null]" RULES_CATEGORY_ID="[null]"
+                    RULE_ID="[null]" text_value="[null]" tendency="[null]" measure_date="[null]" component_uuid="ABCD"
+                    alert_status="[null]" description="[null]" person_id="[null]"/>
                     text_value="[null]" tendency="[null]" measure_date="[null]" project_id="[null]"
                     alert_status="[null]" description="[null]" person_id="[null]"/>-->
 
index dcf925a251f820aac28a938d640b15c392177758..8a1250ea2bacfef53c6ea426a845a3c7f9e588db 100644 (file)
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
+                    text_value="[null]" component_uuid="ABCD"
                     alert_status="[null]" description="[null]"/>
 
   <project_measures id="1002" metric_id="1" value="510" snapshot_id="102"
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
+                    text_value="[null]"
+                    alert_status="[null]" description="[null]"
+                    component_uuid="BCDE" />
 
   <project_measures id="1003" metric_id="1" value="500" snapshot_id="103"
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
+                    text_value="[null]"
+                    alert_status="[null]" description="[null]"
+                    component_uuid="CDEF" />
 
   <project_measures id="1004" metric_id="1" value="10" snapshot_id="104"
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
-                    alert_status="[null]" description="[null]"/>
+                    text_value="[null]"
+                    alert_status="[null]" description="[null]"
+                    component_uuid="DEFG"/>
 
   <!-- profile of java project -->
   <project_measures id="1005" metric_id="2" value="[null]" snapshot_id="101"
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="Sonar way" project_id="[null]"
+                    text_value="Sonar way"
+                    component_uuid="ABCD"
                     alert_status="[null]" description="[null]"/>
 
   <!-- coverage of java project -->
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                       variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="Sonar way" project_id="[null]"
+                    text_value="Sonar way"
+                    component_uuid="ABCD"
                     alert_status="[null]" description="[null]"/>
 
   <!-- php project -->
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="4900"
                     alert_text="[null]"
-                    text_value="[null]" project_id="[null]"
+                    text_value="[null]"
+                    component_uuid="EFGH"
                     alert_status="[null]" description="[null]"/>
 
   <project_measures id="1011" metric_id="2" value="[null]" snapshot_id="110"
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="php way" project_id="[null]"
+                    text_value="php way"
+                    component_uuid="EFGH"
                     alert_status="[null]" description="[null]"/>
 
 
index f3ed36c2b406098a0c5b95b00139835be3a19194..3e944c47343082777615e595a6d830f41099957f 100644 (file)
@@ -26,7 +26,8 @@
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="400"
                     alert_text="[null]"
-                    text_value="WARN" project_id="[null]"
+                    text_value="WARN"
+                    component_uuid="ABCD"
                     alert_status="[null]" description="[null]"/>
 
   <!-- php project -->
@@ -50,7 +51,8 @@
                     url="[null]" variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="OK" project_id="[null]"
+                    text_value="OK"
+                    component_uuid="BCDE"
                     alert_status="[null]" description="[null]"/>
 
   <!-- js project -->
@@ -74,7 +76,8 @@
                     variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
                     variation_value_4="[null]" variation_value_5="[null]"
                     alert_text="[null]"
-                    text_value="ERROR" project_id="[null]"
+                    text_value="ERROR"
+                    component_uuid="CDEF"
                     alert_status="[null]" description="[null]"/>
 
 
index bd56a6cc8548bb2b031599e1aba15094aa6a0a6d..526b10d63ae82cee76394cf200ff43e0ac32bc85 100644 (file)
@@ -26,7 +26,7 @@ class ProjectMeasure < ActiveRecord::Base
   DAY = 1000 * 60 * 60 * 24
 
   belongs_to :snapshot
-  belongs_to :project
+  belongs_to :project, :class_name => 'Project', :foreign_key => 'component_uuid', :primary_key => 'uuid'
   belongs_to :person, :class_name => 'Project', :foreign_key => 'person_id'
 
   def metric
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1214_add_component_uuid_to_measures.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1214_add_component_uuid_to_measures.rb
new file mode 100644 (file)
index 0000000..53279d5
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# 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 AddComponentUuidToMeasures < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.AddComponentUuidColumnToMeasures')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1215_populate_component_uuid_of_measures.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1215_populate_component_uuid_of_measures.rb
new file mode 100644 (file)
index 0000000..55a6a8b
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# 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 PopulateComponentUuidOfMeasures < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.PopulateComponentUuidOfMeasures')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1216_delete_orphan_measures_without_component.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1216_delete_orphan_measures_without_component.rb
new file mode 100644 (file)
index 0000000..e94e0a7
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# 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 DeleteOrphanMeasuresWithoutComponent < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.DeleteOrphanMeasuresWithoutComponent')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1217_make_component_uuid_not_null_on_measures.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1217_make_component_uuid_not_null_on_measures.rb
new file mode 100644 (file)
index 0000000..5de3fec
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# 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 MakeComponentUuidNotNullOnMeasures < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.MakeComponentUuidNotNullOnMeasures')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1218_drop_project_id_column_from_measures.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1218_drop_project_id_column_from_measures.rb
new file mode 100644 (file)
index 0000000..706d60b
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# 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 DropProjectIdColumnFromMeasures < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.DropProjectIdColumnFromMeasures')
+  end
+end
index bf71e0dbe8d5ad4023f2ff3edb9eed00e9e7d2a6..b8ffe2469cbf94949030c8b34df2b23254b5f863 100644 (file)
@@ -40,8 +40,7 @@ public class MeasureDto {
   private String alertStatus;
   private String alertText;
   private String description;
-
-  private Long componentId;
+  private String componentUuid;
   private Long snapshotId;
   private Integer metricId;
   private Long developerId;
@@ -68,6 +67,15 @@ public class MeasureDto {
     return this;
   }
 
+  public String getComponentUuid() {
+    return componentUuid;
+  }
+
+  public MeasureDto setComponentUuid(String s) {
+    this.componentUuid = s;
+    return this;
+  }
+
   @CheckForNull
   public String getData() {
     if (dataValue != null) {
@@ -162,15 +170,6 @@ public class MeasureDto {
     return this;
   }
 
-  public Long getComponentId() {
-    return componentId;
-  }
-
-  public MeasureDto setComponentId(Long componentId) {
-    this.componentId = componentId;
-    return this;
-  }
-
   public Integer getMetricId() {
     return metricId;
   }
@@ -239,7 +238,7 @@ public class MeasureDto {
       .add("alertStatus", alertStatus)
       .add("alertText", alertText)
       .add("description", description)
-      .add("componentId", componentId)
+      .add("componentUuid", componentUuid)
       .add("snapshotId", snapshotId)
       .add("metricId", metricId)
       .add("developerId", developerId)
index 1175f6c9260ded4ba19c09e13124ac77182d196e..ebdc4218ffbc92d95cb12a926c333c23ff84eca3 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.db.MyBatis;
 
 public class DatabaseVersion {
 
-  public static final int LAST_VERSION = 1_213;
+  public static final int LAST_VERSION = 1_218;
 
   /**
    * The minimum supported version which can be upgraded. Lower
index 22486d912a69fdcf319d5d2a4b7dedfdc45a58ec..35bb3c2b1c6ba669daa2c2e23a42886a3e805e96 100644 (file)
@@ -83,15 +83,20 @@ import org.sonar.db.version.v55.FeedRulesLongDateColumns;
 import org.sonar.db.version.v55.FeedRulesTypes;
 import org.sonar.db.version.v56.FixLengthOfIssuesMessageOnOracle;
 import org.sonar.db.version.v56.FixTypeOfRuleTypeOnMysql;
+import org.sonar.db.version.v60.AddComponentUuidColumnToMeasures;
 import org.sonar.db.version.v60.AddUuidColumnsToResourceIndex;
 import org.sonar.db.version.v60.AddUuidColumnsToSnapshots;
 import org.sonar.db.version.v60.CleanOrphanRowsInResourceIndex;
 import org.sonar.db.version.v60.CleanOrphanRowsInSnapshots;
+import org.sonar.db.version.v60.DeleteOrphanMeasuresWithoutComponent;
 import org.sonar.db.version.v60.DropIdColumnsFromResourceIndex;
 import org.sonar.db.version.v60.DropUnusedMeasuresColumns;
 import org.sonar.db.version.v60.DropIdColumnsFromSnapshots;
+import org.sonar.db.version.v60.DropProjectIdColumnFromMeasures;
+import org.sonar.db.version.v60.MakeComponentUuidNotNullOnMeasures;
 import org.sonar.db.version.v60.MakeUuidColumnsNotNullOnResourceIndex;
 import org.sonar.db.version.v60.MakeUuidColumnsNotNullOnSnapshots;
+import org.sonar.db.version.v60.PopulateComponentUuidOfMeasures;
 import org.sonar.db.version.v60.PopulateUuidColumnsOfResourceIndex;
 import org.sonar.db.version.v60.PopulateUuidColumnsOfSnapshots;
 
@@ -189,6 +194,11 @@ public class MigrationStepModule extends Module {
       PopulateUuidColumnsOfSnapshots.class,
       CleanOrphanRowsInSnapshots.class,
       MakeUuidColumnsNotNullOnSnapshots.class,
-      DropIdColumnsFromSnapshots.class);
+      DropIdColumnsFromSnapshots.class,
+      AddComponentUuidColumnToMeasures.class,
+      PopulateComponentUuidOfMeasures.class,
+      DeleteOrphanMeasuresWithoutComponent.class,
+      MakeComponentUuidNotNullOnMeasures.class,
+      DropProjectIdColumnFromMeasures.class);
   }
 }
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/AddComponentUuidColumnToMeasures.java b/sonar-db/src/main/java/org/sonar/db/version/v60/AddComponentUuidColumnToMeasures.java
new file mode 100644 (file)
index 0000000..0a834cb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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 AddComponentUuidColumnToMeasures extends DdlChange {
+
+  private static final String TABLE_MEASURES = "project_measures";
+
+  public AddComponentUuidColumnToMeasures(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddColumnsBuilder(getDatabase().getDialect(), TABLE_MEASURES)
+      .addColumn(newVarcharColumnDefBuilder().setColumnName("component_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(true).build())
+      .build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponent.java b/sonar-db/src/main/java/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponent.java
new file mode 100644 (file)
index 0000000..1946c3e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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 DeleteOrphanMeasuresWithoutComponent extends BaseDataChange {
+
+  public DeleteOrphanMeasuresWithoutComponent(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select("SELECT id from project_measures where component_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;
+    });
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/DropProjectIdColumnFromMeasures.java b/sonar-db/src/main/java/org/sonar/db/version/v60/DropProjectIdColumnFromMeasures.java
new file mode 100644 (file)
index 0000000..45b5cc7
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.DdlChange;
+import org.sonar.db.version.DropColumnsBuilder;
+
+public class DropProjectIdColumnFromMeasures extends DdlChange {
+
+  private static final String TABLE_MEASURES = "project_measures";
+
+  public DropProjectIdColumnFromMeasures(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(
+      new DropColumnsBuilder(getDatabase().getDialect(), TABLE_MEASURES, "project_id").build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasures.java b/sonar-db/src/main/java/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasures.java
new file mode 100644 (file)
index 0000000..8c01e07
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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 MakeComponentUuidNotNullOnMeasures extends DdlChange {
+
+  private static final String TABLE_MEASURES = "project_measures";
+
+  public MakeComponentUuidNotNullOnMeasures(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AlterColumnsBuilder(getDatabase().getDialect(), TABLE_MEASURES)
+      .updateColumn(newVarcharColumnDefBuilder().setColumnName("component_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(false).build())
+      .build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateComponentUuidOfMeasures.java b/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateComponentUuidOfMeasures.java
new file mode 100644 (file)
index 0000000..7dd23cc
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.HashMap;
+import java.util.Map;
+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 PopulateComponentUuidOfMeasures extends BaseDataChange {
+
+  public PopulateComponentUuidOfMeasures(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    Map<Long, String> componentUuidById = buildComponentUuidMap(context);
+    if (componentUuidById.isEmpty()) {
+      return;
+    }
+
+    populateUuidColumns(context, componentUuidById);
+  }
+
+  private Map<Long, String> buildComponentUuidMap(Context context) throws SQLException {
+    Map<Long, String> componentUuidById = new HashMap<>();
+    context.prepareSelect("select distinct p.id, p.uuid from projects p" +
+      " join project_measures pm on pm.project_id = p.id and pm.component_uuid is null")
+      .scroll(row -> componentUuidById.put(row.getLong(1), row.getString(2)));
+    return componentUuidById;
+  }
+
+  private void populateUuidColumns(Context context, Map<Long, String> componentUuidById) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select("SELECT pm.id, pm.project_id from project_measures pm where pm.component_uuid is null");
+    massUpdate.update("UPDATE project_measures SET component_uuid=? WHERE id=?");
+    massUpdate.rowPluralName("measures");
+    massUpdate.execute((row, update) -> this.handle(componentUuidById, row, update));
+  }
+
+  public boolean handle(Map<Long, String> componentUuidById, Select.Row row, SqlStatement update) throws SQLException {
+    long id = row.getLong(1);
+    long componentId = row.getLong(2);
+
+    String componentUuid = componentUuidById.get(componentId);
+
+    if (componentUuid == null) {
+      return false;
+    }
+
+    update.setString(1, componentUuid);
+    update.setLong(2, id);
+
+    return true;
+  }
+
+}
index 90c5a3dde465dd326ef86b00056d752930b18632..f2e85bb036c887a1960b5dec92f0733b8629ac04 100644 (file)
@@ -6,6 +6,7 @@
     pm.id,
     pm.metric_id as metricId,
     pm.person_id as developerId,
+    pm.component_uuid as componentUuid,
     pm.snapshot_id as snapshotId,
     pm.value as value,
     pm.text_value as textValue,
@@ -29,7 +30,7 @@
     <include refid="extendedMeasureColumns"/>
     FROM project_measures pm
     INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true}
-    INNER JOIN projects p ON p.uuid=s.component_uuid AND p.enabled=${_true}
+    INNER JOIN projects p ON p.uuid=pm.component_uuid AND p.enabled=${_true}
     INNER JOIN metrics metric ON metric.id=pm.metric_id
     <where>
       AND p.kee = #{componentKey}
@@ -43,7 +44,7 @@
     <include refid="extendedMeasureColumns"/>
     FROM project_measures pm
     INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true}
-    INNER JOIN projects p ON p.uuid=s.component_uuid AND p.enabled=${_true}
+    INNER JOIN projects p ON p.uuid=pm.component_uuid AND p.enabled=${_true}
     INNER JOIN metrics metric ON metric.id=pm.metric_id
     <where>
       AND p.kee = #{componentKey}
     INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.islast=${_true}
     INNER JOIN metrics metric ON metric.id=pm.metric_id
     INNER JOIN projects p ON p.uuid=s.component_uuid AND p.enabled=${_true}
-    <where>
-      AND p.kee = #{componentKey}
+    WHERE
+      p.kee = #{componentKey}
       AND metric.name = #{metricKey}
       AND pm.person_id IS NULL
-    </where>
   </select>
 
   <select id="selectByComponentUuidAndProjectSnapshotIdAndStatusAndMetricIds" parameterType="map"
     FROM project_measures pm
     INNER JOIN snapshots s ON s.id=pm.snapshot_id AND s.status=#{status}
     INNER JOIN projects p ON p.uuid=s.component_uuid AND p.enabled=${_true}
-    <where>
-      AND p.uuid = #{componentUuid}
+    WHERE
+      <!-- do not filter on pm.component_uuid in order to benefit from index on p.uuid -->
+      p.uuid=#{componentUuid}
       AND (s.root_snapshot_id=#{rootSnapshotId} OR s.id=#{rootSnapshotId})
       AND
       <foreach item="metricId" index="index" collection="metricIds" open="(" separator=" or " close=")">
         pm.metric_id=#{metricId}
       </foreach>
       AND pm.person_id IS NULL
-    </where>
   </select>
 
   <insert id="insert" parameterType="Measure" useGeneratedKeys="false">
     INSERT INTO project_measures (
-    value, metric_id, snapshot_id, text_value, project_id, alert_status, alert_text, description,
+    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)
     VALUES (
-    #{value, jdbcType=DOUBLE}, #{metricId, jdbcType=INTEGER}, #{snapshotId, jdbcType=INTEGER},
+    #{value, jdbcType=DOUBLE}, #{metricId, jdbcType=INTEGER}, #{componentUuid, jdbcType=VARCHAR},
+    #{snapshotId, jdbcType=INTEGER},
     #{textValue, jdbcType=VARCHAR},
-    #{componentId, jdbcType=INTEGER}, #{alertStatus, jdbcType=VARCHAR}, #{alertText, jdbcType=VARCHAR},
+    #{alertStatus, jdbcType=VARCHAR}, #{alertText, jdbcType=VARCHAR},
     #{description, jdbcType=VARCHAR},
     #{developerId, jdbcType=INTEGER}, #{variation1, jdbcType=DOUBLE}, #{variation2, jdbcType=DOUBLE},
     #{variation3, jdbcType=DOUBLE},
index 8c8dee58255613dd05020afb611c1e8664d90cfc..c271e3f35a45a3e55adccfeb1b57a8935247005f 100644 (file)
@@ -420,6 +420,11 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1210');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1211');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1212');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1213');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1214');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1215');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1216');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1217');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1218');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'admin', 'sonarqube', true, 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482', null, null);
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
index cc740743516c0f33303a0d489a11b456d9a16779..ca3150776104e044bbdc224e742d52c001118f92 100644 (file)
@@ -196,9 +196,9 @@ 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),
-  "PROJECT_ID" INTEGER,
   "ALERT_STATUS" VARCHAR(5),
   "ALERT_TEXT" VARCHAR(4000),
   "DESCRIPTION" VARCHAR(4000),
index b710955955c5e2d3ffa4e975bf6de93d99769bb4..390fa58022f0a85096e8726f4bd01bcacf6417ef 100644 (file)
@@ -398,7 +398,7 @@ public class MeasureDaoTest {
 
     ComponentDto projectDto = insertProject("aa");
     SnapshotDto snapshotDto = insertSnapshot(projectDto, true);
-    insertMeasure(snapshotDto, DEVELOPER_ID, NCLOC_METRIC_ID, 12d);
+    insertMeasure(projectDto, snapshotDto, DEVELOPER_ID, NCLOC_METRIC_ID, 12d);
 
     List<MeasureDto> measureDtos = underTest.selectProjectMeasuresByDeveloperForMetrics(dbSession, DEVELOPER_ID, ImmutableList.of(NCLOC_METRIC_ID));
     assertThat(measureDtos).hasSize(1);
@@ -406,7 +406,7 @@ public class MeasureDaoTest {
     assertThat(measureDto.getId()).isNotNull();
     assertThat(measureDto.getMetricId()).isEqualTo(NCLOC_METRIC_ID);
     assertThat(measureDto.getSnapshotId()).isEqualTo(snapshotDto.getId());
-    assertThat(measureDto.getComponentId()).isEqualTo(projectDto.getId());
+    assertThat(measureDto.getComponentUuid()).isEqualTo(projectDto.uuid());
     assertThat(measureDto.getDeveloperId()).isEqualTo(DEVELOPER_ID);
 
     assertThat(underTest.selectProjectMeasuresByDeveloperForMetrics(dbSession, otherDeveloperId, ImmutableList.of(NCLOC_METRIC_ID))).isEmpty();
@@ -419,9 +419,9 @@ public class MeasureDaoTest {
 
     ComponentDto projectDto = insertProject("aa");
     SnapshotDto nonLastSnapshotDto = insertSnapshot(projectDto, false);
-    insertMeasure(nonLastSnapshotDto, DEVELOPER_ID, NCLOC_METRIC_ID, 12d);
+    insertMeasure(projectDto, nonLastSnapshotDto, DEVELOPER_ID, NCLOC_METRIC_ID, 12d);
     SnapshotDto lastSnapshotDto = insertSnapshot(projectDto, true);
-    insertMeasure(lastSnapshotDto, otherDeveloperId, NCLOC_METRIC_ID, 15d);
+    insertMeasure(projectDto, lastSnapshotDto, otherDeveloperId, NCLOC_METRIC_ID, 15d);
 
     assertThat(underTest.selectProjectMeasuresByDeveloperForMetrics(dbSession, DEVELOPER_ID, ImmutableList.of(NCLOC_METRIC_ID))).hasSize(0);
 
@@ -430,7 +430,7 @@ public class MeasureDaoTest {
     MeasureDto measureDto = measureDtos.iterator().next();
     assertThat(measureDto.getMetricId()).isEqualTo(NCLOC_METRIC_ID);
     assertThat(measureDto.getSnapshotId()).isEqualTo(lastSnapshotDto.getId());
-    assertThat(measureDto.getComponentId()).isEqualTo(projectDto.getId());
+    assertThat(measureDto.getComponentUuid()).isEqualTo(projectDto.uuid());
     assertThat(measureDto.getDeveloperId()).isEqualTo(otherDeveloperId);
     assertThat(measureDto.getValue()).isEqualTo(15d);
   }
@@ -440,11 +440,11 @@ public class MeasureDaoTest {
     ComponentDto projectDto = insertProject("aa");
     insertSnapshot(projectDto, true);
     ComponentDto moduleDto = insertComponent(ComponentTesting.newModuleDto(projectDto));
-    insertMeasure(insertSnapshot(moduleDto, true), DEVELOPER_ID, NCLOC_METRIC_ID, 15d);
+    insertMeasure(moduleDto, insertSnapshot(moduleDto, true), DEVELOPER_ID, NCLOC_METRIC_ID, 15d);
     ComponentDto dirDto = insertComponent(ComponentTesting.newDirectory(moduleDto, "toto"));
-    insertMeasure(insertSnapshot(dirDto, true), DEVELOPER_ID, NCLOC_METRIC_ID, 25d);
+    insertMeasure(dirDto, insertSnapshot(dirDto, true), DEVELOPER_ID, NCLOC_METRIC_ID, 25d);
     ComponentDto fileDto = insertComponent(ComponentTesting.newFileDto(moduleDto, "tutu"));
-    insertMeasure(insertSnapshot(fileDto, true), DEVELOPER_ID, NCLOC_METRIC_ID, 35d);
+    insertMeasure(fileDto, insertSnapshot(fileDto, true), DEVELOPER_ID, NCLOC_METRIC_ID, 35d);
 
     assertThat(underTest.selectProjectMeasuresByDeveloperForMetrics(dbSession, DEVELOPER_ID, ImmutableList.of(NCLOC_METRIC_ID))).isEmpty();
   }
@@ -468,8 +468,13 @@ public class MeasureDaoTest {
     return snapshotDto;
   }
 
-  private MeasureDto insertMeasure(SnapshotDto snapshotDto, Long developerId, int metricId, double value) {
-    MeasureDto measureDto = new MeasureDto().setMetricId(metricId).setValue(value).setSnapshotId(snapshotDto.getId()).setDeveloperId(developerId);
+  private MeasureDto insertMeasure(ComponentDto componentDto, SnapshotDto snapshotDto, Long developerId, int metricId, double value) {
+    MeasureDto measureDto = new MeasureDto()
+      .setMetricId(metricId)
+      .setValue(value)
+      .setComponentUuid(componentDto.uuid())
+      .setSnapshotId(snapshotDto.getId())
+      .setDeveloperId(developerId);
     dbClient.measureDao().insert(dbSession, measureDto);
     dbSession.commit();
     return measureDto;
@@ -483,8 +488,7 @@ public class MeasureDaoTest {
       .setSnapshotId(2L)
       .setMetricId(3)
       .setDeveloperId(23L)
-      .setRuleId(5)
-      .setComponentId(6L)
+      .setComponentUuid("FILE1")
       .setValue(2.0d)
       .setData("measure-value")
       .setVariation(1, 1.0d)
@@ -507,12 +511,12 @@ public class MeasureDaoTest {
     underTest.insert(dbSession, new MeasureDto()
       .setSnapshotId(2L)
       .setMetricId(3)
-      .setComponentId(6L)
+      .setComponentUuid("COMPONENT_1")
       .setValue(2.0d),
       new MeasureDto()
         .setSnapshotId(3L)
         .setMetricId(4)
-        .setComponentId(6L)
+        .setComponentUuid("COMPONENT_2")
         .setValue(4.0d));
     dbSession.commit();
 
index b862d76047688ef6b3a0a86b7a1ec72d9a244505..f77c8be5fb82f50e157630815918cc3aa0f121c4 100644 (file)
  */
 package org.sonar.db.measure;
 
+import org.apache.commons.lang.RandomStringUtils;
+import org.sonar.core.util.Uuids;
 import org.sonar.db.metric.MetricDto;
 
-import static org.apache.commons.lang.math.RandomUtils.nextInt;
-
 public class MeasureTesting {
   private MeasureTesting() {
     // static methods only
@@ -32,7 +32,7 @@ public class MeasureTesting {
     return new MeasureDto()
       .setMetricId(metricDto.getId())
       .setMetricKey(metricDto.getKey())
-      .setComponentId((long) nextInt())
+      .setComponentUuid(RandomStringUtils.randomAlphanumeric(Uuids.MAX_LENGTH))
       .setSnapshotId(snapshotId);
   }
 }
index 9b8567733eac7236208c9305502c3829b8c4f16c..68b3e0c0eda2d34ebd703e0cd2290f6197cb0c6a 100644 (file)
@@ -29,6 +29,6 @@ public class MigrationStepModuleTest {
   public void verify_count_of_added_MigrationStep_types() {
     ComponentContainer container = new ComponentContainer();
     new MigrationStepModule().configure(container);
-    assertThat(container.size()).isEqualTo(76);
+    assertThat(container.size()).isEqualTo(81);
   }
 }
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/AddComponentUuidColumnToMeasuresTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/AddComponentUuidColumnToMeasuresTest.java
new file mode 100644 (file)
index 0000000..414c2d9
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 AddComponentUuidColumnToMeasuresTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, AddComponentUuidColumnToMeasuresTest.class, "project_measures_5.6.sql");
+
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private AddComponentUuidColumnToMeasures underTest = new AddComponentUuidColumnToMeasures(db.database());
+
+  @Test
+  public void migration_adds_column_to_empty_table() throws SQLException {
+    underTest.execute();
+
+    verifyAddedColumns();
+  }
+
+  @Test
+  public void migration_adds_column_to_populated_table() throws SQLException {
+    for (int i = 0; i < 9; i++) {
+      db.executeInsert(
+        "project_measures",
+        "METRIC_ID", valueOf(i),
+        "VALUE", valueOf(i),
+        "SNAPSHOT_ID", valueOf(i));
+    }
+    db.commit();
+
+    underTest.execute();
+
+    verifyAddedColumns();
+  }
+
+  @Test
+  public void migration_is_not_reentrant() throws SQLException {
+    underTest.execute();
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Fail to execute ");
+    underTest.execute();
+  }
+
+  private void verifyAddedColumns() {
+    db.assertColumnDefinition("project_measures", "component_uuid", Types.VARCHAR, 50, true);
+  }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponentTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponentTest.java
new file mode 100644 (file)
index 0000000..b19ed81
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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 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 DeleteOrphanMeasuresWithoutComponentTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, DeleteOrphanMeasuresWithoutComponentTest.class,
+    "in_progress_project_measures.sql");
+
+  private DeleteOrphanMeasuresWithoutComponent underTest = new DeleteOrphanMeasuresWithoutComponent(db.database());
+
+  @Test
+  public void migration_has_no_effects_on_empty_table() throws SQLException {
+    underTest.execute();
+
+    assertThat(db.countRowsOfTable("project_measures")).isEqualTo(0);
+  }
+
+  @Test
+  public void migration_deletes_any_row_with_a_null_component_uuid() throws SQLException {
+    insertMeasure(1, true);
+    insertMeasure(2, false);
+    insertMeasure(3, false);
+    insertMeasure(4, true);
+    db.commit();
+
+    underTest.execute();
+
+    assertThat(idsOfRowsInMeasures()).containsOnly(1L, 4L);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    insertMeasure(1, true);
+    insertMeasure(2, false);
+
+    underTest.execute();
+
+    assertThat(idsOfRowsInMeasures()).containsOnly(1L);
+
+    underTest.execute();
+
+    assertThat(idsOfRowsInMeasures()).containsOnly(1L);
+  }
+
+  private List<Long> idsOfRowsInMeasures() {
+    return db.select("select ID from project_measures").stream().map(map -> (Long) map.get("ID")).collect(Collectors.toList());
+  }
+
+  private void insertMeasure(long id, boolean hasComponentUuid) {
+    db.executeInsert(
+      "project_measures",
+      "ID", valueOf(id),
+      "METRIC_ID", valueOf(id + 10),
+      "SNAPSHOT_ID", valueOf(id + 100),
+      "VALUE", valueOf(id + 1000));
+
+    if (hasComponentUuid) {
+      db.executeUpdateSql("update project_measures set COMPONENT_UUID=? where id=?", "uuid_" + id, valueOf(id));
+    }
+  }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/DropProjectIdColumnFromMeasuresTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/DropProjectIdColumnFromMeasuresTest.java
new file mode 100644 (file)
index 0000000..b30c5ab
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.junit.Test;
+import org.sonar.db.Database;
+import org.sonar.db.dialect.PostgreSql;
+import org.sonar.db.version.DdlChange;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class DropProjectIdColumnFromMeasuresTest {
+  private Database database = mock(Database.class);
+
+  private DropProjectIdColumnFromMeasures underTest = new DropProjectIdColumnFromMeasures(database);
+
+  @Test
+  public void verify_generated_sql_on_postgresql() throws SQLException {
+    when(database.getDialect()).thenReturn(new PostgreSql());
+
+    DdlChange.Context context = mock(DdlChange.Context.class);
+    underTest.execute(context);
+
+    verify(context).execute("ALTER TABLE project_measures DROP COLUMN project_id");
+  }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasuresTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasuresTest.java
new file mode 100644 (file)
index 0000000..1021d91
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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 java.util.List;
+import java.util.stream.Collectors;
+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;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class MakeComponentUuidNotNullOnMeasuresTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, MakeComponentUuidNotNullOnMeasuresTest.class,
+    "in_progress_project_measures.sql");
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private MakeComponentUuidNotNullOnMeasures underTest = new MakeComponentUuidNotNullOnMeasures(db.database());
+
+  @Test
+  public void migration_sets_uuid_columns_not_nullable_on_empty_table() throws SQLException {
+    underTest.execute();
+
+    verifyColumnDefinitions();
+  }
+
+  @Test
+  public void migration_sets_uuid_columns_not_nullable_on_populated_table() throws SQLException {
+    insertMeasure(1L, true);
+    insertMeasure(2L, true);
+
+    underTest.execute();
+
+    verifyColumnDefinitions();
+    assertThat(idsOfRowsInMeasures()).containsOnly(1L, 2L);
+  }
+
+  @Test
+  public void migration_fails_if_some_uuid_columns_are_null() throws SQLException {
+    insertMeasure(1L, false);
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Fail to execute");
+
+    underTest.execute();
+  }
+
+  private void verifyColumnDefinitions() {
+    db.assertColumnDefinition("project_measures", "component_uuid", Types.VARCHAR, 50, false);
+  }
+
+  private List<Long> idsOfRowsInMeasures() {
+    return db.select("select ID from project_measures").stream().map(map -> (Long) map.get("ID")).collect(Collectors.toList());
+  }
+
+  private void insertMeasure(long id, boolean hasComponentUuid) {
+    db.executeInsert(
+      "project_measures",
+      "ID", valueOf(id),
+      "METRIC_ID", valueOf(id + 10),
+      "SNAPSHOT_ID", valueOf(id + 100),
+      "VALUE", valueOf(id + 1000));
+
+    if (hasComponentUuid) {
+      db.executeUpdateSql("update project_measures set COMPONENT_UUID=? where id=?", "uuid_" + id, valueOf(id));
+    }
+  }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/PopulateComponentUuidOfMeasuresTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/PopulateComponentUuidOfMeasuresTest.java
new file mode 100644 (file)
index 0000000..5a95ac5
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.Map;
+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 PopulateComponentUuidOfMeasuresTest {
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, PopulateComponentUuidOfMeasuresTest.class,
+    "in_progress_measures_with_projects.sql");
+
+  private PopulateComponentUuidOfMeasures underTest = new PopulateComponentUuidOfMeasures(db.database());
+
+  @Test
+  public void migration_has_no_effect_on_empty_tables() throws SQLException {
+    underTest.execute();
+
+    assertThat(db.countRowsOfTable("project_measures")).isEqualTo(0);
+    assertThat(db.countRowsOfTable("projects")).isEqualTo(0);
+  }
+
+  @Test
+  public void migration_updates_component_uuid_with_values_from_table_projects_when_they_exist() throws SQLException {
+    String uuid1 = insertComponent(40);
+    String uuid2 = insertComponent(50);
+    String uuid3 = insertComponent(60);
+    String uuid4 = insertComponent(70);
+
+    insertMeasure(1, 40);
+    insertMeasure(2, 60);
+    insertMeasure(3, 90); // 90 does not exist
+    insertMeasure(4, 100); // 100 does not exist
+    db.commit();
+
+    underTest.execute();
+
+    verifyMeasure(1, 40, uuid1);
+    verifyMeasure(2, 60, uuid3);
+    verifyMeasure(3, 90, null);
+    verifyMeasure(4, 100, null);
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    String uuid1 = insertComponent(40);
+    String uuid2 = insertComponent(50);
+    insertMeasure(1, 40);
+
+    underTest.execute();
+    verifyMeasure(1, 40, uuid1);
+
+    underTest.execute();
+    verifyMeasure(1, 40, uuid1);
+
+  }
+
+  private void verifyMeasure(long id, long componentId, @Nullable String componentUuid) {
+    List<Map<String, Object>> rows = db.select("select PROJECT_ID, COMPONENT_UUID from project_measures where ID=" + id);
+    assertThat(rows).hasSize(1);
+    Map<String, Object> row = rows.get(0);
+    assertThat(row.get("PROJECT_ID")).isEqualTo(componentId);
+    assertThat(row.get("COMPONENT_UUID")).isEqualTo(componentUuid);
+  }
+
+  private String insertComponent(long id) {
+    String uuid = "uuid_" + id;
+    db.executeInsert(
+      "projects",
+      "ID", valueOf(id),
+      "UUID", uuid);
+    return uuid;
+  }
+
+  private void insertMeasure(long id, long componentId) {
+    db.executeInsert(
+      "project_measures",
+      "ID", valueOf(id),
+      "METRIC_ID", valueOf(id + 10),
+      "SNAPSHOT_ID", valueOf(id + 100),
+      "VALUE", valueOf(id + 1000),
+      "PROJECT_ID", valueOf(componentId));
+
+  }
+}
index 468afb6e0bd672da298f94415c3f07b19aecbd8f..e2080221686931ebef3ceb04b25a27f992b451c5 100644 (file)
@@ -3,7 +3,7 @@
       id="1"
       snapshot_id="2"
       metric_id="3"
-      project_id="6"
+      component_uuid="FILE1"
       person_id="23"
       value="2.0"
       text_value="measure-value"
index db51be1f6e9705a1d3c1b5c97f93db71c6bc1629..db64cefe322a32d26619b316ca54a96dba718c89 100644 (file)
 
 
   <!-- project measures -->
-  <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="[null]"/>
+  <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="[null]" component_uuid="ABCD"/>
 
-  <project_measures id="2" VALUE="80" METRIC_ID="2" SNAPSHOT_ID="1000" person_id="[null]"/>
+  <project_measures id="2" VALUE="80" METRIC_ID="2" SNAPSHOT_ID="1000" person_id="[null]" component_uuid="ABCD"/>
 
   <!-- package measures -->
-  <project_measures id="3" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1001" person_id="[null]"/>
+  <project_measures id="3" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1001" person_id="[null]" component_uuid="BCDE"/>
 
-  <project_measures id="4" VALUE="70" METRIC_ID="2" SNAPSHOT_ID="1001" person_id="[null]"/>
+  <project_measures id="4" VALUE="70" METRIC_ID="2" SNAPSHOT_ID="1001" person_id="[null]" component_uuid="BCDE"/>
 
   <!-- file measures -->
-  <project_measures id="5" VALUE="5" METRIC_ID="1" SNAPSHOT_ID="1002" person_id="[null]"/>
+  <project_measures id="5" VALUE="5" METRIC_ID="1" SNAPSHOT_ID="1002" person_id="[null]" component_uuid="CDEF"/>
 
-  <project_measures id="6" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="1002" person_id="[null]"/>
+  <project_measures id="6" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="1002" person_id="[null]" component_uuid="CDEF"/>
 
 </dataset>
index ab6d117dae07dd6e951b6d3d5bf09a3cc6f062d6..cc554e9e486722317a44e39449b42f3673f5246e 100644 (file)
              status="P" islast="[false]" depth="0"/>
 
   <!-- project measures -->
-  <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="[null]"/>
+  <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="[null]" component_uuid="ABCD"/>
 
-  <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="20"/>
+  <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="20" component_uuid="ABCD"/>
 
-  <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="21"/>
+  <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" person_id="21" component_uuid="ABCD"/>
 
 </dataset>
index 3b41cf2d22107601497acc234b93c3a1cb6d7250..cf3af96ea09dcdb0377a892462b2a7bd43e8eaa3 100644 (file)
@@ -4,18 +4,18 @@
   <metrics id="11" name="coverage_line_hits_data"/>
   <metrics id="12" name="ncloc"/>
 
-  <projects id="1" kee="org.struts:struts-core:src/org/struts/RequestContext.java" enabled="[true]" uuid="ABCD"/>
+  <projects id="1" kee="org.struts:struts-core:src/org/struts/RequestContext.java" enabled="[true]" uuid="FILE1"/>
 
   <snapshots id="5" component_uuid="ABCD" root_component_uuid="ABCD" islast="[true]" />
 
   <project_measures id="20" snapshot_id="5" metric_id="10" value="[null]" text_value="0123456789012345678901234567890123456789" 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]" />
+                    alert_status="[null]" alert_text="[null]" component_uuid="FILE1"/>
   <project_measures id="21" snapshot_id="5" metric_id="11" value="[null]" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" 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]" />
+                    alert_status="[null]" alert_text="[null]" component_uuid="FILE1"/>
   <project_measures id="22" snapshot_id="5" metric_id="12" value="10" text_value="[null]" measure_data="[null]"
                     variation_value_1="1" variation_value_2="2" variation_value_3="3" variation_value_4="4" variation_value_5="-5"
-                    alert_status="OK" alert_text="Green"/>
+                    alert_status="OK" alert_text="Green" component_uuid="FILE1"/>
 
 </dataset>
index 3b41cf2d22107601497acc234b93c3a1cb6d7250..c9e5417e180fe54071b07a09d9ead4bde4f8030a 100644 (file)
@@ -8,13 +8,22 @@
 
   <snapshots id="5" component_uuid="ABCD" root_component_uuid="ABCD" islast="[true]" />
 
-  <project_measures id="20" snapshot_id="5" metric_id="10" value="[null]" text_value="0123456789012345678901234567890123456789" measure_data="[null]"
+  <project_measures id="20"
+                    component_uuid="ABCD"
+                    snapshot_id="5"
+                    metric_id="10" value="[null]" text_value="0123456789012345678901234567890123456789" 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]" />
-  <project_measures id="21" snapshot_id="5" metric_id="11" value="[null]" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" measure_data="[null]"
+  <project_measures id="21"
+                    component_uuid="ABCD"
+                    snapshot_id="5"
+                    metric_id="11" value="[null]" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" 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]" />
-  <project_measures id="22" snapshot_id="5" metric_id="12" value="10" text_value="[null]" measure_data="[null]"
+  <project_measures id="22"
+                    component_uuid="ABCD"
+                    snapshot_id="5"
+                    metric_id="12" value="10" text_value="[null]" measure_data="[null]"
                     variation_value_1="1" variation_value_2="2" variation_value_3="3" variation_value_4="4" variation_value_5="-5"
                     alert_status="OK" alert_text="Green"/>
 
index f2e5a9c8decb8873cd3f140c311015ecf1f54080..d1fe38a34eea206a1dd61b04efb782d4cca4aa97 100644 (file)
   <project_measures id="20" snapshot_id="5" metric_id="10" value="[null]" text_value="0123456789012345678901234567890123456789" 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]"
-                    person_id="[null]"/>
+                    person_id="[null]" component_uuid="1"/>
   <project_measures id="21" snapshot_id="5" metric_id="11" value="[null]" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" 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]"
-                    person_id="[null]"/>
+                    person_id="[null]" component_uuid="1"/>
   <project_measures id="22" snapshot_id="5" metric_id="12" value="10" text_value="[null]" measure_data="[null]"
                     variation_value_1="1" variation_value_2="2" variation_value_3="3" variation_value_4="4" variation_value_5="-5"
                     alert_status="OK" alert_text="Green"
-                    person_id="[null]"/>
+                    person_id="[null]" component_uuid="1"/>
   <!--measures for developer 333-->
   <project_measures id="30" snapshot_id="5" metric_id="10" value="[null]" text_value="0123456789012345678901234567890123456789" 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]"
-                    person_id="333"/>
+                    person_id="333" component_uuid="1"/>
   <project_measures id="31" snapshot_id="5" metric_id="11" value="[null]" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" 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]"
-                    person_id="333"/>
+                    person_id="333" component_uuid="1"/>
   <project_measures id="32" snapshot_id="5" metric_id="12" value="10" text_value="[null]" measure_data="[null]"
                     variation_value_1="1" variation_value_2="2" variation_value_3="3" variation_value_4="4" variation_value_5="-5"
                     alert_status="OK" alert_text="Green"
-                    person_id="333"/>
+                    person_id="333" component_uuid="1"/>
 
 </dataset>
index 4ead71d632c062e4c3a384f7ac8598253e4e0bdd..fe50ae405d7e13a7e7c823dcf610520c96e0acb9 100644 (file)
@@ -18,7 +18,8 @@
                     variation_value_5="[null]"
                     alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1"
                     person_id="[null]"
-                    text_value="[null]" project_id="[null]"
+                    text_value="[null]"
+                    component_uuid="1"
                     alert_status="[null]" description="[null]" measure_data="[null]"/>
   <events id="1" name="Version 1.0" component_uuid="1" snapshot_id="1" category="VERSION" description="[null]"
           event_date="1228222680000" created_at="1228222680000" event_data="[null]"/>
index 791b313516bf07fc8a908dde0e2060b5de81d25d..f8f8dc3055a341133bf0f4c3d04f0d97f5c7cd35 100644 (file)
@@ -18,7 +18,8 @@
                     variation_value_5="[null]"
                     alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1"
                     person_id="[null]"
-                    text_value="[null]" project_id="[null]"
+                    text_value="[null]"
+                    component_uuid="1"
                     alert_status="[null]" description="[null]" measure_data="[null]"/>
   <events id="1" name="Version 1.0" component_uuid="1" snapshot_id="1" category="VERSION" description="[null]"
           event_date="1228222680000" created_at="1228222680000" event_data="[null]"/>
@@ -43,7 +44,8 @@
                     variation_value_5="[null]"
                     alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="5"
                     person_id="[null]"
-                    text_value="[null]" project_id="[null]"
+                    text_value="[null]"
+                    component_uuid="5"
                     alert_status="[null]" description="[null]" measure_data="[null]"/>
   <events id="2" name="Version 1.0" component_uuid="5" snapshot_id="5" category="VERSION" description="[null]"
           event_date="1228222680000" created_at="1228222680000" event_data="[null]"/>
index 7bb4215979f7125fe3458248ded7696f2ad7bb40..a90f9929879ba5c75c6acdb448fb60b2413304e1 100644 (file)
              build_date="1228222680000" version="[null]" path="[null]"/>
 
   <!-- do not delete standard measure -->
-  <project_measures id="1" project_id="1" snapshot_id="1" metric_id="1"
+  <project_measures id="1"
+                    snapshot_id="1"
+                    metric_id="1"
+                    component_uuid="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"
index 23b5e4aff63babc26e7fee21dff604ee4b5d0797..4fd5023f74e5baa065ad11e426435aa7f00c4b06 100644 (file)
@@ -22,7 +22,9 @@
              build_date="1228222680000" version="[null]" path="[null]"/>
 
   <!-- do not delete standard measure -->
-  <project_measures id="1" project_id="1" snapshot_id="1" metric_id="1"
+  <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]"
                     variation_value_4="[null]"
                     variation_value_5="[null]" alert_text="[null]" value="10.0"
@@ -31,7 +33,9 @@
                     description="[null]" measure_data="[null]"/>
 
   <!-- delete measure on metrics that are flagged with delete_historical_data=true -->
-  <project_measures id="6" project_id="1" snapshot_id="1" metric_id="2"
+  <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]"
                     variation_value_4="[null]"
                     variation_value_5="[null]" alert_text="[null]" value="10.0"
@@ -40,7 +44,9 @@
                     description="[null]" measure_data="[null]"/>
 
   <!-- delete measure on developers -->
-  <project_measures id="7" project_id="1" snapshot_id="1" metric_id="2"
+  <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]"
                     person_id="123456"
                     variation_value_4="[null]"
index 78e880e7dcc784251d01cf9f64251e2631c4ff80..1933ad4f216a9b9b7d176c7ec1cba69b84172bb8 100644 (file)
@@ -24,7 +24,9 @@ Note that measures, events and reviews are not deleted.
   <!--created_at="2008-12-02 13:58:00.00"-->
   <!--checksum="[null]" person_id="[null]"/>-->
 
-  <project_measures ID="1" project_id="1" SNAPSHOT_ID="1"
+  <project_measures ID="1"
+                    component_uuid="1"
+                    SNAPSHOT_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" METRIC_ID="1"
@@ -54,7 +56,9 @@ Note that measures, events and reviews are not deleted.
              build_date="1228222680000" version="[null]" path="[null]"/>
 
 
-  <project_measures ID="2" project_id="2" SNAPSHOT_ID="2"
+  <project_measures ID="2"
+                    component_uuid="2"
+                    SNAPSHOT_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" METRIC_ID="1"
index d754dffab3ef1213bb8fad8c2dd1c4c5e27ffba0..a4b06bcc31ebf15dac3ccfd42d6dd1138bfcbb51 100644 (file)
@@ -11,7 +11,9 @@
              depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000"
              build_date="1228222680000" version="[null]" path="[null]"/>
 
-  <project_measures ID="1" project_id="1" SNAPSHOT_ID="1"
+  <project_measures ID="1"
+                    component_uuid="1"
+                    SNAPSHOT_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" METRIC_ID="1" person_id="[null]" text_value="[null]"
@@ -39,7 +41,9 @@
              depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000"
              build_date="1228222680000" version="[null]" path="[null]"/>
 
-  <project_measures ID="2" project_id="2" SNAPSHOT_ID="2" characteristic_id="[null]"
+  <project_measures ID="2"
+                    component_uuid="2"
+                    SNAPSHOT_ID="2" characteristic_id="[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" METRIC_ID="1"
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/AddComponentUuidColumnToMeasuresTest/project_measures_5.6.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/AddComponentUuidColumnToMeasuresTest/project_measures_5.6.sql
new file mode 100644 (file)
index 0000000..c4f1eab
--- /dev/null
@@ -0,0 +1,29 @@
+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 INDEX "MEASURES_SID_METRIC" ON "PROJECT_MEASURES" ("SNAPSHOT_ID", "METRIC_ID");
+
+CREATE INDEX "MEASURES_PERSON" ON "PROJECT_MEASURES" ("PERSON_ID");
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponentTest/in_progress_project_measures.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/DeleteOrphanMeasuresWithoutComponentTest/in_progress_project_measures.sql
new file mode 100644 (file)
index 0000000..42d9248
--- /dev/null
@@ -0,0 +1,32 @@
+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),
+
+  // new column, introduced in migration 1214
+  "COMPONENT_UUID" VARCHAR(50)
+);
+
+CREATE INDEX "MEASURES_SID_METRIC" ON "PROJECT_MEASURES" ("SNAPSHOT_ID", "METRIC_ID");
+
+CREATE INDEX "MEASURES_PERSON" ON "PROJECT_MEASURES" ("PERSON_ID");
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasuresTest/in_progress_project_measures.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/MakeComponentUuidNotNullOnMeasuresTest/in_progress_project_measures.sql
new file mode 100644 (file)
index 0000000..42d9248
--- /dev/null
@@ -0,0 +1,32 @@
+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),
+
+  // new column, introduced in migration 1214
+  "COMPONENT_UUID" VARCHAR(50)
+);
+
+CREATE INDEX "MEASURES_SID_METRIC" ON "PROJECT_MEASURES" ("SNAPSHOT_ID", "METRIC_ID");
+
+CREATE INDEX "MEASURES_PERSON" ON "PROJECT_MEASURES" ("PERSON_ID");
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateComponentUuidOfMeasuresTest/in_progress_measures_with_projects.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateComponentUuidOfMeasuresTest/in_progress_measures_with_projects.sql
new file mode 100644 (file)
index 0000000..c21cb13
--- /dev/null
@@ -0,0 +1,55 @@
+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),
+
+  // new column, introduced in migration 1214
+  "COMPONENT_UUID" VARCHAR(50)
+);
+
+CREATE INDEX "MEASURES_SID_METRIC" ON "PROJECT_MEASURES" ("SNAPSHOT_ID", "METRIC_ID");
+
+CREATE INDEX "MEASURES_PERSON" ON "PROJECT_MEASURES" ("PERSON_ID");
+
+CREATE TABLE "PROJECTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(400),
+  "ROOT_ID" INTEGER,
+  "UUID" VARCHAR(50),
+  "PROJECT_UUID" VARCHAR(50),
+  "MODULE_UUID" VARCHAR(50),
+  "MODULE_UUID_PATH" VARCHAR(4000),
+  "NAME" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(2000),
+  "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+  "SCOPE" VARCHAR(3),
+  "QUALIFIER" VARCHAR(10),
+  "DEPRECATED_KEE" VARCHAR(400),
+  "PATH" VARCHAR(2000),
+  "LANGUAGE" VARCHAR(20),
+  "COPY_RESOURCE_ID" INTEGER,
+  "LONG_NAME" VARCHAR(2000),
+  "PERSON_ID" INTEGER,
+  "CREATED_AT" TIMESTAMP,
+  "AUTHORIZATION_UPDATED_AT" BIGINT
+);