diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-06-16 22:10:06 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-06-17 20:22:08 +0200 |
commit | d1349c48d4674a7dc8e3a7bad4bc53a2bf94ebc6 (patch) | |
tree | f0cc94ec0db8425ad8b445142d26371198a7e46f | |
parent | 9865eac69141d22968f060bfb3bbadba8c9bacbf (diff) | |
download | sonarqube-d1349c48d4674a7dc8e3a7bad4bc53a2bf94ebc6.tar.gz sonarqube-d1349c48d4674a7dc8e3a7bad4bc53a2bf94ebc6.zip |
SONAR-7691 table CE_ACTIVITY should use analysis UUID
37 files changed, 687 insertions, 108 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java index 600f2fe4515..3801a1b5334 100644 --- a/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java +++ b/server/sonar-server/src/main/java/org/sonar/ce/queue/CeTaskResult.java @@ -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(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java index 12c249b7868..df0e5fcf904 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ce/ws/TaskFormatter.java @@ -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()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/InternalCeQueueImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/InternalCeQueueImpl.java index 7ffe4ddf840..6eb9497d81c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/queue/InternalCeQueueImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/queue/InternalCeQueueImpl.java @@ -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()); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PublishTaskResultStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PublishTaskResultStep.java index 656d96759d2..c2046483aa4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/PublishTaskResultStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/PublishTaskResultStep.java @@ -19,21 +19,19 @@ */ 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); } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java index 252a6b3d19c..f76a0b6e79b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ProjectStatusAction.java @@ -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()); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java b/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java index 60df0574a76..6ee8781adba 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java @@ -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(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java index 93b82da9c74..e2a4792de59 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ActivityActionTest.java @@ -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; diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java index ff27f0079b6..7be3ae0f6fb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/ComponentActionTest.java @@ -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; diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java index f0842056d78..8584d97a4f3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskActionTest.java @@ -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(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java index c2b3c191354..a5a71be90a2 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/ce/ws/TaskFormatterTest.java @@ -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; } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/InternalCeQueueImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/InternalCeQueueImplTest.java index 5e407ac4fa6..66ad196524d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/queue/InternalCeQueueImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/queue/InternalCeQueueImplTest.java @@ -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; } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PublishTaskResultStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PublishTaskResultStepTest.java index ffce1b73108..19c96c742ac 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PublishTaskResultStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PublishTaskResultStepTest.java @@ -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); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java index 438423722b3..a3dd6d52aeb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/ProjectStatusActionTest.java @@ -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 index 00000000000..8f25ffedab8 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1232_add_analysis_uuid_column_to_ce_activity.rb @@ -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 index 00000000000..d2642bd9b6f --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1233_populate_analysis_uuid_column_on_ce_activity.rb @@ -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 index 00000000000..ff454ce01bb --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1234_drop_snapshot_id_column_from_ce_activity.rb @@ -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 diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDto.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDto.java index 424de69d211..89755133065 100644 --- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDto.java +++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDto.java @@ -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) diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java index 1292b12b65d..e11efb84948 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java +++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java @@ -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() + ".%"; diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java index e8c9cb0ab08..3318262de0c 100644 --- a/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotMapper.java @@ -56,4 +56,6 @@ public interface SnapshotMapper { List<ViewsSnapshotDto> selectSnapshotBefore(@Param("componentUuid") String componentUuid, @Param("date") long date); + @CheckForNull + SnapshotDto selectByUuid(String analysisUuid); } diff --git a/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java b/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java index 9285480a569..75602eba9b3 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java +++ b/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java @@ -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 diff --git a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java b/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java index 521436d1597..b1018fe89b3 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java +++ b/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java @@ -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 index 00000000000..fc59316bf48 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivity.java @@ -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 index 00000000000..7e0b659efb7 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivity.java @@ -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 index 00000000000..4dde536317e --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivity.java @@ -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; + } + +} diff --git a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml index 69e58b22989..ac826f15c3c 100644 --- a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml @@ -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, @@ -122,12 +122,13 @@ <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}, diff --git a/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml index 4c81f73de09..01a3ef0deef 100644 --- a/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/component/SnapshotMapper.xml @@ -50,6 +50,13 @@ </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" /> diff --git a/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql b/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql index f35f96c2cdb..af6597ae673 100644 --- a/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql +++ b/sonar-db/src/main/resources/org/sonar/db/version/rows-h2.sql @@ -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; diff --git a/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl b/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl index f0433733cc2..0a762dd2fb6 100644 --- a/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl +++ b/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl @@ -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, diff --git a/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java b/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java index c233b42c15d..bfff8a777d3 100644 --- a/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java @@ -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); } diff --git a/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java index fa8bfbee32f..6569992d9b1 100644 --- a/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java @@ -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()); diff --git a/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java b/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java index 27ad48aceb8..152848d750a 100644 --- a/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java +++ b/sonar-db/src/test/java/org/sonar/db/version/MigrationStepModuleTest.java @@ -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 index 00000000000..0cedf70c18f --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest.java @@ -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 index 00000000000..d9a1e4e9931 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/version/v60/DropSnapshotIdColumnFromCeActivityTest.java @@ -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 index 00000000000..b5e9132ecd6 --- /dev/null +++ b/sonar-db/src/test/java/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest.java @@ -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 index 00000000000..8fbdcb6cce4 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/version/v60/AddAnalysisUuidColumnToCeActivityTest/old_ce_activity.sql @@ -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/AddComponentUuidColumnsToSnapshotsTest/old_snapshots.sql b/sonar-db/src/test/resources/org/sonar/db/version/v60/AddComponentUuidColumnsToSnapshotsTest/old_snapshots.sql index 832463b246c..1472d580371 100644 --- a/sonar-db/src/test/resources/org/sonar/db/version/v60/AddComponentUuidColumnsToSnapshotsTest/old_snapshots.sql +++ b/sonar-db/src/test/resources/org/sonar/db/version/v60/AddComponentUuidColumnsToSnapshotsTest/old_snapshots.sql @@ -30,3 +30,4 @@ CREATE TABLE "SNAPSHOTS" ( "PERIOD5_PARAM" VARCHAR(100), "PERIOD5_DATE" BIGINT ); + 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 index 00000000000..25d5c6cb28f --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/version/v60/PopulateAnalysisUuidColumnOnCeActivityTest/in_progress_ce_activity.sql @@ -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 +); |