]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7689 support DUPLICATIONS_INDEX.ANALYSIS_UUID in code 1057/head
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Tue, 21 Jun 2016 10:08:02 +0000 (12:08 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Wed, 22 Jun 2016 11:46:22 +0000 (13:46 +0200)
26 files changed:
server/sonar-server/src/main/java/org/sonar/server/computation/snapshot/Snapshot.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/BuildComponentTreeStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/LoadCrossProjectDuplicationsRepositoryStep.java
server/sonar-server/src/main/java/org/sonar/server/computation/step/PersistCrossProjectDuplicationIndexStep.java
server/sonar-server/src/test/java/org/sonar/server/computation/analysis/AnalysisMetadataHolderImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/filemove/FileMoveDetectionStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/scm/ScmInfoRepositoryImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/snapshot/SnapshotImplTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/LoadCrossProjectDuplicationsRepositoryStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistCrossProjectDuplicationIndexStepTest.java
sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java
sonar-db/src/main/java/org/sonar/db/duplication/DuplicationMapper.java
sonar-db/src/main/java/org/sonar/db/duplication/DuplicationUnitDto.java
sonar-db/src/main/java/org/sonar/db/purge/IdUuidPairs.java
sonar-db/src/main/java/org/sonar/db/purge/PurgeCommands.java
sonar-db/src/main/java/org/sonar/db/purge/PurgeMapper.java
sonar-db/src/main/resources/org/sonar/db/duplication/DuplicationMapper.xml
sonar-db/src/main/resources/org/sonar/db/purge/PurgeMapper.xml
sonar-db/src/test/java/org/sonar/db/duplication/DuplicationDaoTest.java
sonar-db/src/test/java/org/sonar/db/purge/PurgeCommandsTest.java
sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/insert-result.xml
sonar-db/src/test/resources/org/sonar/db/duplication/DuplicationDaoTest/select_candidates.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot-result.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldDeleteSnapshot.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot-result.xml
sonar-db/src/test/resources/org/sonar/db/purge/PurgeCommandsTest/shouldPurgeSnapshot.xml

index b7db3767cee15f417c0189d8d98de2f07f9352a6..28ae303b75dab91ac0c70aa0c31cb8e05de017bf 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.server.computation.snapshot;
 
 import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
 import javax.annotation.concurrent.Immutable;
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -28,10 +29,12 @@ import static com.google.common.base.Preconditions.checkNotNull;
 public class Snapshot {
 
   private long id;
+  private String uuid;
   private long createdAt;
 
   private Snapshot(Builder builder) {
     this.id = builder.id;
+    this.uuid = builder.uuid;
     this.createdAt = builder.createdAt;
   }
 
@@ -39,6 +42,10 @@ public class Snapshot {
     return id;
   }
 
+  public String getUuid() {
+    return uuid;
+  }
+
   public long getCreatedAt() {
     return createdAt;
   }
@@ -47,6 +54,8 @@ public class Snapshot {
     @CheckForNull
     private Long id;
     @CheckForNull
+    private String uuid;
+    @CheckForNull
     private Long createdAt;
 
     public Builder setId(long id) {
@@ -54,6 +63,11 @@ public class Snapshot {
       return this;
     }
 
+    public Builder setUuid(String uuid) {
+      this.uuid = uuid;
+      return this;
+    }
+
     public Builder setCreatedAt(long createdAt) {
       this.createdAt = createdAt;
       return this;
@@ -61,13 +75,14 @@ public class Snapshot {
 
     public Snapshot build() {
       checkNotNull(id, "id cannot be null");
+      checkNotNull(uuid, "uuid cannot be null");
       checkNotNull(createdAt, "createdAt cannot be null");
       return new Snapshot(this);
     }
   }
 
   @Override
-  public boolean equals(Object o) {
+  public boolean equals(@Nullable Object o) {
     if (this == o) {
       return true;
     }
@@ -86,8 +101,9 @@ public class Snapshot {
 
   @Override
   public String toString() {
-    return "SnapshotImpl{" +
+    return "Snapshot{" +
       "id=" + id +
+      ", uuid='" + uuid + '\'' +
       ", createdAt=" + createdAt +
       '}';
   }
index 1805581d6fb5c8602625ec8a3e584669908d1c93..c0dfa740a93d9c5c0390d9255153af004b41c52a 100644 (file)
@@ -83,6 +83,7 @@ public class BuildComponentTreeStep implements ComputationStep {
   private static Snapshot toSnapshot(@Nullable SnapshotDto snapshotDto) {
     return snapshotDto == null ? null : new Snapshot.Builder()
       .setId(snapshotDto.getId())
+      .setUuid(snapshotDto.getUuid())
       .setCreatedAt(snapshotDto.getCreatedAt())
       .build();
   }
index addd61f5fab01ab8e9818a18e8a21aa7a1847638..11e8860d04a1d159f33bf8b5f294723205f93378 100644 (file)
@@ -118,8 +118,8 @@ public class LoadCrossProjectDuplicationsRepositoryStep implements ComputationSt
       DbSession dbSession = dbClient.openSession(false);
       try {
         Snapshot projectSnapshot = analysisMetadataHolder.getBaseProjectSnapshot();
-        Long projectSnapshotId = projectSnapshot == null ? null : projectSnapshot.getId();
-        return dbClient.duplicationDao().selectCandidates(dbSession, projectSnapshotId, file.getFileAttributes().getLanguageKey(), hashes);
+        String analysisUuid = projectSnapshot == null ? null : projectSnapshot.getUuid();
+        return dbClient.duplicationDao().selectCandidates(dbSession, analysisUuid, file.getFileAttributes().getLanguageKey(), hashes);
       } finally {
         dbClient.closeSession(dbSession);
       }
index a59c2af1306a6b12d4ce8bf6430ae1593ec38589..5ed6136e9c699b8e908ed22107fedd9666424210 100644 (file)
@@ -24,10 +24,10 @@ import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.duplication.DuplicationUnitDto;
 import org.sonar.scanner.protocol.output.ScannerReport;
+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.computation.component.CrawlerDepthLimit;
-import org.sonar.server.computation.component.DbIdsRepository;
 import org.sonar.server.computation.component.DepthTraversalTypeAwareCrawler;
 import org.sonar.server.computation.component.TreeRootHolder;
 import org.sonar.server.computation.component.TypeAwareVisitorAdapter;
@@ -42,28 +42,30 @@ public class PersistCrossProjectDuplicationIndexStep implements ComputationStep
 
   private final DbClient dbClient;
   private final TreeRootHolder treeRootHolder;
+  private final AnalysisMetadataHolder analysisMetadataHolder;
   private final BatchReportReader reportReader;
-  private final DbIdsRepository dbIdsRepository;
   private final CrossProjectDuplicationStatusHolder crossProjectDuplicationStatusHolder;
 
-  public PersistCrossProjectDuplicationIndexStep(DbClient dbClient, DbIdsRepository dbIdsRepository, TreeRootHolder treeRootHolder, BatchReportReader reportReader,
-    CrossProjectDuplicationStatusHolder crossProjectDuplicationStatusHolder) {
+  public PersistCrossProjectDuplicationIndexStep(CrossProjectDuplicationStatusHolder crossProjectDuplicationStatusHolder, DbClient dbClient,
+    TreeRootHolder treeRootHolder, AnalysisMetadataHolder analysisMetadataHolder,
+    BatchReportReader reportReader) {
     this.dbClient = dbClient;
     this.treeRootHolder = treeRootHolder;
+    this.analysisMetadataHolder = analysisMetadataHolder;
     this.reportReader = reportReader;
-    this.dbIdsRepository = dbIdsRepository;
     this.crossProjectDuplicationStatusHolder = crossProjectDuplicationStatusHolder;
   }
 
   @Override
   public void execute() {
+    if (!crossProjectDuplicationStatusHolder.isEnabled()) {
+      return;
+    }
+
     DbSession session = dbClient.openSession(true);
     try {
-      if (crossProjectDuplicationStatusHolder.isEnabled()) {
-        Component project = treeRootHolder.getRoot();
-        long projectSnapshotId = dbIdsRepository.getSnapshotId(project);
-        new DepthTraversalTypeAwareCrawler(new DuplicationVisitor(session, projectSnapshotId)).visit(project);
-      }
+      Component project = treeRootHolder.getRoot();
+      new DepthTraversalTypeAwareCrawler(new DuplicationVisitor(session, analysisMetadataHolder.getUuid())).visit(project);
       session.commit();
     } finally {
       dbClient.closeSession(session);
@@ -73,12 +75,12 @@ public class PersistCrossProjectDuplicationIndexStep implements ComputationStep
   private class DuplicationVisitor extends TypeAwareVisitorAdapter {
 
     private final DbSession session;
-    private final long projectSnapshotId;
+    private final String analysisUuid;
 
-    private DuplicationVisitor(DbSession session, long projectSnapshotId) {
+    private DuplicationVisitor(DbSession session, String analysisUuid) {
       super(CrawlerDepthLimit.FILE, PRE_ORDER);
       this.session = session;
-      this.projectSnapshotId = projectSnapshotId;
+      this.analysisUuid = analysisUuid;
     }
 
     @Override
@@ -99,9 +101,8 @@ public class PersistCrossProjectDuplicationIndexStep implements ComputationStep
               .setStartLine(block.getStartLine())
               .setEndLine(block.getEndLine())
               .setIndexInFile(indexInFile)
-              .setSnapshotId(dbIdsRepository.getSnapshotId(component))
-              .setComponentUuid(component.getUuid())
-              .setProjectSnapshotId(projectSnapshotId));
+              .setAnalysisUuid(analysisUuid)
+              .setComponentUuid(component.getUuid()));
           indexInFile++;
         }
       } finally {
index 7dbe09306e5aec784438d0e0b0496c7252c5e959..029815d10e5c67c06ff0a3f2d95b4eede7ab5132 100644 (file)
@@ -33,6 +33,7 @@ public class AnalysisMetadataHolderImplTest {
 
   static Snapshot BASE_PROJECT_SNAPSHOT = new Snapshot.Builder()
     .setId(1)
+    .setUuid("uuid_1")
     .setCreatedAt(123456789L)
     .build();
 
index a2dd17509b93edc028f1f6ee24e959db941a1220..3d2b80830f559f18f0ec4a0df46a3d70b75bb177 100644 (file)
@@ -58,6 +58,7 @@ public class FileMoveDetectionStepTest {
   private static final long SNAPSHOT_ID = 98765;
   private static final Snapshot SNAPSHOT = new Snapshot.Builder()
     .setId(SNAPSHOT_ID)
+    .setUuid("uuid_1")
     .setCreatedAt(86521)
     .build();
   private static final int ROOT_REF = 1;
@@ -400,11 +401,11 @@ public class FileMoveDetectionStepTest {
     ComponentDtoWithSnapshotId[] dtos = mockComponentsForSnapshot(FILE_1.getKey(), FILE_2.getKey(), file4.getKey(), file5.getKey());
     mockContentOfFileIdDb(FILE_1.getKey(), CONTENT1);
     mockContentOfFileIdDb(FILE_2.getKey(), LESS_CONTENT1);
-    mockContentOfFileIdDb(file4.getKey(), new String[]{"e","f","g","h","i"});
+    mockContentOfFileIdDb(file4.getKey(), new String[] {"e", "f", "g", "h", "i"});
     mockContentOfFileIdDb(file5.getKey(), CONTENT2);
     setFilesInReport(FILE_3, file4, file6);
     setFileContentInReport(FILE_3_REF, CONTENT1);
-    setFileContentInReport(file4.getReportAttributes().getRef(), new String[]{"a","b"});
+    setFileContentInReport(file4.getReportAttributes().getRef(), new String[] {"a", "b"});
     setFileContentInReport(file6.getReportAttributes().getRef(), LESS_CONTENT2);
 
     underTest.execute();
index 3c8993cf2f03617a485fb25e74de1f13d0ee18b0..85eb211292326e1211893920bd74673050c90966 100644 (file)
@@ -68,6 +68,7 @@ public class ScmInfoRepositoryImplTest {
 
   static Snapshot BASE_PROJECT_SNAPSHOT = new Snapshot.Builder()
     .setId(1)
+    .setUuid("uuid_1")
     .setCreatedAt(123456789L)
     .build();
 
index 0ba8a38278f0c6cc097bcb8a889c52f5c0dd70e5..51420bd87d387563a19e99abc4e0e6e2095ed46b 100644 (file)
@@ -31,16 +31,19 @@ public class SnapshotImplTest {
   public ExpectedException thrown = ExpectedException.none();
 
   static final long ID = 10;
+  static final String UUID = "uuid ";
   static final long CREATED_AT = 123456789L;
 
   @Test
   public void build_snapshot() throws Exception {
     Snapshot snapshot = new Snapshot.Builder()
       .setId(ID)
+      .setUuid(UUID)
       .setCreatedAt(CREATED_AT)
       .build();
 
     assertThat(snapshot.getId()).isEqualTo(ID);
+    assertThat(snapshot.getUuid()).isEqualTo(UUID);
     assertThat(snapshot.getCreatedAt()).isEqualTo(CREATED_AT);
   }
 
@@ -50,6 +53,18 @@ public class SnapshotImplTest {
     thrown.expectMessage("id cannot be null");
 
     new Snapshot.Builder()
+      .setUuid(UUID)
+      .setCreatedAt(CREATED_AT)
+      .build();
+  }
+
+  @Test
+  public void fail_with_NPE_when_building_snapshot_without_uuid() throws Exception {
+    thrown.expect(NullPointerException.class);
+    thrown.expectMessage("uuid cannot be null");
+
+    new Snapshot.Builder()
+      .setId(ID)
       .setCreatedAt(CREATED_AT)
       .build();
   }
@@ -61,6 +76,7 @@ public class SnapshotImplTest {
 
     new Snapshot.Builder()
       .setId(ID)
+      .setUuid(UUID)
       .build();
   }
 
@@ -68,33 +84,44 @@ public class SnapshotImplTest {
   public void test_toString() throws Exception {
     assertThat(new Snapshot.Builder()
       .setId(ID)
+      .setUuid(UUID)
       .setCreatedAt(CREATED_AT)
       .build().toString())
-      .isEqualTo("SnapshotImpl{id=10, createdAt=123456789}");
+        .isEqualTo("Snapshot{id=10, uuid='uuid ', createdAt=123456789}");
   }
 
   @Test
   public void test_equals_and_hascode() throws Exception {
     Snapshot snapshot = new Snapshot.Builder()
       .setId(ID)
+      .setUuid(UUID)
       .setCreatedAt(CREATED_AT)
       .build();
     Snapshot sameSnapshot = new Snapshot.Builder()
       .setId(ID)
+      .setUuid(UUID)
+      .setCreatedAt(CREATED_AT)
+      .build();
+    Snapshot sameSnapshotNotSameUuid = new Snapshot.Builder()
+      .setId(ID)
+      .setUuid("other uuid")
       .setCreatedAt(CREATED_AT)
       .build();
     Snapshot otherSnapshot = new Snapshot.Builder()
       .setId(11L)
+      .setUuid(UUID)
       .setCreatedAt(CREATED_AT)
       .build();
 
     assertThat(snapshot).isEqualTo(snapshot);
     assertThat(snapshot).isEqualTo(sameSnapshot);
+    assertThat(snapshot).isEqualTo(sameSnapshotNotSameUuid);
     assertThat(snapshot).isNotEqualTo(otherSnapshot);
     assertThat(snapshot).isNotEqualTo(null);
 
     assertThat(snapshot.hashCode()).isEqualTo(snapshot.hashCode());
     assertThat(snapshot.hashCode()).isEqualTo(sameSnapshot.hashCode());
+    assertThat(snapshot.hashCode()).isEqualTo(sameSnapshotNotSameUuid.hashCode());
     assertThat(snapshot.hashCode()).isNotEqualTo(otherSnapshot.hashCode());
   }
 }
index 1b84b4591a9a698e2219257e56ff812a5389858e..2ae008a2c4adf0a9b232ebee802a783f9ae0f7cb 100644 (file)
@@ -115,6 +115,7 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
 
     baseProjectSnapshot = new Snapshot.Builder()
       .setId(projectSnapshot.getId())
+      .setUuid(projectSnapshot.getUuid())
       .setCreatedAt(projectSnapshot.getCreatedAt())
       .build();
   }
@@ -136,8 +137,7 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
       .setStartLine(40)
       .setEndLine(55)
       .setIndexInFile(0)
-      .setProjectSnapshotId(otherProjectSnapshot.getId())
-      .setSnapshotId(otherFileSnapshot.getId())
+      .setAnalysisUuid(otherProjectSnapshot.getUuid())
       .setComponentUuid(otherFileSnapshot.getComponentUuid());
     dbClient.duplicationDao().insert(dbSession, duplicate);
     dbSession.commit();
@@ -203,8 +203,7 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
       .setStartLine(40)
       .setEndLine(55)
       .setIndexInFile(0)
-      .setProjectSnapshotId(otherProjectSnapshot.getId())
-      .setSnapshotId(otherFileSnapshot.getId())
+      .setAnalysisUuid(otherProjectSnapshot.getUuid())
       .setComponentUuid(otherFileSnapshot.getComponentUuid());
 
     DuplicationUnitDto duplicate2 = new DuplicationUnitDto()
@@ -212,8 +211,7 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
       .setStartLine(20)
       .setEndLine(35)
       .setIndexInFile(1)
-      .setProjectSnapshotId(otherProjectSnapshot.getId())
-      .setSnapshotId(otherFileSnapshot.getId())
+      .setAnalysisUuid(otherProjectSnapshot.getUuid())
       .setComponentUuid(otherFileSnapshot.getComponentUuid());
     dbClient.duplicationDao().insert(dbSession, duplicate1);
     dbClient.duplicationDao().insert(dbSession, duplicate2);
@@ -279,8 +277,7 @@ public class LoadCrossProjectDuplicationsRepositoryStepTest {
       .setStartLine(40)
       .setEndLine(55)
       .setIndexInFile(0)
-      .setProjectSnapshotId(otherProjectSnapshot.getId())
-      .setSnapshotId(otherFileSnapshot.getId())
+      .setAnalysisUuid(otherProjectSnapshot.getUuid())
       .setComponentUuid(otherFileSnapshot.getComponentUuid());
     dbClient.duplicationDao().insert(dbSession, duplicate);
     dbSession.commit();
index 6fcabab19e8a469e16ee499b1ef69976e3d251cf..455ba0fc6ebd4b9e0e8ac4f9a52aeb8714001eab 100644 (file)
@@ -30,10 +30,10 @@ import org.sonar.api.utils.System2;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbTester;
 import org.sonar.scanner.protocol.output.ScannerReport;
+import org.sonar.server.computation.analysis.AnalysisMetadataHolderRule;
 import org.sonar.server.computation.batch.BatchReportReaderRule;
 import org.sonar.server.computation.batch.TreeRootHolderRule;
 import org.sonar.server.computation.component.Component;
-import org.sonar.server.computation.component.DbIdsRepositoryImpl;
 import org.sonar.server.computation.component.ReportComponent;
 import org.sonar.server.computation.duplication.CrossProjectDuplicationStatusHolder;
 
@@ -44,42 +44,38 @@ import static org.mockito.Mockito.when;
 
 public class PersistCrossProjectDuplicationIndexStepTest {
 
-  static final int FILE_REF = 2;
-  static final Component FILE = ReportComponent.builder(Component.Type.FILE, FILE_REF).build();
-  static final long FILE_SNAPSHOT_ID = 11L;
+  private static final int FILE_REF = 2;
+  private static final Component FILE = ReportComponent.builder(Component.Type.FILE, FILE_REF).build();
 
-  static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1)
+  private static final Component PROJECT = ReportComponent.builder(Component.Type.PROJECT, 1)
     .addChildren(FILE)
     .build();
-  static final long PROJECT_SNAPSHOT_ID = 10L;
 
-  static final ScannerReport.CpdTextBlock CPD_TEXT_BLOCK = ScannerReport.CpdTextBlock.newBuilder()
+  private static final ScannerReport.CpdTextBlock CPD_TEXT_BLOCK = ScannerReport.CpdTextBlock.newBuilder()
     .setHash("a8998353e96320ec")
     .setStartLine(30)
     .setEndLine(45)
     .build();
+  private static final String ANALYSIS_UUID = "analysis uuid";
 
   @Rule
   public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
   @Rule
   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
-
   @Rule
   public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule().setRoot(PROJECT);
+  @Rule
+  public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule();
 
   CrossProjectDuplicationStatusHolder crossProjectDuplicationStatusHolder = mock(CrossProjectDuplicationStatusHolder.class);
 
-  DbIdsRepositoryImpl dbIdsRepository = new DbIdsRepositoryImpl();
-
   DbClient dbClient = dbTester.getDbClient();
 
-  ComputationStep underTest = new PersistCrossProjectDuplicationIndexStep(dbClient, dbIdsRepository, treeRootHolder, reportReader, crossProjectDuplicationStatusHolder);
+  ComputationStep underTest = new PersistCrossProjectDuplicationIndexStep(crossProjectDuplicationStatusHolder, dbClient, treeRootHolder, analysisMetadataHolder, reportReader);
 
   @Before
   public void setUp() throws Exception {
-    dbIdsRepository.setSnapshotId(PROJECT, PROJECT_SNAPSHOT_ID);
-    dbIdsRepository.setSnapshotId(FILE, FILE_SNAPSHOT_ID);
+    analysisMetadataHolder.setUuid(ANALYSIS_UUID);
   }
 
   @Test
@@ -89,15 +85,13 @@ public class PersistCrossProjectDuplicationIndexStepTest {
 
     underTest.execute();
 
-    Map<String, Object> dto = dbTester.selectFirst("select hash as \"hash\", start_line as \"startLine\", end_line as \"endLine\", index_in_file as \"indexInFile\", " +
-      "snapshot_id as \"snapshotId\", component_uuid as \"componentUuid\", project_snapshot_id as \"projectSnapshotId\" from duplications_index");
-    assertThat(dto.get("hash")).isEqualTo(CPD_TEXT_BLOCK.getHash());
-    assertThat(dto.get("startLine")).isEqualTo(30L);
-    assertThat(dto.get("endLine")).isEqualTo(45L);
-    assertThat(dto.get("indexInFile")).isEqualTo(0L);
-    assertThat(dto.get("snapshotId")).isEqualTo(FILE_SNAPSHOT_ID);
-    assertThat(dto.get("componentUuid")).isEqualTo(FILE.getUuid());
-    assertThat(dto.get("projectSnapshotId")).isEqualTo(PROJECT_SNAPSHOT_ID);
+    Map<String, Object> dto = dbTester.selectFirst("select HASH, START_LINE, END_LINE, INDEX_IN_FILE, COMPONENT_UUID, ANALYSIS_UUID from duplications_index");
+    assertThat(dto.get("HASH")).isEqualTo(CPD_TEXT_BLOCK.getHash());
+    assertThat(dto.get("START_LINE")).isEqualTo(30L);
+    assertThat(dto.get("END_LINE")).isEqualTo(45L);
+    assertThat(dto.get("INDEX_IN_FILE")).isEqualTo(0L);
+    assertThat(dto.get("COMPONENT_UUID")).isEqualTo(FILE.getUuid());
+    assertThat(dto.get("ANALYSIS_UUID")).isEqualTo(ANALYSIS_UUID);
   }
 
   @Test
@@ -113,15 +107,13 @@ public class PersistCrossProjectDuplicationIndexStepTest {
 
     underTest.execute();
 
-    List<Map<String, Object>> dtos = dbTester.select("select hash as \"hash\", start_line as \"startLine\", end_line as \"endLine\", index_in_file as \"indexInFile\", " +
-      "snapshot_id as \"snapshotId\", component_uuid as \"componentUuid\", project_snapshot_id as \"projectSnapshotId\" from duplications_index");
-    assertThat(dtos).extracting("hash").containsOnly(CPD_TEXT_BLOCK.getHash(), "b1234353e96320ff");
-    assertThat(dtos).extracting("startLine").containsOnly(30L, 20L);
-    assertThat(dtos).extracting("endLine").containsOnly(45L, 15L);
-    assertThat(dtos).extracting("indexInFile").containsOnly(0L, 1L);
-    assertThat(dtos).extracting("snapshotId").containsOnly(FILE_SNAPSHOT_ID);
-    assertThat(dtos).extracting("componentUuid").containsOnly(FILE.getUuid());
-    assertThat(dtos).extracting("projectSnapshotId").containsOnly(PROJECT_SNAPSHOT_ID);
+    List<Map<String, Object>> dtos = dbTester.select("select HASH, START_LINE, END_LINE, INDEX_IN_FILE, COMPONENT_UUID, ANALYSIS_UUID from duplications_index");
+    assertThat(dtos).extracting("HASH").containsOnly(CPD_TEXT_BLOCK.getHash(), "b1234353e96320ff");
+    assertThat(dtos).extracting("START_LINE").containsOnly(30L, 20L);
+    assertThat(dtos).extracting("END_LINE").containsOnly(45L, 15L);
+    assertThat(dtos).extracting("INDEX_IN_FILE").containsOnly(0L, 1L);
+    assertThat(dtos).extracting("COMPONENT_UUID").containsOnly(FILE.getUuid());
+    assertThat(dtos).extracting("ANALYSIS_UUID").containsOnly(ANALYSIS_UUID);
   }
 
   @Test
index a9c5935ace99a556f6a55725303333cb11fe1710..b4b5a11ed228e1563e59b830e35c6a5b9cd88af0 100644 (file)
@@ -30,12 +30,12 @@ import static org.sonar.db.DatabaseUtils.executeLargeInputs;
 public class DuplicationDao implements Dao {
 
   /**
-   * @param projectSnapshotId snapshot id of the project from the previous analysis (islast=true)
+   * @param analysisUuid snapshot id of the project from the previous analysis (islast=true)
    */
-  public List<DuplicationUnitDto> selectCandidates(DbSession session, @Nullable Long projectSnapshotId, String language, Collection<String> hashes) {
+  public List<DuplicationUnitDto> selectCandidates(DbSession session, @Nullable String analysisUuid, String language, Collection<String> hashes) {
     return executeLargeInputs(
       hashes,
-      partition -> session.getMapper(DuplicationMapper.class).selectCandidates(projectSnapshotId, language, partition));
+      partition -> session.getMapper(DuplicationMapper.class).selectCandidates(analysisUuid, language, partition));
   }
 
   /**
index cef8e1db6e8e28c7480400d882439c44aa3f05dd..2a1a862f7811e2c4d72fd5660f0c231e83b7b7d5 100644 (file)
@@ -27,7 +27,7 @@ import org.apache.ibatis.annotations.Param;
 public interface DuplicationMapper {
 
   List<DuplicationUnitDto> selectCandidates(
-    @Nullable @Param("projectSnapshotId") Long projectSnapshotId,
+    @Nullable @Param("analysisUuid") String analysisUuid,
     @Param("language") String language,
     @Param("hashes") Collection<String> hashes);
 
index d915fb4466a134ef70395324938aed6f2452934c..14bff7a2239d1510eb91580ae3486abbe982dfd0 100644 (file)
@@ -22,9 +22,8 @@ package org.sonar.db.duplication;
 public final class DuplicationUnitDto {
 
   private long id;
-  private long snapshotId;
+  private String analysisUuid;
   private String componentUuid;
-  private long projectSnapshotId;
 
   private String hash;
   private int indexInFile;
@@ -43,12 +42,12 @@ public final class DuplicationUnitDto {
     return this;
   }
 
-  public long getSnapshotId() {
-    return snapshotId;
+  public String getAnalysisUuid() {
+    return analysisUuid;
   }
 
-  public DuplicationUnitDto setSnapshotId(long snapshotId) {
-    this.snapshotId = snapshotId;
+  public DuplicationUnitDto setAnalysisUuid(String analysisUuid) {
+    this.analysisUuid = analysisUuid;
     return this;
   }
 
@@ -61,15 +60,6 @@ public final class DuplicationUnitDto {
     return this;
   }
 
-  public long getProjectSnapshotId() {
-    return projectSnapshotId;
-  }
-
-  public DuplicationUnitDto setProjectSnapshotId(long projectSnapshotId) {
-    this.projectSnapshotId = projectSnapshotId;
-    return this;
-  }
-
   public String getHash() {
     return hash;
   }
index 41695fe834b1b9cac737817bfac857eaeec08e12..2e81cecfe9db3c4ce2f829a5c0fb0a470c1270eb 100644 (file)
  */
 package org.sonar.db.purge;
 
-import com.google.common.base.Function;
 import com.google.common.collect.Lists;
+import java.util.ArrayList;
 import java.util.List;
-import javax.annotation.Nonnull;
+import java.util.stream.Collectors;
 
-public class IdUuidPairs {
+public final class IdUuidPairs {
   private IdUuidPairs() {
+    // prevents instantiation
   }
 
   public static List<Long> ids(List<IdUuidPair> pairs) {
-    return Lists.transform(pairs, new IdUuidPairToIdFunction());
+    return pairs.stream().map(IdUuidPair::getId).collect(Collectors.toCollection(() -> new ArrayList<>(pairs.size())));
   }
 
-  public static List<String> uuids(List<IdUuidPair> pairs) {
-    return Lists.transform(pairs, new IdUuidPairToUuidFunction());
+  public static List<Long> ids(Iterable<IdUuidPair> pairs) {
+    if (pairs instanceof List) {
+      return ids((List<IdUuidPair>) pairs);
+    }
+    return ids(Lists.newArrayList(pairs));
   }
 
-  private static class IdUuidPairToIdFunction implements Function<IdUuidPair, Long> {
-    @Override
-    public Long apply(@Nonnull IdUuidPair pair) {
-      return pair.getId();
-    }
+  public static List<String> uuids(List<IdUuidPair> pairs) {
+    return pairs.stream().map(IdUuidPair::getUuid).collect(Collectors.toCollection(() -> new ArrayList<>(pairs.size())));
   }
 
-  private static class IdUuidPairToUuidFunction implements Function<IdUuidPair, String> {
-    @Override
-    public String apply(@Nonnull IdUuidPair pair) {
-      return pair.getUuid();
+  public static List<String> uuids(Iterable<IdUuidPair> pairs) {
+    if (pairs instanceof List) {
+      return uuids((List<IdUuidPair>) pairs);
     }
+    return uuids(Lists.newArrayList(pairs));
   }
+
 }
index 8dd3c515c927d683ef5e839b6c8e481be3df163b..91a0300a5370d5cb183bbb13eede0d52adb6abac 100644 (file)
 package org.sonar.db.purge;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.stream.Collectors;
 import org.apache.ibatis.session.SqlSession;
 
 import static com.google.common.collect.FluentIterable.from;
@@ -51,7 +51,7 @@ class PurgeCommands {
   }
 
   List<Long> selectSnapshotIds(PurgeSnapshotQuery query) {
-    return purgeMapper.selectSnapshotIds(query);
+    return purgeMapper.selectSnapshotIdsAndUuids(query).stream().map(IdUuidPair::getId).collect(Collectors.toList());
   }
 
   void deleteComponents(List<IdUuidPair> componentIdUuids) {
@@ -62,7 +62,7 @@ class PurgeCommands {
     // Batch requests can only relate to the same PreparedStatement.
 
     for (List<String> componentUuidPartition : componentUuidsPartitions) {
-      deleteSnapshots(purgeMapper.selectSnapshotIdsByResource(componentUuidPartition));
+      deleteSnapshots(purgeMapper.selectSnapshotIdAndUuidsByResource(componentUuidPartition));
     }
 
     // possible missing optimization: filter requests according to resource scope
@@ -146,18 +146,18 @@ class PurgeCommands {
   }
 
   void deleteSnapshots(PurgeSnapshotQuery... queries) {
-    List<Long> snapshotIds = from(asList(queries))
-      .transformAndConcat(purgeMapper::selectSnapshotIds)
+    List<IdUuidPair> snapshotIds = from(asList(queries))
+      .transformAndConcat(purgeMapper::selectSnapshotIdsAndUuids)
       .toList();
     deleteSnapshots(snapshotIds);
   }
 
   @VisibleForTesting
-  protected void deleteSnapshots(final List<Long> snapshotIds) {
+  protected void deleteSnapshots(List<IdUuidPair> snapshotIds) {
+    List<List<Long>> snapshotIdsPartition = Lists.partition(IdUuidPairs.ids(snapshotIds), MAX_SNAPSHOTS_PER_QUERY);
+    List<List<String>> snapshotUuidsPartition = Lists.partition(IdUuidPairs.uuids(snapshotIds), MAX_SNAPSHOTS_PER_QUERY);
 
-    List<List<Long>> snapshotIdsPartition = Lists.partition(snapshotIds, MAX_SNAPSHOTS_PER_QUERY);
-
-    deleteSnapshotDuplications(snapshotIdsPartition);
+    deleteSnapshotDuplications(snapshotUuidsPartition);
 
     profiler.start("deleteSnapshotEvents (events)");
     for (List<Long> partSnapshotIds : snapshotIdsPartition) {
@@ -183,16 +183,18 @@ class PurgeCommands {
 
   void purgeSnapshots(PurgeSnapshotQuery... queries) {
     // use LinkedHashSet to keep order by remove duplicated ids
-    LinkedHashSet<Long> snapshotIds = Sets.newLinkedHashSet(from(asList(queries)).transformAndConcat(purgeMapper::selectSnapshotIds));
+    LinkedHashSet<IdUuidPair> snapshotIds = Sets.newLinkedHashSet(from(asList(queries))
+        .transformAndConcat(purgeMapper::selectSnapshotIdsAndUuids));
     purgeSnapshots(snapshotIds);
   }
 
   @VisibleForTesting
-  protected void purgeSnapshots(Iterable<Long> snapshotIds) {
+  protected void purgeSnapshots(Iterable<IdUuidPair> snapshotIdUuidPairs) {
     // note that events are not deleted
-    Iterable<List<Long>> snapshotIdsPartition = Iterables.partition(snapshotIds, MAX_SNAPSHOTS_PER_QUERY);
+    List<List<Long>> snapshotIdsPartition = Lists.partition(IdUuidPairs.ids(snapshotIdUuidPairs), MAX_SNAPSHOTS_PER_QUERY);
+    List<List<String>> snapshotUuidsPartition = Lists.partition(IdUuidPairs.uuids(snapshotIdUuidPairs), MAX_SNAPSHOTS_PER_QUERY);
 
-    deleteSnapshotDuplications(snapshotIdsPartition);
+    deleteSnapshotDuplications(snapshotUuidsPartition);
 
     profiler.start("deleteSnapshotWastedMeasures (project_measures)");
     List<Long> metricIdsWithoutHistoricalData = purgeMapper.selectMetricIdsWithoutHistoricalData();
@@ -203,17 +205,15 @@ class PurgeCommands {
     profiler.stop();
 
     profiler.start("updatePurgeStatusToOne (snapshots)");
-    for (Long snapshotId : snapshotIds) {
-      purgeMapper.updatePurgeStatusToOne(snapshotId);
-    }
+    snapshotIdUuidPairs.iterator().forEachRemaining(idUuidPair -> purgeMapper.updatePurgeStatusToOne(idUuidPair.getId()));
     session.commit();
     profiler.stop();
   }
 
-  private void deleteSnapshotDuplications(Iterable<List<Long>> snapshotIdsPartition) {
+  private void deleteSnapshotDuplications(Iterable<List<String>> snapshotUuidsPartition) {
     profiler.start("deleteSnapshotDuplications (duplications_index)");
-    for (List<Long> partSnapshotIds : snapshotIdsPartition) {
-      purgeMapper.deleteSnapshotDuplications(partSnapshotIds);
+    for (List<String> partSnapshotUuids : snapshotUuidsPartition) {
+      purgeMapper.deleteSnapshotDuplications(partSnapshotUuids);
     }
     session.commit();
     profiler.stop();
index d0f63fe332b9fef5d0e8fa23f15fd13d431c12d7..7c237d06ba8ee2d765d14a8ec30f1b2cf4ae36be 100644 (file)
@@ -25,9 +25,9 @@ import org.apache.ibatis.annotations.Param;
 
 public interface PurgeMapper {
 
-  List<Long> selectSnapshotIds(PurgeSnapshotQuery query);
+  List<IdUuidPair> selectSnapshotIdsAndUuids(PurgeSnapshotQuery query);
 
-  List<Long> selectSnapshotIdsByResource(@Param("componentUuids") List<String> componentUuids);
+  List<IdUuidPair> selectSnapshotIdAndUuidsByResource(@Param("componentUuids") List<String> componentUuids);
 
   /**
    * Returns the list of components of a project from a project_uuid. The project itself is also returned.
@@ -36,7 +36,7 @@ public interface PurgeMapper {
 
   void deleteSnapshot(@Param("snapshotIds") List<Long> snapshotIds);
 
-  void deleteSnapshotDuplications(@Param("snapshotIds") List<Long> snapshotIds);
+  void deleteSnapshotDuplications(@Param("analysisUuids") List<String> analysisUuids);
 
   void deleteSnapshotEvents(@Param("snapshotIds") List<Long> snapshotIds);
 
index ec02d2e7ef8b0c376e587b4dc7da680af81eef24..1597543164e727e9b24b03eaf8bc81e4d25c00f8 100644 (file)
@@ -6,30 +6,35 @@
   <select id="selectCandidates" parameterType="map" resultType="DuplicationUnit">
     SELECT DISTINCT
     duplication_block.id as id,
-    duplication_block.snapshot_id as snapshotId,
+    duplication_block.analysis_uuid as analysisUuid,
     duplication_block.component_uuid as componentUuid,
-    duplication_block.project_snapshot_id as projectSnapshotId,
     duplication_block.hash as hash,
     duplication_block.index_in_file as indexInFile,
     duplication_block.start_line as startLine,
     duplication_block.end_line as endLine,
     file_component.kee as componentKey
     FROM duplications_index duplication_block
-    INNER JOIN snapshots snapshot ON duplication_block.snapshot_id=snapshot.id AND snapshot.islast=${_true}
+    INNER JOIN snapshots snapshot ON duplication_block.analysis_uuid=snapshot.uuid AND snapshot.islast=${_true}
     INNER JOIN projects file_component ON file_component.uuid=duplication_block.component_uuid AND file_component.language=#{language}
     AND file_component.enabled=${_true}
     <where>
       AND duplication_block.hash in
       <foreach collection="hashes" open="(" close=")" item="hash" separator=",">#{hash}</foreach>
-      <if test="projectSnapshotId != null">
-        AND duplication_block.project_snapshot_id &lt;&gt; #{projectSnapshotId}
+      <if test="analysisUuid != null">
+        AND duplication_block.analysis_uuid &lt;&gt; #{analysisUuid}
       </if>
     </where>
   </select>
 
   <insert id="batchInsert" parameterType="DuplicationUnit" useGeneratedKeys="false">
-    INSERT INTO duplications_index (snapshot_id, component_uuid, project_snapshot_id, hash, index_in_file, start_line, end_line)
-    VALUES (#{snapshotId}, #{componentUuid}, #{projectSnapshotId}, #{hash}, #{indexInFile}, #{startLine}, #{endLine})
+    INSERT INTO duplications_index (
+    analysis_uuid, component_uuid, hash,
+    index_in_file, start_line, end_line
+    )
+    VALUES (
+    #{analysisUuid,jdbcType=VARCHAR}, #{componentUuid,jdbcType=VARCHAR}, #{hash,jdbcType=VARCHAR},
+    #{indexInFile,jdbcType=INTEGER}, #{startLine,jdbcType=INTEGER}, #{endLine,jdbcType=INTEGER}
+    )
   </insert>
 
 </mapper>
index 8c4cce48c0dafaa99cf1947c75bef074383ad4ed..8ed0439ca7c890a791e86f58a72aa12113d9c06a 100644 (file)
@@ -3,8 +3,8 @@
 
 <mapper namespace="org.sonar.db.purge.PurgeMapper">
 
-  <select id="selectSnapshotIds" parameterType="map" resultType="long">
-    select s.id from snapshots s
+  <select id="selectSnapshotIdsAndUuids" parameterType="map" resultType="IdUuidPair">
+    select s.id as id, s.uuid as uuid from snapshots s
     <where>
       <if test="islast != null">
         and s.islast=#{islast}
@@ -48,8 +48,8 @@
     </where>
   </select>
 
-  <select id="selectSnapshotIdsByResource" parameterType="map" resultType="long">
-    select s.id from snapshots s
+  <select id="selectSnapshotIdAndUuidsByResource" parameterType="map" resultType="IdUuidPair">
+    select s.id as id, s.uuid as uuid from snapshots s
     <where>
       s.component_uuid in
       <foreach collection="componentUuids" open="(" close=")" item="componentUuid" separator=",">
@@ -94,9 +94,9 @@
   </delete>
 
   <delete id="deleteSnapshotDuplications" parameterType="map">
-    delete from duplications_index where snapshot_id in
-    <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
-      #{snapshotId}
+    delete from duplications_index where analysis_uuid in
+    <foreach collection="analysisUuids" open="(" close=")" item="analysisUuid" separator=",">
+      #{analysisUuid}
     </foreach>
   </delete>
 
index 4374de333075377ca8993318dc414bf8de106e52..20396bf9020c85eb100813b602dce617fcb86447 100644 (file)
  */
 package org.sonar.db.duplication;
 
-import java.util.List;
 import org.junit.Rule;
 import org.junit.Test;
 import org.sonar.api.utils.System2;
 import org.sonar.db.DbSession;
 import org.sonar.db.DbTester;
 
+import java.util.List;
+
 import static java.util.Collections.singletonList;
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -44,7 +45,7 @@ public class DuplicationDaoTest {
     db.prepareDbUnit(getClass(), "select_candidates.xml");
     dbSession.commit();
 
-    List<DuplicationUnitDto> blocks = dao.selectCandidates(dbSession, 7L, "java", singletonList("aa"));
+    List<DuplicationUnitDto> blocks = dao.selectCandidates(dbSession, "u7", "java", singletonList("aa"));
     assertThat(blocks).hasSize(1);
 
     DuplicationUnitDto block = blocks.get(0);
@@ -66,8 +67,7 @@ public class DuplicationDaoTest {
     dbSession.commit();
 
     dao.insert(dbSession, new DuplicationUnitDto()
-      .setProjectSnapshotId(1)
-      .setSnapshotId(2)
+      .setAnalysisUuid("u1")
       .setComponentUuid("uuid_1")
       .setHash("bb")
       .setIndexInFile(0)
index 1c30f1c9583245759889b6fda58a59ffde88f97a..00c14336d48c5b19c42f1149f343f79130140fea 100644 (file)
@@ -53,7 +53,7 @@ public class PurgeCommandsTest {
    */
   @Test
   public void should_not_fail_when_deleting_huge_number_of_snapshots() {
-    new PurgeCommands(dbTester.getSession(), profiler).deleteSnapshots(getHugeNumberOfIds());
+    new PurgeCommands(dbTester.getSession(), profiler).deleteSnapshots(getHugeNumberOfIdUuidPairs());
     // The goal of this test is only to check that the query do no fail, not to check result
   }
 
@@ -83,7 +83,7 @@ public class PurgeCommandsTest {
    */
   @Test
   public void should_not_fail_when_purging_huge_number_of_snapshots() {
-    new PurgeCommands(dbTester.getSession(), profiler).purgeSnapshots(getHugeNumberOfIds());
+    new PurgeCommands(dbTester.getSession(), profiler).purgeSnapshots(getHugeNumberOfIdUuidPairs());
     // The goal of this test is only to check that the query do no fail, not to check result
   }
 
@@ -118,10 +118,10 @@ public class PurgeCommandsTest {
     return hugeNbOfSnapshotIds;
   }
 
-  private List<Long> getHugeNumberOfIds() {
-    List<Long> hugeNbOfSnapshotIds = newArrayList();
+  private List<IdUuidPair> getHugeNumberOfIdUuidPairs() {
+    List<IdUuidPair> hugeNbOfSnapshotIds = newArrayList();
     for (long i = 0; i < 4500; i++) {
-      hugeNbOfSnapshotIds.add(i);
+      hugeNbOfSnapshotIds.add(new IdUuidPair(i, "uuid_" + i));
     }
     return hugeNbOfSnapshotIds;
   }
index 072ce7fd58672308fc317055987eb1c6e5c639ac..085383822a89a10f799e6bc37d0d88ad2f6a2229 100644 (file)
@@ -15,8 +15,7 @@
   <projects id="1" uuid="1" kee="foo" enabled="1" scope="FIL" qualifier="CLA"/>
 
   <duplications_index id="1"
-                      project_snapshot_id="1"
-                      snapshot_id="2"
+                      analysis_uuid="u1"
                       component_uuid="uuid_1"
                       hash="bb"
                       index_in_file="0"
index ec60a919101282eca91c804f8c49fefffc157992..1bc298a72d0b1169fd172ff82b10cb1497473e2d 100644 (file)
 
   <snapshots id="1"
              uuid="u1"
-             component_uuid="uuid_1" status="P" islast="[false]" purge_status="[null]" root_component_uuid="uuid_1"/>
+             component_uuid="uuid_root_1"
+             status="P"
+             islast="[false]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_1"/>
   <snapshots id="2"
              uuid="u2"
-             component_uuid="uuid_1" status="P" islast="[false]" purge_status="[null]" root_component_uuid="uuid_1"/>
-  <projects id="1" uuid="uuid_1" root_uuid="uuid_root" kee="bar-old" enabled="[true]" scope="FIL" qualifier="CLA" language="java"/>
+             component_uuid="uuid_1"
+             status="P"
+             islast="[false]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_1"/>
+  <projects id="1"
+            uuid="uuid_1"
+            root_uuid="uuid_root_1"
+            kee="bar-old"
+            enabled="[true]"
+            scope="FIL"
+            qualifier="CLA"
+            language="java"/>
 
   <snapshots id="3"
              uuid="u3"
-             component_uuid="uuid_2" status="P" islast="[true]" purge_status="[null]" root_component_uuid="uuid_1"/>
+             component_uuid="uuid_root_2"
+             status="P"
+             islast="[true]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_2"/>
   <snapshots id="4"
              uuid="u4"
-             component_uuid="uuid_2" status="P" islast="[true]" purge_status="[null]" root_component_uuid="uuid_1"/>
-  <projects id="2" uuid="uuid_2" root_uuid="uuid_root" kee="bar-last" enabled="[true]" scope="FIL" qualifier="CLA" language="java"/>
+             component_uuid="uuid_2"
+             status="P"
+             islast="[true]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_2"/>
+  <projects id="2"
+            uuid="uuid_2"
+            root_uuid="uuid_root_2"
+            kee="bar-last"
+            enabled="[true]"
+            scope="FIL"
+            qualifier="CLA"
+            language="java"/>
 
   <snapshots id="5"
              uuid="u5"
-             component_uuid="uuid_3" status="P" islast="[false]" purge_status="[null]" root_component_uuid="uuid_1"/>
+             component_uuid="uuid_root_3"
+             status="P"
+             islast="[false]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_3"/>
   <snapshots id="6"
              uuid="u6"
-             component_uuid="uuid_3" status="P" islast="[false]" purge_status="[null]" root_component_uuid="uuid_1"/>
-  <projects id="3" uuid="uuid_3" root_uuid="uuid_root" kee="foo-old" enabled="[true]" scope="FIL" qualifier="CLA" language="java"/>
+             component_uuid="uuid_3"
+             status="P"
+             islast="[false]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_3"/>
+  <projects id="3"
+            uuid="uuid_3"
+            root_uuid="uuid_root_3"
+            kee="foo-old"
+            enabled="[true]"
+            scope="FIL"
+            qualifier="CLA"
+            language="java"/>
 
   <snapshots id="7"
              uuid="u7"
-             component_uuid="uuid_4" status="P" islast="[true]" purge_status="[null]" root_component_uuid="uuid_1"/>
+             component_uuid="uuid_root_4"
+             status="P"
+             islast="[true]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_4"/>
   <snapshots id="8"
              uuid="u8"
-             component_uuid="uuid_4" status="P" islast="[true]" purge_status="[null]" root_component_uuid="uuid_1"/>
-  <projects id="4" uuid="uuid_4" root_uuid="uuid_root" kee="foo-last" enabled="[true]" scope="FIL" qualifier="CLA" language="java"/>
+             component_uuid="uuid_4"
+             status="P"
+             islast="[true]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_4"/>
+  <projects id="4"
+            uuid="uuid_4"
+            root_uuid="uuid_root_4"
+            kee="foo-last"
+            enabled="[true]"
+            scope="FIL"
+            qualifier="CLA"
+            language="java"/>
 
   <snapshots id="9"
              uuid="u9"
-             component_uuid="uuid_5" status="U" islast="[false]" purge_status="[null]" root_component_uuid="uuid_1"/>
+             component_uuid="uuid_root_5"
+             status="U"
+             islast="[false]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_5"/>
   <snapshots id="10"
              uuid="u10"
-             component_uuid="uuid_5" status="U" islast="[false]" purge_status="[null]" root_component_uuid="uuid_1"/>
-  <projects id="5" uuid="uuid_5" root_uuid="uuid_root" kee="foo" enabled="[true]" scope="FIL" qualifier="CLA" language="java"/>
+             component_uuid="uuid_5"
+             status="U"
+             islast="[false]"
+             purge_status="[null]"
+             root_component_uuid="uuid_root_5"/>
+  <projects id="5"
+            uuid="uuid_5"
+            root_uuid="uuid_root_5"
+            kee="foo"
+            enabled="[true]"
+            scope="FIL"
+            qualifier="CLA"
+            language="java"/>
 
   <snapshots id="11"
              uuid="u11"
-             component_uuid="uuid_6" purge_status="[null]" status="P" islast="1" root_component_uuid="uuid_1"/>
-  <projects id="6" uuid="uuid_6" root_uuid="uuid_root" kee="baz" enabled="[true]" scope="FIL" qualifier="CLA" language="grvy"/>
+             component_uuid="uuid_6"
+             purge_status="[null]"
+             status="P"
+             islast="[true]"
+             root_component_uuid="uuid_root_1"/>
+  <projects id="6"
+            uuid="uuid_6"
+            root_uuid="uuid_root_1"
+            kee="baz"
+            enabled="[true]"
+            scope="FIL"
+            qualifier="CLA"
+            language="grvy"/>
 
   <!-- Old snapshot of another project -->
   <!-- bar-old -->
   <duplications_index id="1"
-                      project_snapshot_id="1"
-                      snapshot_id="2"
+                      analysis_uuid="u1"
                       component_uuid="uuid_1"
                       hash="bb"
                       index_in_file="0"
   <!-- Last snapshot of another project -->
   <!-- bar-last -->
   <duplications_index id="2"
-                      project_snapshot_id="3"
-                      snapshot_id="4"
+                      analysis_uuid="u3"
                       component_uuid="uuid_2"
                       hash="aa"
                       index_in_file="0"
   <!-- Old snapshot of current project -->
   <!-- foo-old -->
   <duplications_index id="3"
-                      project_snapshot_id="5"
-                      snapshot_id="6"
+                      analysis_uuid="u5"
                       component_uuid="uuid_3"
                       hash="bb"
                       index_in_file="0"
   <!-- Last snapshot of current project -->
   <!-- foo-last -->
   <duplications_index id="4"
-                      project_snapshot_id="7"
-                      snapshot_id="8"
+                      analysis_uuid="u7"
                       component_uuid="uuid_4"
                       hash="aa"
                       index_in_file="0"
   <!-- New snapshot of current project -->
   <!-- foo -->
   <duplications_index id="5"
-                      project_snapshot_id="9"
-                      snapshot_id="10"
+                      analysis_uuid="u9"
                       component_uuid="uuid_5"
                       hash="aa"
                       index_in_file="0"
   <!-- Note that there is two blocks with same hash for current analysis to verify that we use "SELECT DISTINCT", -->
   <!-- without "DISTINCT" we will select block from "bar-last" two times. -->
   <duplications_index id="6"
-                      project_snapshot_id="9"
-                      snapshot_id="10"
+                      analysis_uuid="u9"
                       component_uuid="uuid_5"
                       hash="aa"
                       index_in_file="1"
   <!-- Last snapshot of project with another language -->
   <!-- baz -->
   <duplications_index id="7"
-                      project_snapshot_id="1"
-                      snapshot_id="11"
+                      analysis_uuid="u1"
                       component_uuid="uuid_6"
                       hash="aa"
                       index_in_file="0"
index 1c9ba52e8f7fbe3eb5915680c5a83df90e2c31d9..c1ed4d97196a2c39c08594e26042f70b403e01cd 100644 (file)
@@ -3,32 +3,64 @@
   <!-- snapshot to keep -->
   <snapshots id="1"
              uuid="u1"
-             parent_snapshot_id="[null]" component_uuid="uuid_1" root_component_uuid="uuid_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]"
+             parent_snapshot_id="[null]"
+             component_uuid="uuid_1"
+             root_component_uuid="uuid_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="1228222680000"
+             scope="PRJ"
+             qualifier="TRK"
+             created_at="1228222680000"
              build_date="1228222680000"
-             version="[null]" path="[null]"/>
+             version="[null]"
+             path="[null]"/>
 
-  <project_measures ID="1" variation_value_1="[null]" variation_value_2="[null]"
-                    variation_value_3="[null]" variation_value_4="[null]"
+  <project_measures ID="1"
+                    variation_value_1="[null]"
+                    variation_value_2="[null]"
+                    variation_value_3="[null]"
+                    variation_value_4="[null]"
                     variation_value_5="[null]"
-                    alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1"
+                    alert_text="[null]"
+                    VALUE="10.0"
+                    METRIC_ID="1"
+                    SNAPSHOT_ID="1"
                     person_id="[null]"
                     text_value="[null]"
                     component_uuid="1"
-                    alert_status="[null]" description="[null]" measure_data="[null]"/>
-  <events id="1" name="Version 1.0" component_uuid="1" snapshot_id="1" category="VERSION" description="[null]"
-          event_date="1228222680000" created_at="1228222680000" event_data="[null]"/>
+                    alert_status="[null]"
+                    description="[null]"
+                    measure_data="[null]"/>
+  <events id="1"
+          name="Version 1.0"
+          component_uuid="1"
+          snapshot_id="1"
+          category="VERSION"
+          description="[null]"
+          event_date="1228222680000"
+          created_at="1228222680000"
+          event_data="[null]"/>
   <duplications_index id="1"
-                      project_snapshot_id="1"
+                      analysis_uuid="u1"
                       component_uuid="uuid_1"
-                      snapshot_id="1"
                       hash="bb"
                       index_in_file="0"
                       start_line="0"
index 9263dc9015e5a77c0178e4b9c81a9c0e4eba25b8..a388208c88427ea858cdca897b3345f6f0cbc335 100644 (file)
@@ -3,31 +3,63 @@
   <!-- snapshot to keep -->
   <snapshots id="1"
              uuid="u1"
-             parent_snapshot_id="[null]" component_uuid="uuid_1" root_component_uuid="uuid_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]"
+             parent_snapshot_id="[null]"
+             component_uuid="uuid_1"
+             root_component_uuid="uuid_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="1228222680000"
+             scope="PRJ"
+             qualifier="TRK"
+             created_at="1228222680000"
              build_date="1228222680000"
-             version="[null]" path="[null]"/>
+             version="[null]"
+             path="[null]"/>
 
-  <project_measures ID="1" variation_value_1="[null]" variation_value_2="[null]"
-                    variation_value_3="[null]" variation_value_4="[null]"
+  <project_measures ID="1"
+                    variation_value_1="[null]"
+                    variation_value_2="[null]"
+                    variation_value_3="[null]"
+                    variation_value_4="[null]"
                     variation_value_5="[null]"
-                    alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="1"
+                    alert_text="[null]"
+                    VALUE="10.0"
+                    METRIC_ID="1"
+                    SNAPSHOT_ID="1"
                     person_id="[null]"
                     text_value="[null]"
                     component_uuid="1"
-                    alert_status="[null]" description="[null]" measure_data="[null]"/>
-  <events id="1" name="Version 1.0" component_uuid="1" snapshot_id="1" category="VERSION" description="[null]"
-          event_date="1228222680000" created_at="1228222680000" event_data="[null]"/>
+                    alert_status="[null]"
+                    description="[null]"
+                    measure_data="[null]"/>
+  <events id="1"
+          name="Version 1.0"
+          component_uuid="1"
+          snapshot_id="1"
+          category="VERSION"
+          description="[null]"
+          event_date="1228222680000"
+          created_at="1228222680000"
+          event_data="[null]"/>
   <duplications_index id="1"
-                      project_snapshot_id="1"
-                      snapshot_id="1"
+                      analysis_uuid="u1"
                       component_uuid="uuid_1"
                       hash="bb"
                       index_in_file="0"
   <!-- snapshot to remove, id 5 on resource 5-->
   <snapshots id="5"
              uuid="u5"
-             component_uuid="uuid_5" parent_snapshot_id="[null]" root_component_uuid="uuid_5" 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"
+             component_uuid="uuid_5"
+             parent_snapshot_id="[null]"
+             root_component_uuid="uuid_5"
+             root_snapshot_id="[null]"
+             status="P"
+             islast="[true]"
+             purge_status="[null]"
+             period1_mode="[null]"
+             period1_param="[null]"
+             period1_date="[null]"
+             period2_mode="[null]"
+             period2_param="[null]"
+             period2_date="[null]"
+             period3_mode="[null]"
+             period3_param="[null]"
+             period3_date="[null]"
+             period4_mode="[null]"
+             period4_param="[null]"
+             period4_date="[null]"
+             period5_mode="[null]"
+             period5_param="[null]"
+             period5_date="[null]"
+             depth="[null]"
+             scope="PRJ"
+             qualifier="TRK"
+             created_at="1228222680000"
              build_date="1228222680000"
-             version="[null]" path="[null]"/>
+             version="[null]"
+             path="[null]"/>
 
-  <project_measures ID="2" variation_value_1="[null]" variation_value_2="[null]"
-                    variation_value_3="[null]" variation_value_4="[null]"
+  <project_measures ID="2"
+                    variation_value_1="[null]"
+                    variation_value_2="[null]"
+                    variation_value_3="[null]"
+                    variation_value_4="[null]"
                     variation_value_5="[null]"
-                    alert_text="[null]" VALUE="10.0" METRIC_ID="1" SNAPSHOT_ID="5"
+                    alert_text="[null]"
+                    VALUE="10.0"
+                    METRIC_ID="1"
+                    SNAPSHOT_ID="5"
                     person_id="[null]"
                     text_value="[null]"
                     component_uuid="5"
-                    alert_status="[null]" description="[null]" measure_data="[null]"/>
-  <events id="2" name="Version 1.0" component_uuid="5" snapshot_id="5" category="VERSION" description="[null]"
-          event_date="1228222680000" created_at="1228222680000" event_data="[null]"/>
+                    alert_status="[null]"
+                    description="[null]"
+                    measure_data="[null]"/>
+  <events id="2"
+          name="Version 1.0"
+          component_uuid="5"
+          snapshot_id="5"
+          category="VERSION"
+          description="[null]"
+          event_date="1228222680000"
+          created_at="1228222680000"
+          event_data="[null]"/>
   <duplications_index id="2"
-                      project_snapshot_id="5"
-                      snapshot_id="5"
+                      analysis_uuid="u5"
                       component_uuid="uuid_5"
                       hash="bb"
                       index_in_file="0"
index a6cd4cf7a528e2ca9c1a80c184e8810d1c634c4e..1e8f1ef1c1c637335265b3ceb9708456715f73ef 100644 (file)
@@ -10,15 +10,35 @@ Note that measures, events and reviews are not deleted.
 <dataset>
   <snapshots id="1"
              uuid="u1"
-             component_uuid="uuid_1" parent_snapshot_id="[null]" root_component_uuid="uuid_1" root_snapshot_id="[null]"
-             status="P" islast="[false]" purge_status="1"
-             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
-             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
-             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
-             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
-             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
-             depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000"
-             build_date="1228222680000" version="[null]" path="[null]"/>
+             component_uuid="uuid_1"
+             parent_snapshot_id="[null]"
+             root_component_uuid="uuid_1"
+             root_snapshot_id="[null]"
+             status="P"
+             islast="[false]"
+             purge_status="1"
+             period1_mode="[null]"
+             period1_param="[null]"
+             period1_date="[null]"
+             period2_mode="[null]"
+             period2_param="[null]"
+             period2_date="[null]"
+             period3_mode="[null]"
+             period3_param="[null]"
+             period3_date="[null]"
+             period4_mode="[null]"
+             period4_param="[null]"
+             period4_date="[null]"
+             period5_mode="[null]"
+             period5_param="[null]"
+             period5_date="[null]"
+             depth="[null]"
+             scope="PRJ"
+             qualifier="TRK"
+             created_at="1228222680000"
+             build_date="1228222680000"
+             version="[null]"
+             path="[null]"/>
 
   <!--switched_off="[null]" permanent_id="[null]" FAILURE_LEVEL="2"-->
   <!--MESSAGE="msg1" LINE="[null]" COST="[null]"-->
@@ -28,15 +48,27 @@ Note that measures, events and reviews are not deleted.
   <project_measures ID="1"
                     component_uuid="1"
                     SNAPSHOT_ID="1"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
+                    variation_value_1="[null]"
+                    variation_value_2="[null]"
+                    variation_value_3="[null]"
                     variation_value_4="[null]"
-                    variation_value_5="[null]" alert_text="[null]" VALUE="10.0" METRIC_ID="1"
+                    variation_value_5="[null]"
+                    alert_text="[null]"
+                    VALUE="10.0"
+                    METRIC_ID="1"
                     person_id="[null]"
-                    text_value="[null]" alert_status="[null]"
-                    description="[null]" measure_data="[null]"/>
+                    text_value="[null]"
+                    alert_status="[null]"
+                    description="[null]"
+                    measure_data="[null]"/>
 
-  <events id="1" component_uuid="1" snapshot_id="1"
-          category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000"
+  <events id="1"
+          component_uuid="1"
+          snapshot_id="1"
+          category="VERSION"
+          description="[null]"
+          name="Version 1.0"
+          event_date="1228222680000"
           created_at="1228222680000"
           event_data="[null]"/>
 
@@ -47,35 +79,66 @@ Note that measures, events and reviews are not deleted.
   <!-- The following is not purged but is kept for DBUnit -->
   <snapshots id="2"
              uuid="u2"
-             component_uuid="uuid_2" parent_snapshot_id="[null]" root_component_uuid="uuid_2" root_snapshot_id="[null]"
-             status="P" islast="[false]" purge_status="1"
-             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
-             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
-             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
-             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
-             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
-             depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000"
-             build_date="1228222680000" version="[null]" path="[null]"/>
+             component_uuid="uuid_2"
+             parent_snapshot_id="[null]"
+             root_component_uuid="uuid_2"
+             root_snapshot_id="[null]"
+             status="P"
+             islast="[false]"
+             purge_status="1"
+             period1_mode="[null]"
+             period1_param="[null]"
+             period1_date="[null]"
+             period2_mode="[null]"
+             period2_param="[null]"
+             period2_date="[null]"
+             period3_mode="[null]"
+             period3_param="[null]"
+             period3_date="[null]"
+             period4_mode="[null]"
+             period4_param="[null]"
+             period4_date="[null]"
+             period5_mode="[null]"
+             period5_param="[null]"
+             period5_date="[null]"
+             depth="[null]"
+             scope="PRJ"
+             qualifier="TRK"
+             created_at="1228222680000"
+             build_date="1228222680000"
+             version="[null]"
+             path="[null]"/>
 
 
   <project_measures ID="2"
                     component_uuid="2"
                     SNAPSHOT_ID="2"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
+                    variation_value_1="[null]"
+                    variation_value_2="[null]"
+                    variation_value_3="[null]"
                     variation_value_4="[null]"
-                    variation_value_5="[null]" alert_text="[null]" VALUE="10.0" METRIC_ID="1"
+                    variation_value_5="[null]"
+                    alert_text="[null]"
+                    VALUE="10.0"
+                    METRIC_ID="1"
                     person_id="[null]"
-                    text_value="[null]" alert_status="[null]"
-                    description="[null]" measure_data="[null]"/>
+                    text_value="[null]"
+                    alert_status="[null]"
+                    description="[null]"
+                    measure_data="[null]"/>
 
-  <events id="2" component_uuid="2" snapshot_id="2"
-          category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000"
+  <events id="2"
+          component_uuid="2"
+          snapshot_id="2"
+          category="VERSION"
+          description="[null]"
+          name="Version 1.0"
+          event_date="1228222680000"
           created_at="1228222680000"
           event_data="[null]"/>
 
   <duplications_index id="2"
-                      project_snapshot_id="2"
-                      snapshot_id="2"
+                      analysis_uuid="u2"
                       component_uuid="uuid_2"
                       hash="bb"
                       index_in_file="0"
index af33f74ab3775e1657067dbab7b56d36517f1c40..b218a1369b76e1ee5ad10fbfcdae786692a7cdca 100644 (file)
@@ -2,33 +2,65 @@
 
   <snapshots id="1"
              uuid="u1"
-             component_uuid="uuid_1" parent_snapshot_id="[null]" root_component_uuid="uuid_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="1228222680000"
-             build_date="1228222680000" version="[null]" path="[null]"/>
+             component_uuid="uuid_1"
+             parent_snapshot_id="[null]"
+             root_component_uuid="uuid_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="1228222680000"
+             build_date="1228222680000"
+             version="[null]"
+             path="[null]"/>
 
   <project_measures ID="1"
                     component_uuid="1"
                     SNAPSHOT_ID="1"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
-                    variation_value_4="[null]" variation_value_5="[null]" alert_text="[null]"
-                    VALUE="10.0" METRIC_ID="1" person_id="[null]" text_value="[null]"
-                    alert_status="[null]" description="[null]"
+                    variation_value_1="[null]"
+                    variation_value_2="[null]"
+                    variation_value_3="[null]"
+                    variation_value_4="[null]"
+                    variation_value_5="[null]"
+                    alert_text="[null]"
+                    VALUE="10.0"
+                    METRIC_ID="1"
+                    person_id="[null]"
+                    text_value="[null]"
+                    alert_status="[null]"
+                    description="[null]"
                     measure_data="[null]"/>
 
-  <events id="1" component_uuid="1" snapshot_id="1"
-          category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000"
+  <events id="1"
+          component_uuid="1"
+          snapshot_id="1"
+          category="VERSION"
+          description="[null]"
+          name="Version 1.0"
+          event_date="1228222680000"
           created_at="1228222680000"
           event_data="[null]"/>
 
   <duplications_index id="1"
-                      project_snapshot_id="1"
-                      snapshot_id="1"
+                      analysis_uuid="u1"
                       component_uuid="uuid_1"
                       hash="bb"
                       index_in_file="0"
   <snapshots id="2"
              uuid="u2"
              component_uuid="uuid_2"
-             parent_snapshot_id="[null]" root_component_uuid="uuid_2" root_snapshot_id="[null]"
-             status="P" islast="[false]" purge_status="1"
-             period1_mode="[null]" period1_param="[null]" period1_date="[null]"
-             period2_mode="[null]" period2_param="[null]" period2_date="[null]"
-             period3_mode="[null]" period3_param="[null]" period3_date="[null]"
-             period4_mode="[null]" period4_param="[null]" period4_date="[null]"
-             period5_mode="[null]" period5_param="[null]" period5_date="[null]"
-             depth="[null]" scope="PRJ" qualifier="TRK" created_at="1228222680000"
-             build_date="1228222680000" version="[null]" path="[null]"/>
+             parent_snapshot_id="[null]"
+             root_component_uuid="uuid_2"
+             root_snapshot_id="[null]"
+             status="P"
+             islast="[false]"
+             purge_status="1"
+             period1_mode="[null]"
+             period1_param="[null]"
+             period1_date="[null]"
+             period2_mode="[null]"
+             period2_param="[null]"
+             period2_date="[null]"
+             period3_mode="[null]"
+             period3_param="[null]"
+             period3_date="[null]"
+             period4_mode="[null]"
+             period4_param="[null]"
+             period4_date="[null]"
+             period5_mode="[null]"
+             period5_param="[null]"
+             period5_date="[null]"
+             depth="[null]"
+             scope="PRJ"
+             qualifier="TRK"
+             created_at="1228222680000"
+             build_date="1228222680000"
+             version="[null]"
+             path="[null]"/>
 
   <project_measures ID="2"
                     component_uuid="2"
-                    SNAPSHOT_ID="2" characteristic_id="[null]"
-                    variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]"
+                    SNAPSHOT_ID="2"
+                    characteristic_id="[null]"
+                    variation_value_1="[null]"
+                    variation_value_2="[null]"
+                    variation_value_3="[null]"
                     variation_value_4="[null]"
-                    variation_value_5="[null]" alert_text="[null]" VALUE="10.0" METRIC_ID="1"
+                    variation_value_5="[null]"
+                    alert_text="[null]"
+                    VALUE="10.0"
+                    METRIC_ID="1"
                     person_id="[null]"
-                    text_value="[null]" alert_status="[null]"
-                    description="[null]" measure_data="[null]"/>
+                    text_value="[null]"
+                    alert_status="[null]"
+                    description="[null]"
+                    measure_data="[null]"/>
 
-  <events id="2" component_uuid="2" snapshot_id="2"
-          category="VERSION" description="[null]" name="Version 1.0" event_date="1228222680000"
+  <events id="2"
+          component_uuid="2"
+          snapshot_id="2"
+          category="VERSION"
+          description="[null]"
+          name="Version 1.0"
+          event_date="1228222680000"
           created_at="1228222680000"
           event_data="[null]"/>
 
   <duplications_index id="2"
-                      project_snapshot_id="2"
-                      snapshot_id="2"
+                      analysis_uuid="u2"
                       component_uuid="uuid_2"
                       hash="bb"
                       index_in_file="0"