]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7691 table CE_ACTIVITY should use analysis UUID
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 16 Jun 2016 20:10:06 +0000 (22:10 +0200)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Fri, 17 Jun 2016 18:22:08 +0000 (20:22 +0200)
37 files changed:
server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java
server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java
server/sonar-server/src/main/java/org/sonar/server/computation/queue/InternalCeQueueImpl.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PublishTaskResultStep.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java
server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java
server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/queue/InternalCeQueueImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PublishTaskResultStepTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1232_add_analysis_uuid_column_to_ce_activity.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1233_populate_analysis_uuid_column_on_ce_activity.rb [new file with mode: 0644]
server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1234_drop_snapshot_id_column_from_ce_activity.rb [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/ce/CeActivityDto.java
sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java
sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.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/AddAnalysisUuidColumnToCeActivity.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivity.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivity.java [new file with mode: 0644]
sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml
sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.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/ce/CeActivityDaoTest.java
sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java
sonar-db/src/test/java/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivityTest.java [new file with mode: 0644]
sonar-db/src/test/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest.java [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest/old_ce_activity.sql [new file with mode: 0644]
sonar-db/src/test/resources/org/sonar/db/version/v60/AddComponentUuidColumnsToSnapshotsTest/old_snapshots.sql
sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest/in_progress_ce_activity.sql [new file with mode: 0644]

index 600f2fe4515f62121d65dbf0508ec4fa329009f5..3801a1b5334fb59e7bd086ff76df2beb09839bb3 100644 (file)
@@ -19,7 +19,7 @@
  */
 package org.sonar.ce.queue;
 
-import javax.annotation.CheckForNull;
+import java.util.Optional;
 import org.sonar.ce.taskprocessor.CeTaskProcessor;
 
 /**
@@ -30,8 +30,7 @@ import org.sonar.ce.taskprocessor.CeTaskProcessor;
 @FunctionalInterface
 public interface CeTaskResult {
   /**
-   * The id of the snapshot created, if any, for the Component in {@link CeTask}
+   * The UUID of the analysis created, if any, for the Component in {@link CeTask}
    */
-  @CheckForNull
-  Long getSnapshotId();
+  Optional<String> getAnalysisUuid();
 }
index 12c249b78686a7e8b26e63274b931f3aa55a0c38..df0e5fcf9043375e30ae9e3ee0d89ed62f5ff03b 100644 (file)
@@ -111,8 +111,8 @@ public class TaskFormatter {
       builder.setComponentId(dto.getComponentUuid());
       buildComponent(builder, componentDtoCache.get(dto.getComponentUuid()));
     }
-    if (dto.getSnapshotId() != null) {
-      builder.setAnalysisId(String.valueOf(dto.getSnapshotId()));
+    if (dto.getAnalysisUuid() != null) {
+      builder.setAnalysisId(dto.getAnalysisUuid());
     }
     if (dto.getSubmitterLogin() != null) {
       builder.setSubmitterLogin(dto.getSubmitterLogin());
index 7ffe4ddf840ae498a31beb72c806bf5fd94e3829..6eb9497d81c8d4a640063047cdaa8a66789eee39 100644 (file)
@@ -101,9 +101,9 @@ public class InternalCeQueueImpl extends CeQueueImpl implements InternalCeQueue
 
   private static void updateTaskResult(CeActivityDto activityDto, @Nullable CeTaskResult taskResult) {
     if (taskResult != null) {
-      Long snapshotId = taskResult.getSnapshotId();
-      if (snapshotId != null) {
-        activityDto.setSnapshotId(snapshotId);
+      java.util.Optional<String> analysisUuid = taskResult.getAnalysisUuid();
+      if (analysisUuid.isPresent()) {
+        activityDto.setAnalysisUuid(analysisUuid.get());
       }
     }
   }
index 656d96759d22b150b0397dac9e8c1b9955a77c45..c2046483aa404a19fdead188f838a8f63ee7cc0b 100644 (file)
  */
 package org.sonar.server.computation.step;
 
+import java.util.Optional;
 import javax.annotation.concurrent.Immutable;
-import org.sonar.server.computation.component.DbIdsRepository;
-import org.sonar.server.computation.component.TreeRootHolder;
 import org.sonar.ce.queue.CeTaskResult;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolder;
 import org.sonar.server.computation.taskprocessor.MutableTaskResultHolder;
 
 public class PublishTaskResultStep implements ComputationStep {
   private final MutableTaskResultHolder taskResultHolder;
-  private final TreeRootHolder treeRootHolder;
-  private final DbIdsRepository dbIdsRepository;
+  private final AnalysisMetadataHolder analysisMetadataHolder;
 
-  public PublishTaskResultStep(MutableTaskResultHolder taskResultHolder, TreeRootHolder treeRootHolder, DbIdsRepository dbIdsRepository) {
+  public PublishTaskResultStep(MutableTaskResultHolder taskResultHolder, AnalysisMetadataHolder analysisMetadataHolder) {
     this.taskResultHolder = taskResultHolder;
-    this.treeRootHolder = treeRootHolder;
-    this.dbIdsRepository = dbIdsRepository;
+    this.analysisMetadataHolder = analysisMetadataHolder;
   }
 
   @Override
@@ -43,21 +41,20 @@ public class PublishTaskResultStep implements ComputationStep {
 
   @Override
   public void execute() {
-    long snapshotId = dbIdsRepository.getSnapshotId(treeRootHolder.getRoot());
-    taskResultHolder.setResult(new CeTaskResultImpl(snapshotId));
+    taskResultHolder.setResult(new CeTaskResultImpl(analysisMetadataHolder.getUuid()));
   }
 
   @Immutable
   private static class CeTaskResultImpl implements CeTaskResult {
-    private final long snapshotId;
+    private final String analysisUuid;
 
-    public CeTaskResultImpl(long snapshotId) {
-      this.snapshotId = snapshotId;
+    public CeTaskResultImpl(String analysisUuid) {
+      this.analysisUuid = analysisUuid;
     }
 
     @Override
-    public Long getSnapshotId() {
-      return snapshotId;
+    public Optional<String> getAnalysisUuid() {
+      return Optional.of(analysisUuid);
     }
   }
 }
index 252a6b3d19c42ed49cf2db76930aed76f72a403e..f76a0b6e79b1e52e762ca933e6d2e677e2491ec5 100644 (file)
@@ -49,7 +49,7 @@ import org.sonarqube.ws.client.qualitygate.ProjectStatusWsRequest;
 
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
-import static org.sonar.server.ws.WsUtils.checkFound;
+import static org.sonar.server.ws.WsUtils.checkFoundWithOptional;
 import static org.sonar.server.ws.WsUtils.checkRequest;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
 import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ANALYSIS_ID;
@@ -97,7 +97,7 @@ public class ProjectStatusAction implements QGateWsAction {
 
     action.createParam(PARAM_ANALYSIS_ID)
       .setDescription("Analysis id")
-      .setExampleValue("2963");
+      .setExampleValue(Uuids.UUID_EXAMPLE_04);
 
     action.createParam(PARAM_PROJECT_ID)
       .setSince("5.4")
@@ -132,9 +132,9 @@ public class ProjectStatusAction implements QGateWsAction {
   }
 
   private ProjectAndSnapshot getProjectAndSnapshot(DbSession dbSession, ProjectStatusWsRequest request) {
-    String snapshotId = request.getAnalysisId();
+    String analysisUuid = request.getAnalysisId();
     if (!isNullOrEmpty(request.getAnalysisId())) {
-      return getSnapshotThenProject(dbSession, snapshotId);
+      return getSnapshotThenProject(dbSession, analysisUuid);
     } else if (!isNullOrEmpty(request.getProjectId()) ^ !isNullOrEmpty(request.getProjectKey())) {
       return getProjectThenSnapshot(dbSession, request);
     }
@@ -154,20 +154,9 @@ public class ProjectStatusAction implements QGateWsAction {
     return new ProjectAndSnapshot(projectDto, snapshotDto);
   }
 
-  private SnapshotDto getSnapshot(DbSession dbSession, String snapshotIdFromRequest) {
-    Long snapshotId = null;
-    try {
-      snapshotId = Long.parseLong(snapshotIdFromRequest);
-    } catch (NumberFormatException e) {
-      // checks String is a long
-    }
-
-    SnapshotDto snapshotDto = null;
-    if (snapshotId != null) {
-      snapshotDto = dbClient.snapshotDao().selectById(dbSession, snapshotId);
-    }
-
-    return checkFound(snapshotDto, "Analysis with id '%s' is not found", snapshotIdFromRequest);
+  private SnapshotDto getSnapshot(DbSession dbSession, String analysisUuidFromRequest) {
+    java.util.Optional<SnapshotDto> snapshotDto = dbClient.snapshotDao().selectByUuid(dbSession, analysisUuidFromRequest);
+    return checkFoundWithOptional(snapshotDto, "Analysis with id '%s' is not found", analysisUuidFromRequest);
   }
 
   private Optional<String> getQualityGateDetailsMeasureData(DbSession dbSession, Optional<SnapshotDto> snapshotDto) {
@@ -179,7 +168,7 @@ public class ProjectStatusAction implements QGateWsAction {
       Collections.singleton(CoreMetrics.QUALITY_GATE_DETAILS_KEY), dbSession);
 
     return measures.isEmpty()
-      ? Optional.<String>absent()
+      ? Optional.absent()
       : Optional.fromNullable(measures.get(0).getData());
   }
 
index 60df0574a76afa08fc2499a1ac708b367dd88c97..6ee8781adbae616c4c3a621139364523852d4271 100644 (file)
@@ -99,4 +99,12 @@ public class WsUtils {
 
     return value.get();
   }
+
+  public static <T> T checkFoundWithOptional(java.util.Optional<T> value, String message, Object... messageArguments) {
+    if (!value.isPresent()) {
+      throw new NotFoundException(format(message, messageArguments));
+    }
+
+    return value.get();
+  }
 }
index 93b82da9c74bdc9a448b9ec54811dbd3b2a2b78f..e2a4792de59d684c5f01bc2095f4cb7d5fd59265 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.ce.ws;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Throwables;
-import java.io.File;
 import java.io.IOException;
 import java.util.Collections;
 import java.util.Date;
@@ -89,7 +88,7 @@ public class ActivityActionTest {
 
   @Before
   public void setUp() {
-    when(ceLogging.getFile(any(LogFileRef.class))).thenReturn(Optional.<File>absent());
+    when(ceLogging.getFile(any(LogFileRef.class))).thenReturn(Optional.absent());
   }
 
   @Test
@@ -106,7 +105,7 @@ public class ActivityActionTest {
     assertThat(activityResponse.getTasks(0).getId()).isEqualTo("T2");
     assertThat(activityResponse.getTasks(0).getStatus()).isEqualTo(WsCe.TaskStatus.FAILED);
     assertThat(activityResponse.getTasks(0).getComponentId()).isEqualTo("PROJECT_2");
-    assertThat(activityResponse.getTasks(0).getAnalysisId()).isEqualTo("123456");
+    assertThat(activityResponse.getTasks(0).getAnalysisId()).isEqualTo("U1");
     assertThat(activityResponse.getTasks(0).getExecutionTimeMs()).isEqualTo(500L);
     assertThat(activityResponse.getTasks(0).getLogs()).isFalse();
     assertThat(activityResponse.getTasks(1).getId()).isEqualTo("T1");
@@ -182,7 +181,7 @@ public class ActivityActionTest {
     assertPage(1, asList("T3"));
     assertPage(2, asList("T3", "T2"));
     assertPage(10, asList("T3", "T2", "T1"));
-    assertPage(0, Collections.<String>emptyList());
+    assertPage(0, Collections.emptyList());
   }
 
   private void assertPage(int pageSize, List<String> expectedOrderedTaskIds) {
@@ -364,7 +363,7 @@ public class ActivityActionTest {
     activityDto.setStatus(status);
     activityDto.setExecutionTimeMs(500L);
     activityDto.setExecutedAt(EXECUTED_AT);
-    activityDto.setSnapshotId(123_456L);
+    activityDto.setAnalysisUuid("U1");
     dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
     dbTester.commit();
     return activityDto;
index ff27f0079b6b0ff21a263cd1f7fcba576a2d6820..7be3ae0f6fbaec1393f0bfa755d8ac5c9d5fe388 100644 (file)
@@ -26,17 +26,17 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
 import org.sonar.api.web.UserRole;
+import org.sonar.ce.log.CeLogging;
+import org.sonar.ce.log.LogFileRef;
 import org.sonar.core.util.Protobuf;
 import org.sonar.db.DbTester;
 import org.sonar.db.ce.CeActivityDto;
 import org.sonar.db.ce.CeQueueDto;
 import org.sonar.db.ce.CeTaskTypes;
-import org.sonar.ce.log.CeLogging;
-import org.sonar.ce.log.LogFileRef;
-import org.sonarqube.ws.MediaTypes;
 import org.sonar.server.tester.UserSessionRule;
 import org.sonar.server.ws.TestResponse;
 import org.sonar.server.ws.WsActionTester;
+import org.sonarqube.ws.MediaTypes;
 import org.sonarqube.ws.WsCe;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -139,7 +139,7 @@ public class ComponentActionTest {
     CeActivityDto activityDto = new CeActivityDto(queueDto);
     activityDto.setStatus(status);
     activityDto.setExecutionTimeMs(500L);
-    activityDto.setSnapshotId(123_456L);
+    activityDto.setAnalysisUuid("U1");
     dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
     dbTester.getSession().commit();
     return activityDto;
index f0842056d786613a9a3acae0c5f2697eb0f0c788..8584d97a4f3271dcb7b52d07504e72ce92ca441f 100644 (file)
@@ -26,6 +26,8 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.sonar.api.utils.System2;
+import org.sonar.ce.log.CeLogging;
+import org.sonar.ce.log.LogFileRef;
 import org.sonar.core.util.Protobuf;
 import org.sonar.db.DbTester;
 import org.sonar.db.ce.CeActivityDto;
@@ -33,8 +35,6 @@ import org.sonar.db.ce.CeQueueDto;
 import org.sonar.db.ce.CeTaskTypes;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
-import org.sonar.ce.log.CeLogging;
-import org.sonar.ce.log.LogFileRef;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.tester.UserSessionRule;
@@ -118,7 +118,7 @@ public class TaskActionTest {
     CeActivityDto activityDto = new CeActivityDto(queueDto);
     activityDto.setStatus(CeActivityDto.Status.FAILED);
     activityDto.setExecutionTimeMs(500L);
-    activityDto.setSnapshotId(123_456L);
+    activityDto.setAnalysisUuid("U1");
     dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
     dbTester.commit();
 
@@ -134,7 +134,7 @@ public class TaskActionTest {
     assertThat(task.getComponentId()).isEqualTo(PROJECT.uuid());
     assertThat(task.getComponentKey()).isEqualTo(PROJECT.key());
     assertThat(task.getComponentName()).isEqualTo(PROJECT.name());
-    assertThat(task.getAnalysisId()).isEqualTo("123456");
+    assertThat(task.getAnalysisId()).isEqualTo("U1");
     assertThat(task.getExecutionTimeMs()).isEqualTo(500L);
     assertThat(task.getLogs()).isFalse();
   }
@@ -230,7 +230,7 @@ public class TaskActionTest {
     CeActivityDto activityDto = new CeActivityDto(queueDto);
     activityDto.setStatus(CeActivityDto.Status.FAILED);
     activityDto.setExecutionTimeMs(500L);
-    activityDto.setSnapshotId(123_456L);
+    activityDto.setAnalysisUuid("U1");
     activityDto.setComponentUuid(PROJECT.uuid());
     dbTester.getDbClient().ceActivityDao().insert(dbTester.getSession(), activityDto);
     dbTester.commit();
index c2b3c1913544e8bd54f108f1a37ce2241da9d508..a5a71be90a2ef1ece067c1495282df0134e0e6b3 100644 (file)
@@ -29,13 +29,13 @@ import org.mockito.Mockito;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.api.utils.DateUtils;
 import org.sonar.api.utils.System2;
+import org.sonar.ce.log.CeLogging;
+import org.sonar.ce.log.LogFileRef;
 import org.sonar.db.DbTester;
 import org.sonar.db.ce.CeActivityDto;
 import org.sonar.db.ce.CeQueueDto;
 import org.sonar.db.ce.CeTaskTypes;
 import org.sonar.db.component.ComponentDto;
-import org.sonar.ce.log.CeLogging;
-import org.sonar.ce.log.LogFileRef;
 import org.sonarqube.ws.WsCe;
 
 import static java.util.Arrays.asList;
@@ -176,7 +176,7 @@ public class TaskFormatterTest {
     assertThat(wsTask.getLogs()).isFalse();
     assertThat(wsTask.getSubmittedAt()).isEqualTo(DateUtils.formatDateTime(new Date(1_450_000_000_000L)));
     assertThat(wsTask.getExecutionTimeMs()).isEqualTo(500L);
-    assertThat(wsTask.getAnalysisId()).isEqualTo("123456");
+    assertThat(wsTask.getAnalysisId()).isEqualTo("U1");
     assertThat(wsTask.getLogs()).isFalse();
   }
 
@@ -209,7 +209,7 @@ public class TaskFormatterTest {
     CeActivityDto activityDto = new CeActivityDto(queueDto);
     activityDto.setStatus(status);
     activityDto.setExecutionTimeMs(500L);
-    activityDto.setSnapshotId(123_456L);
+    activityDto.setAnalysisUuid("U1");
     return activityDto;
   }
 }
index 5e407ac4fa6ea07505a5d2eae9e7eecc40fa125c..66ad196524d147a37eb6b8ad1a070913059742dc 100644 (file)
@@ -55,6 +55,8 @@ import static org.mockito.Mockito.when;
 
 public class InternalCeQueueImplTest {
 
+  private static final String AN_ANALYSIS_UUID = "U1";
+
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
 
@@ -149,13 +151,13 @@ public class InternalCeQueueImplTest {
     assertThat(history.isPresent()).isTrue();
     assertThat(history.get().getStatus()).isEqualTo(CeActivityDto.Status.SUCCESS);
     assertThat(history.get().getIsLast()).isTrue();
-    assertThat(history.get().getSnapshotId()).isNull();
+    assertThat(history.get().getAnalysisUuid()).isNull();
 
     verify(listener).onRemoved(task, CeActivityDto.Status.SUCCESS);
   }
 
   @Test
-  public void remove_does_not_set_snapshotId_in_CeActivity_when_CeTaskResult_has_no_snapshot_id() {
+  public void remove_does_not_set_analysisUuid_in_CeActivity_when_CeTaskResult_has_no_analysis_uuid() {
     CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
     Optional<CeTask> peek = underTest.peek();
     underTest.remove(peek.get(), CeActivityDto.Status.SUCCESS, newTaskResult(null));
@@ -163,21 +165,20 @@ public class InternalCeQueueImplTest {
     // available in history
     Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
     assertThat(history.isPresent()).isTrue();
-    assertThat(history.get().getSnapshotId()).isNull();
+    assertThat(history.get().getAnalysisUuid()).isNull();
   }
 
   @Test
   public void remove_sets_snapshotId_in_CeActivity_when_CeTaskResult_has_no_snapshot_id() {
     CeTask task = submit(CeTaskTypes.REPORT, "PROJECT_1");
-    long snapshotId = 663L;
 
     Optional<CeTask> peek = underTest.peek();
-    underTest.remove(peek.get(), CeActivityDto.Status.SUCCESS, newTaskResult(snapshotId));
+    underTest.remove(peek.get(), CeActivityDto.Status.SUCCESS, newTaskResult(AN_ANALYSIS_UUID));
 
     // available in history
     Optional<CeActivityDto> history = dbTester.getDbClient().ceActivityDao().selectByUuid(dbTester.getSession(), task.getUuid());
     assertThat(history.isPresent()).isTrue();
-    assertThat(history.get().getSnapshotId()).isEqualTo(snapshotId);
+    assertThat(history.get().getAnalysisUuid()).isEqualTo("U1");
   }
 
   @Test
@@ -326,9 +327,9 @@ public class InternalCeQueueImplTest {
     return submission.build();
   }
 
-  private CeTaskResult newTaskResult(Long snapshotId) {
+  private CeTaskResult newTaskResult(@Nullable String analysisUuid) {
     CeTaskResult taskResult = mock(CeTaskResult.class);
-    when(taskResult.getSnapshotId()).thenReturn(snapshotId);
+    when(taskResult.getAnalysisUuid()).thenReturn(java.util.Optional.ofNullable(analysisUuid));
     return taskResult;
   }
 
index ffce1b731084780430370f0dc78678ed9c22f025..19c96c742ac08790700966a9125b60ca580bdfdc 100644 (file)
@@ -21,27 +21,22 @@ package org.sonar.server.computation.step;
 
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.server.computation.batch.TreeRootHolderRule;
-import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DbIdsRepository;
+import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule;
 import org.sonar.server.computation.taskprocessor.MutableTaskResultHolder;
 import org.sonar.server.computation.taskprocessor.MutableTaskResultHolderImpl;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 
 public class PublishTaskResultStepTest {
-  private static final Component ROOT_COMPONENT = mock(Component.class);
 
-  @Rule
-  public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule()
-      .setRoot(ROOT_COMPONENT);
+  private static final String AN_ANALYSIS_UUID = "U1";
 
-  private DbIdsRepository dbIdsRepository = mock(DbIdsRepository.class);
   private MutableTaskResultHolder taskResultHolder = new MutableTaskResultHolderImpl();
 
-  private PublishTaskResultStep underTest = new PublishTaskResultStep(taskResultHolder, treeRootHolder, dbIdsRepository);
+  @Rule
+  public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule();
+
+  private PublishTaskResultStep underTest = new PublishTaskResultStep(taskResultHolder, analysisMetadataHolder);
 
   @Test
   public void verify_getDescription() {
@@ -50,12 +45,10 @@ public class PublishTaskResultStepTest {
 
   @Test
   public void execute_populate_TaskResultHolder_with_a_TaskResult_with_snapshot_id_of_the_root_taken_from_DbIdsRepository() {
-    long snapshotId = 1233L;
-
-    when(dbIdsRepository.getSnapshotId(ROOT_COMPONENT)).thenReturn(snapshotId);
+    analysisMetadataHolder.setUuid(AN_ANALYSIS_UUID);
 
     underTest.execute();
 
-    assertThat(taskResultHolder.getResult().getSnapshotId()).isEqualTo(snapshotId);
+    assertThat(taskResultHolder.getResult().getAnalysisUuid().get()).isEqualTo(AN_ANALYSIS_UUID);
   }
 }
index 438423722b32cef4de7703455b38441261ed6ec0..a3dd6d52aeb899a4da9294b7089922c507ca4b7d 100644 (file)
@@ -60,6 +60,7 @@ import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM
 
 public class ProjectStatusActionTest {
   private static final String ANALYSIS_ID = "task-uuid";
+
   @Rule
   public ExpectedException expectedException = ExpectedException.none();
   @Rule
@@ -103,7 +104,7 @@ public class ProjectStatusActionTest {
     dbSession.commit();
 
     String response = ws.newRequest()
-      .setParam("analysisId", snapshot.getId().toString())
+      .setParam("analysisId", snapshot.getUuid())
       .execute().getInput();
 
     assertJson(response).isSimilarTo(getClass().getResource("project_status-example.json"));
@@ -175,7 +176,7 @@ public class ProjectStatusActionTest {
     SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newSnapshotForProject(project));
     dbSession.commit();
 
-    ProjectStatusWsResponse result = call(snapshot.getId().toString());
+    ProjectStatusWsResponse result = call(snapshot.getUuid());
 
     assertThat(result.getProjectStatus().getStatus()).isEqualTo(Status.NONE);
     assertThat(result.getProjectStatus().getConditionsCount()).isEqualTo(0);
@@ -200,7 +201,7 @@ public class ProjectStatusActionTest {
     SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newSnapshotForProject(project));
     dbSession.commit();
 
-    call(snapshot.getId().toString());
+    call(snapshot.getUuid());
   }
 
   @Test
@@ -211,7 +212,7 @@ public class ProjectStatusActionTest {
     SnapshotDto snapshot = dbClient.snapshotDao().insert(dbSession, newSnapshotForProject(project));
     dbSession.commit();
 
-    call(snapshot.getId().toString());
+    call(snapshot.getUuid());
   }
 
   @Test
@@ -233,7 +234,7 @@ public class ProjectStatusActionTest {
     dbSession.commit();
 
     expectedException.expect(ForbiddenException.class);
-    call(snapshot.getId().toString());
+    call(snapshot.getUuid());
   }
 
   @Test
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1232_add_analysis_uuid_column_to_ce_activity.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1232_add_analysis_uuid_column_to_ce_activity.rb
new file mode 100644 (file)
index 0000000..8f25ffe
--- /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 AddAnalysisUuidColumnToCeActivity < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.AddAnalysisUuidColumnToCeActivity')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1233_populate_analysis_uuid_column_on_ce_activity.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1233_populate_analysis_uuid_column_on_ce_activity.rb
new file mode 100644 (file)
index 0000000..d2642bd
--- /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 PopulateAnalysisUuidColumnOnCeActivity < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.PopulateAnalysisUuidColumnOnCeActivity')
+  end
+end
diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1234_drop_snapshot_id_column_from_ce_activity.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1234_drop_snapshot_id_column_from_ce_activity.rb
new file mode 100644 (file)
index 0000000..ff454ce
--- /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 DropSnapshotIdColumnFromCeActivity < ActiveRecord::Migration
+
+  def self.up
+    execute_java_migration('org.sonar.db.version.v60.DropSnapshotIdColumnFromCeActivity')
+  end
+end
index 424de69d211fc953bfcef7df4cb3fa31bdc5b08c..89755133065e449cbfaabed768304297bce00774 100644 (file)
@@ -35,7 +35,7 @@ public class CeActivityDto {
 
   private String uuid;
   private String componentUuid;
-  private Long snapshotId;
+  private String analysisUuid;
   private Status status;
   private String taskType;
   private boolean isLast;
@@ -178,12 +178,12 @@ public class CeActivityDto {
   }
 
   @CheckForNull
-  public Long getSnapshotId() {
-    return snapshotId;
+  public String getAnalysisUuid() {
+    return analysisUuid;
   }
 
-  public CeActivityDto setSnapshotId(@Nullable Long snapshotId) {
-    this.snapshotId = snapshotId;
+  public CeActivityDto setAnalysisUuid(@Nullable String s) {
+    this.analysisUuid = s;
     return this;
   }
 
@@ -193,6 +193,7 @@ public class CeActivityDto {
       .add("uuid", uuid)
       .add("taskType", taskType)
       .add("componentUuid", componentUuid)
+      .add("analysisUuid", analysisUuid)
       .add("status", status)
       .add("isLast", isLast)
       .add("isLastKey", isLastKey)
index 1292b12b65d1ad0064f718e016e3b79c45be7ea7..e11efb849488f17d373e39dbc545a06eaf43d13d 100644 (file)
@@ -23,6 +23,7 @@ import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import java.util.Collection;
 import java.util.List;
+import java.util.Optional;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.apache.ibatis.session.RowBounds;
@@ -42,11 +43,19 @@ public class SnapshotDao implements Dao {
     return previousLastSnapshot == null || previousLastSnapshot.getCreatedAt() < snapshotTested.getCreatedAt();
   }
 
+  /**
+   * @deprecated use {@link #selectByUuid(DbSession, String)}
+   */
+  @Deprecated
   @CheckForNull
   public SnapshotDto selectById(DbSession session, long id) {
     return mapper(session).selectByKey(id);
   }
 
+  /**
+   * @deprecated use {@link #selectByUuid(DbSession, String)}
+   */
+  @Deprecated
   public SnapshotDto selectOrFailById(DbSession session, long id) {
     SnapshotDto value = selectById(session, id);
     if (value == null) {
@@ -100,6 +109,10 @@ public class SnapshotDao implements Dao {
     return mapper(session).selectSnapshotAndChildrenOfScope(snapshotId, Scopes.PROJECT);
   }
 
+  public Optional<SnapshotDto> selectByUuid(DbSession dbSession, String analysisUuid) {
+    return Optional.ofNullable(mapper(dbSession).selectByUuid(analysisUuid));
+  }
+
   public int updateSnapshotAndChildrenLastFlagAndStatus(DbSession session, SnapshotDto snapshot, boolean isLast, String status) {
     Long rootId = snapshot.getId();
     String path = Strings.nullToEmpty(snapshot.getPath()) + snapshot.getId() + ".%";
index e8c9cb0ab08556661b83c72fa57b3498d0687388..3318262de0c114d77ec6a407bb4c95472d04a081 100644 (file)
@@ -56,4 +56,6 @@ public interface SnapshotMapper {
 
   List<ViewsSnapshotDto> selectSnapshotBefore(@Param("componentUuid") String componentUuid, @Param("date") long date);
 
+  @CheckForNull
+  SnapshotDto selectByUuid(String analysisUuid);
 }
index 9285480a5690a73ba1c3715a3a63a790e7651267..75602eba9b3a608a71b131d43fd56fd6359a85fe 100644 (file)
@@ -30,7 +30,7 @@ import org.sonar.db.MyBatis;
 
 public class DatabaseVersion {
 
-  public static final int LAST_VERSION = 1_231;
+  public static final int LAST_VERSION = 1_234;
 
   /**
    * The minimum supported version which can be upgraded. Lower
index 521436d159764589e980c487536894d58bb83702..b1018fe89b31ad4e4866722d6b304905b1ab1007 100644 (file)
@@ -83,6 +83,7 @@ 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.AddAnalysisUuidColumnToCeActivity;
 import org.sonar.db.version.v60.AddComponentUuidColumnToMeasures;
 import org.sonar.db.version.v60.AddComponentUuidColumnsToSnapshots;
 import org.sonar.db.version.v60.AddUuidColumnToSnapshots;
@@ -97,17 +98,19 @@ import org.sonar.db.version.v60.DropIdColumnsFromResourceIndex;
 import org.sonar.db.version.v60.DropIdColumnsFromSnapshots;
 import org.sonar.db.version.v60.DropProjectIdColumnFromMeasures;
 import org.sonar.db.version.v60.DropRememberMeColumnsFromUsers;
+import org.sonar.db.version.v60.DropSnapshotIdColumnFromCeActivity;
 import org.sonar.db.version.v60.DropUnusedMeasuresColumns;
 import org.sonar.db.version.v60.MakeComponentUuidColumnsNotNullOnSnapshots;
 import org.sonar.db.version.v60.MakeComponentUuidNotNullOnMeasures;
 import org.sonar.db.version.v60.MakeUuidColumnNotNullOnSnapshots;
 import org.sonar.db.version.v60.MakeUuidColumnsNotNullOnProjects;
 import org.sonar.db.version.v60.MakeUuidColumnsNotNullOnResourceIndex;
+import org.sonar.db.version.v60.PopulateAnalysisUuidColumnOnCeActivity;
+import org.sonar.db.version.v60.PopulateComponentUuidColumnsOfSnapshots;
 import org.sonar.db.version.v60.PopulateComponentUuidOfMeasures;
 import org.sonar.db.version.v60.PopulateUuidColumnOnSnapshots;
 import org.sonar.db.version.v60.PopulateUuidColumnsOfProjects;
 import org.sonar.db.version.v60.PopulateUuidColumnsOfResourceIndex;
-import org.sonar.db.version.v60.PopulateComponentUuidColumnsOfSnapshots;
 
 public class MigrationStepModule extends Module {
   @Override
@@ -219,7 +222,12 @@ public class MigrationStepModule extends Module {
       // SNAPSHOTS.UUID
       AddUuidColumnToSnapshots.class,
       PopulateUuidColumnOnSnapshots.class,
-      MakeUuidColumnNotNullOnSnapshots.class
+      MakeUuidColumnNotNullOnSnapshots.class,
+
+      // CE_ACTIVITY.ANALYSIS_UUID
+      AddAnalysisUuidColumnToCeActivity.class,
+      PopulateAnalysisUuidColumnOnCeActivity.class,
+      DropSnapshotIdColumnFromCeActivity.class
     );
   }
 }
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivity.java b/sonar-db/src/main/java/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivity.java
new file mode 100644 (file)
index 0000000..fc59316
--- /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 AddAnalysisUuidColumnToCeActivity extends DdlChange {
+
+  private static final String TABLE_CE_ACTIVITY = "ce_activity";
+
+  public AddAnalysisUuidColumnToCeActivity(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(new AddColumnsBuilder(getDatabase().getDialect(), TABLE_CE_ACTIVITY)
+      .addColumn(newVarcharColumnDefBuilder().setColumnName("analysis_uuid").setLimit(UUID_VARCHAR_SIZE).setIsNullable(true).build())
+      .build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivity.java b/sonar-db/src/main/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivity.java
new file mode 100644 (file)
index 0000000..7e0b659
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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 DropSnapshotIdColumnFromCeActivity extends DdlChange {
+
+  private static final String TABLE_CE_ACTIVITY = "ce_activity";
+
+  public DropSnapshotIdColumnFromCeActivity(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    context.execute(
+      new DropColumnsBuilder(
+        getDatabase().getDialect(), TABLE_CE_ACTIVITY,
+        "snapshot_id")
+          .build());
+  }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivity.java b/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivity.java
new file mode 100644 (file)
index 0000000..4dde536
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.version.BaseDataChange;
+import org.sonar.db.version.MassUpdate;
+import org.sonar.db.version.Select;
+import org.sonar.db.version.SqlStatement;
+
+public class PopulateAnalysisUuidColumnOnCeActivity extends BaseDataChange {
+
+  public PopulateAnalysisUuidColumnOnCeActivity(Database db) {
+    super(db);
+  }
+
+  @Override
+  public void execute(Context context) throws SQLException {
+    MassUpdate massUpdate = context.prepareMassUpdate();
+    massUpdate.select("SELECT a.id, s.uuid from ce_activity a inner join snapshots s on s.id=a.snapshot_id where a.snapshot_id is not null and a.analysis_uuid is null");
+    massUpdate.update("UPDATE ce_activity SET analysis_uuid=? WHERE id=?");
+    massUpdate.rowPluralName("ce_activity");
+    massUpdate.execute((row, update) -> this.handle(row, update));
+  }
+
+  private boolean handle(Select.Row row, SqlStatement update) throws SQLException {
+    long id = row.getLong(1);
+    String analysisUuid = row.getString(2);
+
+    update.setString(1, analysisUuid);
+    update.setLong(2, id);
+
+    return true;
+  }
+
+}
index 69e58b22989ad458c197875500242b01d3d1efdb..ac826f15c3cb6111a4af06f0c80b0e6fe146b8d3 100644 (file)
@@ -8,7 +8,7 @@
     ca.uuid,
     ca.task_type as taskType,
     ca.component_uuid as componentUuid,
-    ca.snapshot_id as snapshotId,
+    ca.analysis_uuid as analysisUuid,
     ca.status as status,
     ca.submitter_login as submitterLogin,
     ca.submitted_at as submittedAt,
 
   <insert id="insert" parameterType="org.sonar.db.ce.CeActivityDto" useGeneratedKeys="false">
     insert into ce_activity
-    (uuid, component_uuid, snapshot_id, status, task_type, is_last, is_last_key, submitter_login, submitted_at, started_at,
+    (uuid, component_uuid, analysis_uuid, status, task_type, is_last, is_last_key, submitter_login, submitted_at,
+    started_at,
     executed_at, created_at, updated_at, execution_time_ms)
     values (
     #{uuid,jdbcType=VARCHAR},
     #{componentUuid,jdbcType=VARCHAR},
-    #{snapshotId,jdbcType=BIGINT},
+    #{analysisUuid,jdbcType=VARCHAR},
     #{status,jdbcType=VARCHAR},
     #{taskType,jdbcType=VARCHAR},
     #{isLast,jdbcType=BOOLEAN},
index 4c81f73de09175a22b19e7f4a2c3ee92d9716279..01a3ef0deef59c7f562fa4324ae26401d8297f19 100644 (file)
     </where>
   </select>
 
+  <select id="selectByUuid" parameterType="String" resultType="Snapshot">
+    SELECT
+    <include refid="snapshotColumns"/>
+    FROM snapshots s
+    WHERE s.uuid=#{uuid}
+  </select>
+
   <select id="selectByIds" parameterType="Long" resultType="Snapshot">
     SELECT
     <include refid="snapshotColumns" />
index f35f96c2cdbeba2fe7238fda35820e2f2b6a5986..af6597ae6732b2ef8a36b56b77e92266d4061682 100644 (file)
@@ -438,6 +438,9 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1228');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1229');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1230');
 INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1231');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1232');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1233');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('1234');
 
 INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, EXTERNAL_IDENTITY, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT) VALUES (1, 'admin', 'Administrator', '', 'admin', 'sonarqube', true, 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '1418215735482', '1418215735482');
 ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
index f0433733cc297b32c359b1536ab538193c1ec3e4..0a762dd2fb65dadbc9a5d4688c92f87c43515eea 100644 (file)
@@ -513,7 +513,7 @@ CREATE TABLE "CE_ACTIVITY" (
   "UUID" VARCHAR(40) NOT NULL,
   "TASK_TYPE" VARCHAR(15) NOT NULL,
   "COMPONENT_UUID" VARCHAR(40) NULL,
-  "SNAPSHOT_ID" INTEGER NULL,
+  "ANALYSIS_UUID" VARCHAR(50) NULL,
   "STATUS" VARCHAR(15) NOT NULL,
   "IS_LAST" BOOLEAN NOT NULL,
   "IS_LAST_KEY" VARCHAR(55) NOT NULL,
index c233b42c15dfc8815b2d40c7c4444b18eddd483f..bfff8a777d3246093096215d48788638e281b21a 100644 (file)
@@ -39,6 +39,8 @@ import static org.sonar.db.ce.CeTaskTypes.REPORT;
 
 public class CeActivityDaoTest {
 
+  private static final String AN_ANALYSIS_UUID = "U1";
+
   TestSystem2 system2 = new TestSystem2().setNow(1_450_000_000_000L);
 
   @Rule
@@ -64,7 +66,7 @@ public class CeActivityDaoTest {
     assertThat(saved.get().getStartedAt()).isEqualTo(1_500_000_000_000L);
     assertThat(saved.get().getExecutedAt()).isEqualTo(1_500_000_000_500L);
     assertThat(saved.get().getExecutionTimeMs()).isEqualTo(500L);
-    assertThat(saved.get().getSnapshotId()).isEqualTo(123_456);
+    assertThat(saved.get().getAnalysisUuid()).isEqualTo("U1");
     assertThat(saved.get().toString()).isNotEmpty();
   }
 
@@ -244,7 +246,7 @@ public class CeActivityDaoTest {
     dto.setStartedAt(1_500_000_000_000L);
     dto.setExecutedAt(1_500_000_000_500L);
     dto.setExecutionTimeMs(500L);
-    dto.setSnapshotId(123_456L);
+    dto.setAnalysisUuid(AN_ANALYSIS_UUID);
     underTest.insert(db.getSession(), dto);
   }
 
index fa8bfbee32fbae0ca1f8e65890a4aad1e092399c..6569992d9b1e183c49283b3f9c6bcd2ed5051850 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.db.component;
 
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -41,7 +42,6 @@ import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC;
 import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
 import static org.sonar.db.component.SnapshotTesting.newSnapshotForProject;
 
-
 public class SnapshotDaoTest {
 
   @Rule
@@ -56,7 +56,17 @@ public class SnapshotDaoTest {
   SnapshotDao underTest = dbClient.snapshotDao();
 
   @Test
-  public void get_by_key() {
+  public void test_selectByUuid() {
+    db.prepareDbUnit(getClass(), "shared.xml");
+
+    Optional<SnapshotDto> result = underTest.selectByUuid(db.getSession(), "u3");
+    assertThat(result.isPresent()).isTrue();
+
+    assertThat(underTest.selectByUuid(db.getSession(), "DOES_NOT_EXIST").isPresent()).isFalse();
+  }
+
+  @Test
+  public void test_selectById() {
     db.prepareDbUnit(getClass(), "shared.xml");
 
     SnapshotDto result = underTest.selectById(db.getSession(), 3L);
@@ -99,7 +109,7 @@ public class SnapshotDaoTest {
   }
 
   @Test
-  public void select_by_ids() {
+  public void test_selectByIds() {
     SnapshotDto snapshot1 = componentDb.insertProjectAndSnapshot(newProjectDto());
     SnapshotDto snapshot2 = componentDb.insertProjectAndSnapshot(newProjectDto());
     SnapshotDto snapshot3 = componentDb.insertProjectAndSnapshot(newProjectDto());
@@ -226,8 +236,7 @@ public class SnapshotDaoTest {
     db.getDbClient().snapshotDao().insert(dbSession,
       newSnapshotForProject(project).setCreatedAt(5L),
       newSnapshotForProject(project).setCreatedAt(2L),
-      newSnapshotForProject(project).setCreatedAt(1L)
-      );
+      newSnapshotForProject(project).setCreatedAt(1L));
     dbSession.commit();
 
     SnapshotDto dto = underTest.selectOldestSnapshot(dbSession, project.uuid());
index 27ad48aceb84ab40c790db2dbaeaf434c1281ced..152848d750a59c7f20df1f3abdc4571acc2fc15c 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(90);
+    assertThat(container.size()).isEqualTo(93);
   }
 }
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest.java
new file mode 100644 (file)
index 0000000..0cedf70
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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 AddAnalysisUuidColumnToCeActivityTest {
+
+  private static final long A_DATE = 123_456L;
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, AddAnalysisUuidColumnToCeActivityTest.class, "old_ce_activity.sql");
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  private AddAnalysisUuidColumnToCeActivity underTest = new AddAnalysisUuidColumnToCeActivity(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(
+        "ce_activity",
+        "uuid", valueOf(i),
+        "task_type", "REPORT",
+        "status", "SUCCESS",
+        "is_last", valueOf(true),
+        "is_last_key", valueOf(i + 100),
+        "created_at", valueOf(A_DATE),
+        "updated_at", valueOf(A_DATE),
+        "submitted_at", valueOf(A_DATE));
+    }
+    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("ce_activity", "analysis_uuid", Types.VARCHAR, 50, true);
+  }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivityTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivityTest.java
new file mode 100644 (file)
index 0000000..d9a1e4e
--- /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 DropSnapshotIdColumnFromCeActivityTest {
+
+  private Database database = mock(Database.class);
+  private DropSnapshotIdColumnFromCeActivity underTest = new DropSnapshotIdColumnFromCeActivity(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 ce_activity DROP COLUMN snapshot_id");
+  }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest.java b/sonar-db/src/test/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest.java
new file mode 100644 (file)
index 0000000..b5e9132
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2016 SonarSource SA
+ * mailto:contact AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+package org.sonar.db.version.v60;
+
+import java.sql.SQLException;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.RandomStringUtils;
+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 PopulateAnalysisUuidColumnOnCeActivityTest {
+
+  private static final long A_DATE = 123_456L;
+  private static final String TABLE_CE_ACTIVITY = "ce_activity";
+  private static final String TABLE_SNAPSHOTS = "snapshots";
+
+  @Rule
+  public DbTester db = DbTester.createForSchema(System2.INSTANCE, PopulateAnalysisUuidColumnOnCeActivityTest.class,
+    "in_progress_ce_activity.sql");
+
+  private PopulateAnalysisUuidColumnOnCeActivity underTest = new PopulateAnalysisUuidColumnOnCeActivity(db.database());
+
+  @Test
+  public void migration_has_no_effect_on_empty_tables() throws SQLException {
+    underTest.execute();
+
+    assertThat(db.countRowsOfTable(TABLE_CE_ACTIVITY)).isEqualTo(0);
+  }
+
+  @Test
+  public void migration_generates_uuids() throws SQLException {
+    insertSnapshot(1, "U1");
+    insertSnapshot(2, "U2");
+    insertCeActivity(1, null);
+    insertCeActivity(2, 1L);
+    insertCeActivity(3, 2L);
+    db.commit();
+
+    underTest.execute();
+
+    verifyAnalysisUuid(1, null);
+    verifyAnalysisUuid(2, "U1");
+    verifyAnalysisUuid(3, "U2");
+  }
+
+  @Test
+  public void migration_is_reentrant() throws SQLException {
+    insertSnapshot(1, "U1");
+    insertCeActivity(1, null);
+    insertCeActivity(2, 1L);
+
+    underTest.execute();
+    verifyAnalysisUuid(1, null);
+    verifyAnalysisUuid(2, "U1");
+
+    underTest.execute();
+    verifyAnalysisUuid(1, null);
+    verifyAnalysisUuid(2, "U1");
+  }
+
+  private void verifyAnalysisUuid(int activityId, @Nullable String expectedAnalysisUuid) {
+    Map<String, Object> rows = db.selectFirst("select analysis_uuid as \"analysisUuid\" from ce_activity where id=" + activityId);
+    assertThat(rows.get("analysisUuid")).isEqualTo(expectedAnalysisUuid);
+  }
+
+  private String insertSnapshot(long id, String uuid) {
+    db.executeInsert(
+      TABLE_SNAPSHOTS,
+      "ID", valueOf(id),
+      "UUID", uuid,
+      "COMPONENT_UUID", valueOf(id + 10),
+      "ROOT_COMPONENT_UUID", valueOf(id + 100),
+      "SCOPE", "PRJ",
+      "QUALIFIER", "FIL");
+    return uuid;
+  }
+
+  private void insertCeActivity(long id, @Nullable Long snapshotId) {
+    db.executeInsert(
+      TABLE_CE_ACTIVITY,
+      "uuid", valueOf(id),
+      "snapshot_id", snapshotId == null ? null : valueOf(snapshotId),
+      "task_type", "REPORT",
+      "status", "SUCCESS",
+      "is_last", valueOf(true),
+      "is_last_key", RandomStringUtils.randomAlphabetic(10),
+      "created_at", valueOf(A_DATE),
+      "updated_at", valueOf(A_DATE),
+      "submitted_at", valueOf(A_DATE));
+  }
+
+}
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest/old_ce_activity.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest/old_ce_activity.sql
new file mode 100644 (file)
index 0000000..8fbdcb6
--- /dev/null
@@ -0,0 +1,17 @@
+CREATE TABLE "CE_ACTIVITY" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "TASK_TYPE" VARCHAR(15) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(40) NULL,
+  "SNAPSHOT_ID" INTEGER NULL,
+  "STATUS" VARCHAR(15) NOT NULL,
+  "IS_LAST" BOOLEAN NOT NULL,
+  "IS_LAST_KEY" VARCHAR(55) NOT NULL,
+  "SUBMITTER_LOGIN" VARCHAR(255) NULL,
+  "SUBMITTED_AT" BIGINT NOT NULL,
+  "STARTED_AT" BIGINT NULL,
+  "EXECUTED_AT" BIGINT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+  "EXECUTION_TIME_MS" BIGINT NULL
+);
diff --git a/sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest/in_progress_ce_activity.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest/in_progress_ce_activity.sql
new file mode 100644 (file)
index 0000000..25d5c6c
--- /dev/null
@@ -0,0 +1,52 @@
+CREATE TABLE "CE_ACTIVITY" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "TASK_TYPE" VARCHAR(15) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(40) NULL,
+  "SNAPSHOT_ID" INTEGER NULL,
+  "ANALYSIS_UUID" VARCHAR(50) NULL,
+  "STATUS" VARCHAR(15) NOT NULL,
+  "IS_LAST" BOOLEAN NOT NULL,
+  "IS_LAST_KEY" VARCHAR(55) NOT NULL,
+  "SUBMITTER_LOGIN" VARCHAR(255) NULL,
+  "SUBMITTED_AT" BIGINT NOT NULL,
+  "STARTED_AT" BIGINT NULL,
+  "EXECUTED_AT" BIGINT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+  "EXECUTION_TIME_MS" BIGINT NULL
+);
+
+CREATE TABLE "SNAPSHOTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(50) NOT NULL,
+  "CREATED_AT" BIGINT,
+  "BUILD_DATE" BIGINT,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "PARENT_SNAPSHOT_ID" INTEGER,
+  "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+  "PURGE_STATUS" INTEGER,
+  "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+  "SCOPE" VARCHAR(3),
+  "QUALIFIER" VARCHAR(10),
+  "ROOT_SNAPSHOT_ID" INTEGER,
+  "VERSION" VARCHAR(500),
+  "PATH" VARCHAR(500),
+  "DEPTH" INTEGER,
+  "ROOT_COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "PERIOD1_MODE" VARCHAR(100),
+  "PERIOD1_PARAM" VARCHAR(100),
+  "PERIOD1_DATE" BIGINT,
+  "PERIOD2_MODE" VARCHAR(100),
+  "PERIOD2_PARAM" VARCHAR(100),
+  "PERIOD2_DATE" BIGINT,
+  "PERIOD3_MODE" VARCHAR(100),
+  "PERIOD3_PARAM" VARCHAR(100),
+  "PERIOD3_DATE" BIGINT,
+  "PERIOD4_MODE" VARCHAR(100),
+  "PERIOD4_PARAM" VARCHAR(100),
+  "PERIOD4_DATE" BIGINT,
+  "PERIOD5_MODE" VARCHAR(100),
+  "PERIOD5_PARAM" VARCHAR(100),
+  "PERIOD5_DATE" BIGINT
+);