diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-10-05 12:55:35 +0200 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2015-10-05 15:39:00 +0200 |
commit | a3caa98f84849143fa78f9fc286079e871b3c9dd (patch) | |
tree | 4deec6bf15632e570e10b35e6df5cd7340025017 | |
parent | bce3d38e9c99e156a8251f95cb437f3d54ee9a80 (diff) | |
download | sonarqube-a3caa98f84849143fa78f9fc286079e871b3c9dd.tar.gz sonarqube-a3caa98f84849143fa78f9fc286079e871b3c9dd.zip |
SONAR-6397 Do not read SCM info from db on first analysis
15 files changed, 250 insertions, 21 deletions
diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java index 87ad097dbab..09520d5b788 100644 --- a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java +++ b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/PersistFileSourcesStepTest.java @@ -37,6 +37,7 @@ import org.sonar.batch.protocol.output.BatchReportWriter; import org.sonar.core.util.Uuids; import org.sonar.db.DbClient; import org.sonar.db.DbTester; +import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule; import org.sonar.server.computation.batch.BatchReportDirectoryHolderImpl; import org.sonar.server.computation.batch.BatchReportReaderImpl; import org.sonar.server.computation.batch.TreeRootHolderRule; @@ -69,6 +70,9 @@ public class PersistFileSourcesStepTest { @Rule public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + @Rule + public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule(); + @Test public void benchmark() throws Exception { File reportDir = prepareReport(); @@ -85,7 +89,8 @@ public class PersistFileSourcesStepTest { batchReportDirectoryHolder.setDirectory(reportDir); org.sonar.server.computation.batch.BatchReportReader batchReportReader = new BatchReportReaderImpl(batchReportDirectoryHolder); SourceService sourceService = new SourceService(dbClient, null); - ScmInfoRepositoryImpl scmInfoRepository = new ScmInfoRepositoryImpl(batchReportReader, dbClient, sourceService); + analysisMetadataHolder.setIsFirstAnalysis(false); + ScmInfoRepositoryImpl scmInfoRepository = new ScmInfoRepositoryImpl(batchReportReader, analysisMetadataHolder, dbClient, sourceService); PersistFileSourcesStep step = new PersistFileSourcesStep(dbClient, System2.INSTANCE, treeRootHolder, batchReportReader, new SourceLinesRepositoryImpl(batchReportReader), scmInfoRepository); step.execute(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java index 5653e72110f..445fd8a63c8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/AnalysisMetadataHolder.java @@ -26,4 +26,9 @@ public interface AnalysisMetadataHolder { * @throws IllegalStateException if no analysis date has been set */ Date getAnalysisDate(); + + /** + * @throws IllegalStateException if isFirstAnalysis has not been set + */ + boolean isFirstAnalysis(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java index aa8736419ea..1733010fc93 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolder.java @@ -27,4 +27,9 @@ public interface MutableAnalysisMetadataHolder extends AnalysisMetadataHolder { * @throws IllegalStateException if the analysis date has already been set */ void setAnalysisDate(Date date); + + /** + * @throws IllegalStateException if isFirstAnalysis has already been set + */ + void setIsFirstAnalysis(boolean isFirstAnalysis); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java index fa1fdf3754b..64e4c923d0a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolder.java @@ -28,6 +28,9 @@ public class ReportAnalysisMetadataHolder implements MutableAnalysisMetadataHold @CheckForNull private Long analysisDate; + @CheckForNull + private Boolean firstAnalysis; + @Override public void setAnalysisDate(Date date) { checkState(analysisDate == null, "Analysis date has already been set"); @@ -39,4 +42,16 @@ public class ReportAnalysisMetadataHolder implements MutableAnalysisMetadataHold checkState(analysisDate != null, "Analysis date has not been set"); return new Date(this.analysisDate); } + + @Override + public void setIsFirstAnalysis(boolean firstAnalysis) { + checkState(this.firstAnalysis == null, "firstAnalysis flag has already been set"); + this.firstAnalysis = firstAnalysis; + } + + @Override + public boolean isFirstAnalysis() { + checkState(firstAnalysis != null, "firstAnalysis flag has not been set"); + return firstAnalysis; + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java b/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java index 20a7e1d88b9..b39fc819f20 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/scm/ScmInfoRepositoryImpl.java @@ -28,6 +28,7 @@ import org.sonar.batch.protocol.output.BatchReport; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.protobuf.DbFileSources; +import org.sonar.server.computation.analysis.AnalysisMetadataHolder; import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.Component; import org.sonar.server.source.SourceService; @@ -39,13 +40,15 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository { private static final Logger LOGGER = Loggers.get(ScmInfoRepositoryImpl.class); private final BatchReportReader batchReportReader; + private final AnalysisMetadataHolder analysisMetadataHolder; private final DbClient dbClient; private final SourceService sourceService; private final Map<Component, ScmInfo> scmInfoCache = new HashMap<>(); - public ScmInfoRepositoryImpl(BatchReportReader batchReportReader, DbClient dbClient, SourceService sourceService) { + public ScmInfoRepositoryImpl(BatchReportReader batchReportReader, AnalysisMetadataHolder analysisMetadataHolder, DbClient dbClient, SourceService sourceService) { this.batchReportReader = batchReportReader; + this.analysisMetadataHolder = analysisMetadataHolder; this.dbClient = dbClient; this.sourceService = sourceService; } @@ -68,15 +71,17 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository { private Optional<ScmInfo> getScmInfoForComponent(Component component) { BatchReport.Changesets changesets = batchReportReader.readChangesets(component.getReportAttributes().getRef()); if (changesets == null) { - LOGGER.trace("Reading SCM info from db for file '{}'", component); return getScmInfoFromDb(component); - } else { - LOGGER.trace("Reading SCM info from report for file '{}'", component); - return Optional.<ScmInfo>of(new ReportScmInfo(changesets)); } + return getScmInfoFromReport(component, changesets); } private Optional<ScmInfo> getScmInfoFromDb(Component component) { + if (analysisMetadataHolder.isFirstAnalysis()) { + return Optional.absent(); + } + LOGGER.trace("Reading SCM info from db for file '{}'", component); + DbSession dbSession = dbClient.openSession(false); try { Optional<Iterable<DbFileSources.Line>> linesOpt = sourceService.getLines(dbSession, component.getUuid(), 1, Integer.MAX_VALUE); @@ -88,4 +93,9 @@ public class ScmInfoRepositoryImpl implements ScmInfoRepository { dbClient.closeSession(dbSession); } } + + private static Optional<ScmInfo> getScmInfoFromReport(Component component, BatchReport.Changesets changesets) { + LOGGER.trace("Reading SCM info from report for file '{}'", component); + return Optional.<ScmInfo>of(new ReportScmInfo(changesets)); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java index 6e1e2a2fdc5..036bce963f4 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java @@ -28,6 +28,7 @@ import javax.annotation.Nullable; import org.sonar.batch.protocol.output.BatchReport; import org.sonar.core.component.ComponentKeys; import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolder; import org.sonar.server.computation.batch.BatchReportReader; import org.sonar.server.computation.component.Component; @@ -62,7 +63,18 @@ public class BuildComponentTreeStep implements ComputationStep { String branch = reportMetadata.hasBranch() ? reportMetadata.getBranch() : null; BatchReport.Component reportProject = reportReader.readComponent(reportMetadata.getRootComponentRef()); UuidFactory uuidFactory = new UuidFactory(dbClient, moduleKey(reportProject, branch)); - treeRootHolder.setRoot(new ComponentRootBuilder(reportProject, uuidFactory, branch).build()); + Component project = new ComponentRootBuilder(reportProject, uuidFactory, branch).build(); + treeRootHolder.setRoot(project); + setIsFirstAnalysis(project.getUuid()); + } + + private void setIsFirstAnalysis(String projectUuid){ + DbSession dbSession = dbClient.openSession(false); + try { + analysisMetadataHolder.setIsFirstAnalysis(!dbClient.snapshotDao().hasLastSnapshotByComponentUuid(dbSession, projectUuid)); + } finally { + dbClient.closeSession(dbSession); + } } private class ComponentRootBuilder { diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java index dd06019d1d9..ba6984f58cc 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/MutableAnalysisMetadataHolderRule.java @@ -39,4 +39,14 @@ public class MutableAnalysisMetadataHolderRule extends ExternalResource implemen public void setAnalysisDate(Date date) { delegate.setAnalysisDate(date); } + + @Override + public boolean isFirstAnalysis() { + return delegate.isFirstAnalysis(); + } + + @Override + public void setIsFirstAnalysis(boolean isFirstAnalysis) { + delegate.setIsFirstAnalysis(isFirstAnalysis); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java index d9d6cf93c3b..c5b362d9eee 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/analysis/ReportAnalysisMetadataHolderTest.java @@ -33,14 +33,6 @@ public class ReportAnalysisMetadataHolderTest { private Date someDate = new Date(); @Test - public void getAnalysisDate_throws_ISE_when_not_holder_is_not_initialized() { - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Analysis date has not been set"); - - new ReportAnalysisMetadataHolder().getAnalysisDate(); - } - - @Test public void getAnalysisDate_returns_date_with_same_time_as_the_one_set_with_setAnalysisDate() throws InterruptedException { ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder(); @@ -54,6 +46,14 @@ public class ReportAnalysisMetadataHolderTest { } @Test + public void getAnalysisDate_throws_ISE_when_holder_is_not_initialized() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Analysis date has not been set"); + + new ReportAnalysisMetadataHolder().getAnalysisDate(); + } + + @Test public void setAnalysisDate_throws_ISE_when_called_twice() { expectedException.expect(IllegalStateException.class); expectedException.expectMessage("Analysis date has already been set"); @@ -63,4 +63,39 @@ public class ReportAnalysisMetadataHolderTest { underTest.setAnalysisDate(someDate); underTest.setAnalysisDate(someDate); } + + @Test + public void isFirstAnalysis_return_true() throws Exception { + ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder(); + + underTest.setIsFirstAnalysis(true); + assertThat(underTest.isFirstAnalysis()).isTrue(); + } + + @Test + public void isFirstAnalysis_return_false() throws Exception { + ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder(); + + underTest.setIsFirstAnalysis(false); + assertThat(underTest.isFirstAnalysis()).isFalse(); + } + + @Test + public void isFirstAnalysis_throws_ISE_when_holder_is_not_initialized() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("firstAnalysis flag has not been set"); + + new ReportAnalysisMetadataHolder().isFirstAnalysis(); + } + + @Test + public void setIsFirstAnalysis_throws_ISE_when_called_twice() { + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("firstAnalysis flag has already been set"); + + ReportAnalysisMetadataHolder underTest = new ReportAnalysisMetadataHolder(); + + underTest.setIsFirstAnalysis(true); + underTest.setIsFirstAnalysis(true); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java index 6108f9f640d..6380d274b2c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java @@ -30,6 +30,7 @@ import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.protobuf.DbFileSources; import org.sonar.db.source.FileSourceDto; +import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule; import org.sonar.server.computation.batch.BatchReportReaderRule; import org.sonar.server.computation.component.Component; import org.sonar.server.source.SourceService; @@ -41,27 +42,32 @@ import static org.sonar.server.computation.component.ReportComponent.builder; public class ScmInfoRepositoryImplTest { - @Rule - public LogTester logTester = new LogTester(); + static final int FILE_REF = 1; + + static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build(); @Rule public ExpectedException thrown = ExpectedException.none(); - static final int FILE_REF = 1; - static final Component FILE = builder(Component.Type.FILE, FILE_REF).setKey("FILE_KEY").setUuid("FILE_UUID").build(); + @Rule + public LogTester logTester = new LogTester(); @Rule public BatchReportReaderRule reportReader = new BatchReportReaderRule(); @Rule + public MutableAnalysisMetadataHolderRule analysisMetadataHolder = new MutableAnalysisMetadataHolderRule(); + + @Rule public DbTester dbTester = DbTester.create(System2.INSTANCE); DbClient dbClient = dbTester.getDbClient(); - ScmInfoRepositoryImpl underTest = new ScmInfoRepositoryImpl(reportReader, dbClient, new SourceService(dbClient, null)); + ScmInfoRepositoryImpl underTest = new ScmInfoRepositoryImpl(reportReader, analysisMetadataHolder, dbClient, new SourceService(dbClient, null)); @Test public void read_from_report() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(false); addChangesetInReport("john", 123456789L, "rev-1"); ScmInfo scmInfo = underTest.getScmInfo(FILE).get(); @@ -72,6 +78,7 @@ public class ScmInfoRepositoryImplTest { @Test public void read_from_db() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(false); addChangesetInDb("henry", 123456789L, "rev-1"); ScmInfo scmInfo = underTest.getScmInfo(FILE).get(); @@ -82,6 +89,7 @@ public class ScmInfoRepositoryImplTest { @Test public void read_from_report_even_if_data_in_db_exists() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(false); addChangesetInDb("henry", 123456789L, "rev-1"); addChangesetInReport("john", 1234567810L, "rev-2"); @@ -96,11 +104,13 @@ public class ScmInfoRepositoryImplTest { @Test public void return_nothing_when_no_data_in_report_and_db() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(false); assertThat(underTest.getScmInfo(FILE)).isAbsent(); } @Test - public void return_nothing_when_nothing_in_erpot_and_db_has_no_scm() throws Exception { + public void return_nothing_when_nothing_in_report_and_db_has_no_scm() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(false); DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder(); fileDataBuilder.addLinesBuilder() .setLine(1); @@ -114,6 +124,8 @@ public class ScmInfoRepositoryImplTest { @Test public void fail_with_NPE_when_component_is_null() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(false); + thrown.expect(NullPointerException.class); thrown.expectMessage("Component cannot be bull"); @@ -122,6 +134,7 @@ public class ScmInfoRepositoryImplTest { @Test public void load_scm_info_from_cache_when_already_read() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(false); addChangesetInReport("john", 123456789L, "rev-1"); ScmInfo scmInfo = underTest.getScmInfo(FILE).get(); assertThat(scmInfo.getAllChangesets()).hasSize(1); @@ -133,6 +146,15 @@ public class ScmInfoRepositoryImplTest { assertThat(logTester.logs(TRACE)).isEmpty(); } + @Test + public void not_read_in_db_on_first_analysis() throws Exception { + analysisMetadataHolder.setIsFirstAnalysis(true); + addChangesetInDb("henry", 123456789L, "rev-1"); + + assertThat(underTest.getScmInfo(FILE)).isAbsent(); + assertThat(logTester.logs(TRACE)).isEmpty(); + } + private void addChangesetInDb(String author, Long date, String revision) { DbFileSources.Data.Builder fileDataBuilder = DbFileSources.Data.newBuilder(); fileDataBuilder.addLinesBuilder() diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java index 788507d9197..c085483ace5 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BuildComponentTreeStepTest.java @@ -38,6 +38,7 @@ import org.sonar.batch.protocol.output.BatchReport.Metadata; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.SnapshotDto; import org.sonar.server.computation.analysis.MutableAnalysisMetadataHolderRule; import org.sonar.server.computation.batch.BatchReportReaderRule; import org.sonar.server.computation.component.Component; @@ -53,6 +54,7 @@ import static org.sonar.db.component.ComponentTesting.newDirectory; import static org.sonar.db.component.ComponentTesting.newFileDto; import static org.sonar.db.component.ComponentTesting.newModuleDto; import static org.sonar.db.component.ComponentTesting.newProjectDto; +import static org.sonar.db.component.SnapshotTesting.newSnapshotForProject; @Category(DbTests.class) @RunWith(DataProviderRunner.class) @@ -274,6 +276,36 @@ public class BuildComponentTreeStepTest { verifyComponent(FILE_1_REF, REPORT_MODULE_KEY + ":" + REPORT_FILE_KEY_1, "DEFG"); } + @Test + public void set_first_analysis_to_true_when_no_snapshot() throws Exception { + reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY)); + underTest.execute(); + + assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue(); + } + + @Test + public void set_first_analysis_to_true_when_no_last_snapshot() throws Exception { + ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY)); + insertSnapshot(newSnapshotForProject(project).setLast(false)); + + reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY)); + underTest.execute(); + + assertThat(analysisMetadataHolder.isFirstAnalysis()).isTrue(); + } + + @Test + public void set_first_analysis_to_false_when_last_snapshot_exist() throws Exception { + ComponentDto project = insertComponent(newProjectDto("ABCD").setKey(REPORT_PROJECT_KEY)); + insertSnapshot(newSnapshotForProject(project).setLast(true)); + + reportReader.putComponent(componentWithKey(ROOT_REF, PROJECT, REPORT_PROJECT_KEY)); + underTest.execute(); + + assertThat(analysisMetadataHolder.isFirstAnalysis()).isFalse(); + } + private void verifyComponent(Component component, Component.Type type, int componentRef, int size) { assertThat(component.getType()).isEqualTo(type); assertThat(component.getReportAttributes().getRef()).isEqualTo(componentRef); @@ -342,4 +374,10 @@ public class BuildComponentTreeStepTest { return component; } + private SnapshotDto insertSnapshot(SnapshotDto snapshot) { + dbClient.snapshotDao().insert(dbTester.getSession(), snapshot); + dbTester.getSession().commit(); + return snapshot; + } + } 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 46306bf9a04..55d3fbbb630 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 @@ -53,6 +53,10 @@ public class SnapshotDao implements Dao { return mapper(session).selectLastSnapshot(componentId); } + public boolean hasLastSnapshotByComponentUuid(DbSession session, String componentUUid) { + return mapper(session).countLastSnapshotByComponentUuid(componentUUid) > 0; + } + public List<SnapshotDto> selectSnapshotsByComponentId(DbSession session, long componentId) { return mapper(session).selectSnapshotsByQuery(new SnapshotQuery().setComponentId(componentId)); } 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 49fe34a0ee0..a77633f7d1a 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 @@ -34,6 +34,8 @@ public interface SnapshotMapper { @CheckForNull SnapshotDto selectLastSnapshot(Long resourceId); + int countLastSnapshotByComponentUuid(String componentUuid); + List<SnapshotDto> selectSnapshotsByQuery(@Param("query") SnapshotQuery query); List<SnapshotDto> selectPreviousVersionSnapshots(@Param(value = "componentId") Long componentId, @Param(value = "lastVersion") String lastVersion); 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 6892b27e3b6..01b89c7e1aa 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 @@ -56,6 +56,15 @@ where s.islast=${_true} and s.project_id = #{resource} </select> + <select id="countLastSnapshotByComponentUuid" resultType="Integer"> + SELECT count(s.id) + FROM snapshots s + INNER JOIN projects p ON p.id=s.project_id AND p.uuid=#{componentUuid} + <where> + AND s.islast=${_true} + </where> + </select> + <select id="selectSnapshotsByQuery" parameterType="map" resultType="Snapshot"> SELECT <include refid="snapshotColumns"/> 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 4377a7d45ca..9768a52e1c6 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 @@ -261,6 +261,15 @@ public class SnapshotDaoTest { assertThat(isLast).isFalse(); } + @Test + public void has_last_snapshot_by_component_uuid() throws Exception { + db.prepareDbUnit(getClass(), "has_last_snapshot_by_component_uuid.xml"); + + assertThat(underTest.hasLastSnapshotByComponentUuid(db.getSession(), "ABCD")).isTrue(); + assertThat(underTest.hasLastSnapshotByComponentUuid(db.getSession(), "EFGH")).isFalse(); + assertThat(underTest.hasLastSnapshotByComponentUuid(db.getSession(), "FGHI")).isFalse(); + } + private static SnapshotDto defaultSnapshot() { return new SnapshotDto() .setComponentId(3L) diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/has_last_snapshot_by_component_uuid.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/has_last_snapshot_by_component_uuid.xml new file mode 100644 index 00000000000..16f7fe75471 --- /dev/null +++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/has_last_snapshot_by_component_uuid.xml @@ -0,0 +1,48 @@ +<dataset> + + <!-- Has last snapshot --> + <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts" + uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="." + description="the description" long_name="Apache Struts" + enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="[null]" /> + <snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[true]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000" build_date="1228222680000" + version="[null]" path=""/> + <snapshots id="10" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228136280000" build_date="1228136280000" + version="[null]" path=""/> + + <!-- No snapshot --> + <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core" + uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." + scope="PRJ" qualifier="BRC" long_name="Struts Core" + description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> + + <!-- No last snapshot --> + <projects id="3" root_id="1" kee="org.struts:struts-data" name="Struts Data" + uuid="FGHI" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH." + scope="PRJ" qualifier="BRC" long_name="Struts Data" + description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" /> + <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1" + status="P" islast="[false]" purge_status="[null]" + period1_mode="[null]" period1_param="[null]" period1_date="[null]" + period2_mode="[null]" period2_param="[null]" period2_date="[null]" + period3_mode="[null]" period3_param="[null]" period3_date="[null]" + period4_mode="[null]" period4_param="[null]" period4_date="[null]" + period5_mode="[null]" period5_param="[null]" period5_date="[null]" + depth="[null]" scope="PRJ" qualifier="BRC" created_at="1228222680000" build_date="1228222680000" + version="[null]" path="1.2."/> + +</dataset> |