aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java30
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbCloneIndex.java114
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarCloneIndex.java (renamed from plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/CombinedCloneIndex.java)48
-rw-r--r--plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/DbCloneIndexTest.java38
-rw-r--r--plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/fixture.xml25
-rw-r--r--plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldGetByHash.xml43
-rw-r--r--plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert-result.xml26
-rw-r--r--plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert.xml7
-rw-r--r--plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PurgeUtils.java9
-rw-r--r--plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots-result.xml5
-rw-r--r--plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots.xml5
-rw-r--r--sonar-core/src/main/java/org/sonar/jpa/entity/CloneBlock.java16
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/db/migrate/217_create_clone_blocks.rb5
-rw-r--r--sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl5
14 files changed, 230 insertions, 146 deletions
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
index b3cd865cfc2..e99cd441e9f 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/SonarEngine.java
@@ -21,6 +21,7 @@ package org.sonar.plugins.cpd;
import java.io.File;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
@@ -30,7 +31,6 @@ import java.util.Set;
import org.sonar.api.batch.SensorContext;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
-import org.sonar.api.database.model.Snapshot;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Measure;
import org.sonar.api.resources.InputFile;
@@ -45,19 +45,15 @@ import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.BlockChunker;
import org.sonar.duplications.detector.original.OriginalCloneDetectionAlgorithm;
import org.sonar.duplications.index.CloneGroup;
-import org.sonar.duplications.index.CloneIndex;
import org.sonar.duplications.index.ClonePart;
-import org.sonar.duplications.index.PackedMemoryCloneIndex;
import org.sonar.duplications.java.JavaStatementBuilder;
import org.sonar.duplications.java.JavaTokenProducer;
import org.sonar.duplications.statement.Statement;
import org.sonar.duplications.statement.StatementChunker;
import org.sonar.duplications.token.TokenChunker;
import org.sonar.duplications.token.TokenQueue;
-import org.sonar.plugins.cpd.index.CombinedCloneIndex;
import org.sonar.plugins.cpd.index.DbCloneIndex;
-
-import com.google.common.collect.Lists;
+import org.sonar.plugins.cpd.index.SonarCloneIndex;
public class SonarEngine implements CpdEngine {
@@ -94,13 +90,12 @@ public class SonarEngine implements CpdEngine {
}
// Create index
- CloneIndex index = new PackedMemoryCloneIndex();
+ final SonarCloneIndex index;
if (isCrossProject(project)) {
Logs.INFO.info("Enabled cross-project analysis");
- Snapshot currentSnapshot = resourcePersister.getSnapshot(project);
- Snapshot lastSnapshot = resourcePersister.getLastSnapshot(currentSnapshot, false);
- DbCloneIndex db = new DbCloneIndex(dbSession, currentSnapshot.getId(), lastSnapshot == null ? null : lastSnapshot.getId());
- index = new CombinedCloneIndex(index, db);
+ index = new SonarCloneIndex(new DbCloneIndex(dbSession, resourcePersister, project));
+ } else {
+ index = new SonarCloneIndex();
}
TokenChunker tokenChunker = JavaTokenProducer.build();
@@ -108,21 +103,22 @@ public class SonarEngine implements CpdEngine {
BlockChunker blockChunker = new BlockChunker(BLOCK_SIZE);
for (InputFile inputFile : inputFiles) {
+ Resource resource = getResource(inputFile);
+ String resourceKey = getFullKey(project, resource);
+
File file = inputFile.getFile();
TokenQueue tokenQueue = tokenChunker.chunk(file);
List<Statement> statements = statementChunker.chunk(tokenQueue);
- Resource resource = getResource(inputFile);
- List<Block> blocks = blockChunker.chunk(getFullKey(project, resource), statements);
- for (Block block : blocks) {
- index.insert(block);
- }
+ List<Block> blocks = blockChunker.chunk(resourceKey, statements);
+ index.insert(resource, blocks);
}
// Detect
for (InputFile inputFile : inputFiles) {
Resource resource = getResource(inputFile);
+ String resourceKey = getFullKey(project, resource);
- List<Block> fileBlocks = Lists.newArrayList(index.getByResourceId(getFullKey(project, resource)));
+ Collection<Block> fileBlocks = index.getByResource(resource, resourceKey);
List<CloneGroup> clones = OriginalCloneDetectionAlgorithm.detect(index, fileBlocks);
if (!clones.isEmpty()) {
// Save
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbCloneIndex.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbCloneIndex.java
index 06f6c481cad..571dc43d3ec 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbCloneIndex.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/DbCloneIndex.java
@@ -24,48 +24,88 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
+import javax.persistence.Query;
+
+import org.hibernate.ejb.HibernateQuery;
+import org.hibernate.transform.Transformers;
import org.sonar.api.database.DatabaseSession;
+import org.sonar.api.database.model.Snapshot;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.Resource;
+import org.sonar.batch.index.ResourcePersister;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.ByteArray;
-import org.sonar.duplications.index.AbstractCloneIndex;
import org.sonar.jpa.entity.CloneBlock;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
-public class DbCloneIndex extends AbstractCloneIndex {
+public class DbCloneIndex {
+
+ private final Map<ByteArray, Collection<Block>> cache = Maps.newHashMap();
- private final Map<ByteArray, List<Block>> cache = Maps.newHashMap();
+ private final DatabaseSession session;
+ private final ResourcePersister resourcePersister;
+ private final int currentProjectSnapshotId;
+ private final Integer lastSnapshotId;
- private DatabaseSession session;
- private int currentSnapshotId;
- private Integer lastSnapshotId;
+ public DbCloneIndex(DatabaseSession session, ResourcePersister resourcePersister, Project currentProject) {
+ this.session = session;
+ this.resourcePersister = resourcePersister;
+ Snapshot currentSnapshot = resourcePersister.getSnapshotOrFail(currentProject);
+ Snapshot lastSnapshot = resourcePersister.getLastSnapshot(currentSnapshot, false);
+ this.currentProjectSnapshotId = currentSnapshot.getId();
+ this.lastSnapshotId = lastSnapshot == null ? null : lastSnapshot.getId();
+ }
- public DbCloneIndex(DatabaseSession session, Integer currentSnapshotId, Integer lastSnapshotId) {
+ /**
+ * For tests.
+ */
+ DbCloneIndex(DatabaseSession session, ResourcePersister resourcePersister, Integer currentProjectSnapshotId, Integer prevSnapshotId) {
this.session = session;
- this.currentSnapshotId = currentSnapshotId;
- this.lastSnapshotId = lastSnapshotId;
+ this.resourcePersister = resourcePersister;
+ this.currentProjectSnapshotId = currentProjectSnapshotId;
+ this.lastSnapshotId = prevSnapshotId;
}
- public void prepareCache(String resourceKey) {
- String sql = "SELECT block.id, hash, block.snapshot_id, resource_key, index_in_file, start_line, end_line FROM clone_blocks AS block, snapshots AS snapshot" +
- " WHERE block.snapshot_id=snapshot.id AND snapshot.islast=true" +
- " AND hash IN ( SELECT hash FROM clone_blocks WHERE resource_key = :resource_key AND snapshot_id = :current_snapshot_id )";
+ int getSnapshotIdFor(Resource resource) {
+ return resourcePersister.getSnapshotOrFail(resource).getId();
+ }
+
+ public void prepareCache(Resource resource) {
+ int resourceSnapshotId = getSnapshotIdFor(resource);
+
+ // Order of columns is important - see code below!
+ String sql = "SELECT hash, resource.kee, index_in_file, start_line, end_line" +
+ " FROM clone_blocks AS block, snapshots AS snapshot, projects AS resource" +
+ " WHERE block.snapshot_id=snapshot.id AND snapshot.islast=true AND snapshot.project_id=resource.id" +
+ " AND hash IN ( SELECT hash FROM clone_blocks WHERE snapshot_id = :resource_snapshot_id AND project_snapshot_id = :current_project_snapshot_id )";
if (lastSnapshotId != null) {
// Filter for blocks from previous snapshot of current project
- sql += " AND snapshot.id != " + lastSnapshotId;
+ sql += " AND block.project_snapshot_id != :last_project_snapshot_id";
}
- List<CloneBlock> blocks = session.getEntityManager()
- .createNativeQuery(sql, CloneBlock.class)
- .setParameter("resource_key", resourceKey)
- .setParameter("current_snapshot_id", currentSnapshotId)
- .getResultList();
+ Query query = session.getEntityManager().createNativeQuery(sql)
+ .setParameter("resource_snapshot_id", resourceSnapshotId)
+ .setParameter("current_project_snapshot_id", currentProjectSnapshotId);
+ if (lastSnapshotId != null) {
+ query.setParameter("last_project_snapshot_id", lastSnapshotId);
+ }
+ // Ugly hack for mapping results of custom SQL query into plain list (MyBatis is coming soon)
+ ((HibernateQuery) query).getHibernateQuery().setResultTransformer(Transformers.TO_LIST);
+ List<List<Object>> blocks = query.getResultList();
cache.clear();
- for (CloneBlock dbBlock : blocks) {
- Block block = new Block(dbBlock.getResourceKey(), new ByteArray(dbBlock.getHash()), dbBlock.getIndexInFile(), dbBlock.getStartLine(), dbBlock.getEndLine());
+ for (List<Object> dbBlock : blocks) {
+ String hash = (String) dbBlock.get(0);
+ String resourceKey = (String) dbBlock.get(1);
+ int indexInFile = (Integer) dbBlock.get(2);
+ int startLine = (Integer) dbBlock.get(3);
+ int endLine = (Integer) dbBlock.get(4);
+
+ Block block = new Block(resourceKey, new ByteArray(hash), indexInFile, startLine, endLine);
- List<Block> sameHash = cache.get(block.getBlockHash());
+ // Group blocks by hash
+ Collection<Block> sameHash = cache.get(block.getBlockHash());
if (sameHash == null) {
sameHash = Lists.newArrayList();
cache.put(block.getBlockHash(), sameHash);
@@ -74,28 +114,28 @@ public class DbCloneIndex extends AbstractCloneIndex {
}
}
- public Collection<Block> getByResourceId(String resourceId) {
- throw new UnsupportedOperationException();
- }
-
- public Collection<Block> getBySequenceHash(ByteArray sequenceHash) {
- List<Block> result = cache.get(sequenceHash);
+ public Collection<Block> getByHash(ByteArray hash) {
+ Collection<Block> result = cache.get(hash);
if (result != null) {
return result;
} else {
- // not in cache
return Collections.emptyList();
}
}
- public void insert(Block block) {
- CloneBlock dbBlock = new CloneBlock(currentSnapshotId,
- block.getBlockHash().toString(),
- block.getResourceId(),
- block.getIndexInFile(),
- block.getFirstLineNumber(),
- block.getLastLineNumber());
- session.save(dbBlock);
+ public void insert(Resource resource, Collection<Block> blocks) {
+ int resourceSnapshotId = getSnapshotIdFor(resource);
+ for (Block block : blocks) {
+ CloneBlock dbBlock = new CloneBlock(
+ currentProjectSnapshotId,
+ resourceSnapshotId,
+ block.getBlockHash().toString(),
+ block.getIndexInFile(),
+ block.getFirstLineNumber(),
+ block.getLastLineNumber());
+ session.save(dbBlock);
+ }
+ session.commit();
}
}
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/CombinedCloneIndex.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarCloneIndex.java
index 0b2f4e4c929..f5bd39542c1 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/CombinedCloneIndex.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/SonarCloneIndex.java
@@ -22,38 +22,60 @@ package org.sonar.plugins.cpd.index;
import java.util.Collection;
import java.util.List;
+import org.sonar.api.resources.Resource;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.ByteArray;
import org.sonar.duplications.index.AbstractCloneIndex;
import org.sonar.duplications.index.CloneIndex;
+import org.sonar.duplications.index.PackedMemoryCloneIndex;
import com.google.common.collect.Lists;
-public class CombinedCloneIndex extends AbstractCloneIndex {
+public class SonarCloneIndex extends AbstractCloneIndex {
- private final CloneIndex mem;
+ private final CloneIndex mem = new PackedMemoryCloneIndex();
private final DbCloneIndex db;
- public CombinedCloneIndex(CloneIndex mem, DbCloneIndex db) {
- this.mem = mem;
+ public SonarCloneIndex() {
+ this(null);
+ }
+
+ public SonarCloneIndex(DbCloneIndex db) {
this.db = db;
}
- public Collection<Block> getByResourceId(String resourceId) {
- db.prepareCache(resourceId);
- return mem.getByResourceId(resourceId);
+ public void insert(Resource resource, Collection<Block> blocks) {
+ for (Block block : blocks) {
+ mem.insert(block);
+ }
+ if (db != null) {
+ db.insert(resource, blocks);
+ }
+ }
+
+ public Collection<Block> getByResource(Resource resource, String resourceKey) {
+ if (db != null) {
+ db.prepareCache(resource);
+ }
+ return mem.getByResourceId(resourceKey);
}
public Collection<Block> getBySequenceHash(ByteArray hash) {
- List<Block> result = Lists.newArrayList();
- result.addAll(mem.getBySequenceHash(hash));
- result.addAll(db.getBySequenceHash(hash));
- return result;
+ if (db == null) {
+ return mem.getBySequenceHash(hash);
+ } else {
+ List<Block> result = Lists.newArrayList(mem.getBySequenceHash(hash));
+ result.addAll(db.getByHash(hash));
+ return result;
+ }
+ }
+
+ public Collection<Block> getByResourceId(String resourceId) {
+ throw new UnsupportedOperationException();
}
public void insert(Block block) {
- mem.insert(block);
- db.insert(block);
+ throw new UnsupportedOperationException();
}
}
diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/DbCloneIndexTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/DbCloneIndexTest.java
index 86698e89d64..5823c9f6044 100644
--- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/DbCloneIndexTest.java
+++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/DbCloneIndexTest.java
@@ -21,12 +21,16 @@ package org.sonar.plugins.cpd.index;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
-import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.resources.JavaFile;
+import org.sonar.api.resources.Resource;
import org.sonar.duplications.block.Block;
import org.sonar.duplications.block.ByteArray;
import org.sonar.jpa.test.AbstractDbUnitTestCase;
@@ -35,35 +39,35 @@ public class DbCloneIndexTest extends AbstractDbUnitTestCase {
private DbCloneIndex index;
- @Before
- public void setUp() {
- index = new DbCloneIndex(getSession(), 5, 4);
- }
-
- @Test(expected = UnsupportedOperationException.class)
- public void shouldNotGetByResource() {
- index.getByResourceId("foo");
- }
-
@Test
public void shouldGetByHash() {
- setupData("fixture");
+ Resource resource = new JavaFile("foo");
+ index = spy(new DbCloneIndex(getSession(), null, 9, 7));
+ doReturn(10).when(index).getSnapshotIdFor(resource);
+ setupData("shouldGetByHash");
- index.prepareCache("foo");
- Collection<Block> blocks = index.getBySequenceHash(new ByteArray("aa"));
+ index.prepareCache(resource);
+ Collection<Block> blocks = index.getByHash(new ByteArray("aa"));
Iterator<Block> blocksIterator = blocks.iterator();
assertThat(blocks.size(), is(1));
Block block = blocksIterator.next();
- assertThat(block.getResourceId(), is("bar-last"));
+ assertThat("block resourceId", block.getResourceId(), is("bar-last"));
+ assertThat("block hash", block.getBlockHash(), is(new ByteArray("aa")));
+ assertThat("block index in file", block.getIndexInFile(), is(0));
+ assertThat("block start line", block.getFirstLineNumber(), is(1));
+ assertThat("block end line", block.getLastLineNumber(), is(2));
}
@Test
public void shouldInsert() {
- setupData("fixture");
+ Resource resource = new JavaFile("foo");
+ index = spy(new DbCloneIndex(getSession(), null, 1, null));
+ doReturn(2).when(index).getSnapshotIdFor(resource);
+ setupData("shouldInsert");
- index.insert(new Block("baz", new ByteArray("bb"), 0, 0, 1));
+ index.insert(resource, Arrays.asList(new Block("foo", new ByteArray("bb"), 0, 1, 2)));
checkTables("shouldInsert", "clone_blocks");
}
diff --git a/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/fixture.xml b/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/fixture.xml
deleted file mode 100644
index 95599894c1b..00000000000
--- a/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/fixture.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<dataset>
-
- <snapshots id="1" status="P" islast="false" />
- <snapshots id="2" status="P" islast="true" />
-
- <snapshots id="3" status="P" islast="false" />
- <snapshots id="4" status="P" islast="true" />
- <snapshots id="5" status="U" islast="false" />
-
- <!-- Old snapshot of another project -->
- <clone_blocks id="1" snapshot_id="1" hash="aa" resource_key="bar-old" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- Last snapshot of another project -->
- <clone_blocks id="2" snapshot_id="2" hash="aa" resource_key="bar-last" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- Old snapshot of current project -->
- <clone_blocks id="3" snapshot_id="3" hash="aa" resource_key="foo-old" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- Last snapshot of current project -->
- <clone_blocks id="4" snapshot_id="4" hash="aa" resource_key="foo-last" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- New snapshot of current project -->
- <clone_blocks id="5" snapshot_id="5" hash="aa" resource_key="foo" index_in_file="0" start_line="0" end_line="1" />
-
-</dataset>
diff --git a/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldGetByHash.xml b/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldGetByHash.xml
new file mode 100644
index 00000000000..1dab2d464cf
--- /dev/null
+++ b/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldGetByHash.xml
@@ -0,0 +1,43 @@
+<dataset>
+
+ <snapshots id="1" status="P" islast="false" project_id="0" />
+ <snapshots id="2" status="P" islast="false" project_id="1" />
+ <projects id="1" kee="bar-old" enabled="true" scope="FIL" qualifier="CLA" />
+
+ <snapshots id="3" status="P" islast="true" />
+ <snapshots id="4" status="P" islast="true" project_id="2" />
+ <projects id="2" kee="bar-last" enabled="true" scope="FIL" qualifier="CLA" />
+
+ <snapshots id="5" status="P" islast="false" />
+ <snapshots id="6" status="P" islast="false" project_id="3" />
+ <projects id="3" kee="foo-old" enabled="true" scope="FIL" qualifier="CLA" />
+
+ <snapshots id="7" status="P" islast="true" />
+ <snapshots id="8" status="P" islast="true" project_id="4" />
+ <projects id="4" kee="foo-last" enabled="true" scope="FIL" qualifier="CLA" />
+
+ <snapshots id="9" status="U" islast="false" />
+ <snapshots id="10" status="U" islast="false" project_id="5" />
+ <projects id="5" kee="foo" enabled="true" scope="FIL" qualifier="CLA" />
+
+ <!-- Old snapshot of another project -->
+ <!-- bar-old -->
+ <clone_blocks id="1" project_snapshot_id="1" snapshot_id="2" hash="bb" index_in_file="0" start_line="0" end_line="0" />
+
+ <!-- Last snapshot of another project -->
+ <!-- bar-last -->
+ <clone_blocks id="2" project_snapshot_id="3" snapshot_id="4" hash="aa" index_in_file="0" start_line="1" end_line="2" />
+
+ <!-- Old snapshot of current project -->
+ <!-- foo-old -->
+ <clone_blocks id="3" project_snapshot_id="5" snapshot_id="6" hash="bb" index_in_file="0" start_line="0" end_line="0" />
+
+ <!-- Last snapshot of current project -->
+ <!-- foo-last -->
+ <clone_blocks id="4" project_snapshot_id="7" snapshot_id="8" hash="bb" index_in_file="0" start_line="0" end_line="0" />
+
+ <!-- New snapshot of current project -->
+ <!-- foo -->
+ <clone_blocks id="5" project_snapshot_id="9" snapshot_id="10" hash="aa" index_in_file="0" start_line="0" end_line="0" />
+
+</dataset>
diff --git a/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert-result.xml b/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert-result.xml
index ae2767dfedb..e3e709ffc45 100644
--- a/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert-result.xml
+++ b/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert-result.xml
@@ -1,27 +1,9 @@
<dataset>
- <snapshots id="1" status="P" islast="false" />
- <snapshots id="2" status="P" islast="true" />
+ <snapshots id="1" status="U" islast="false" project_id="0" />
+ <snapshots id="2" status="U" islast="false" project_id="1" />
+ <projects id="1" kee="foo" enabled="true" scope="FIL" qualifier="CLA" />
- <snapshots id="3" status="P" islast="false" />
- <snapshots id="4" status="P" islast="true" />
- <snapshots id="5" status="U" islast="false" />
-
- <!-- Old snapshot of another project -->
- <clone_blocks id="1" snapshot_id="1" hash="aa" resource_key="bar-old" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- Last snapshot of another project -->
- <clone_blocks id="2" snapshot_id="2" hash="aa" resource_key="bar-last" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- Old snapshot of current project -->
- <clone_blocks id="3" snapshot_id="3" hash="aa" resource_key="foo-old" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- Last snapshot of current project -->
- <clone_blocks id="4" snapshot_id="4" hash="aa" resource_key="foo-last" index_in_file="0" start_line="0" end_line="1" />
-
- <!-- New snapshot of current project -->
- <clone_blocks id="5" snapshot_id="5" hash="aa" resource_key="foo" index_in_file="0" start_line="0" end_line="1" />
-
- <clone_blocks id="6" snapshot_id="5" hash="bb" resource_key="baz" index_in_file="0" start_line="0" end_line="1" />
+ <clone_blocks id="1" project_snapshot_id="1" snapshot_id="2" hash="bb" index_in_file="0" start_line="1" end_line="2" />
</dataset>
diff --git a/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert.xml b/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert.xml
new file mode 100644
index 00000000000..940281a0599
--- /dev/null
+++ b/plugins/sonar-cpd-plugin/src/test/resources/org/sonar/plugins/cpd/index/DbCloneIndexTest/shouldInsert.xml
@@ -0,0 +1,7 @@
+<dataset>
+
+ <snapshots id="1" status="U" islast="false" project_id="0" />
+ <snapshots id="2" status="U" islast="false" project_id="1" />
+ <projects id="1" kee="foo" enabled="true" scope="FIL" qualifier="CLA" />
+
+</dataset>
diff --git a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PurgeUtils.java b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PurgeUtils.java
index c417befec67..8a7451b9d80 100644
--- a/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PurgeUtils.java
+++ b/plugins/sonar-dbcleaner-plugin/src/main/java/org/sonar/plugins/dbcleaner/api/PurgeUtils.java
@@ -24,6 +24,7 @@ import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.*;
import org.sonar.api.design.DependencyDto;
import org.sonar.api.utils.TimeProfiler;
+import org.sonar.jpa.entity.CloneBlock;
import javax.persistence.Query;
import java.util.List;
@@ -58,6 +59,7 @@ public final class PurgeUtils {
deleteSources(session, snapshotIds);
deleteViolations(session, snapshotIds);
deleteDependencies(session, snapshotIds);
+ deleteCloneBlocks(session, snapshotIds);
deleteSnapshots(session, snapshotIds);
}
@@ -97,6 +99,13 @@ public final class PurgeUtils {
}
/**
+ * @since 2.11
+ */
+ private static void deleteCloneBlocks(DatabaseSession session, List<Integer> snapshotIds) {
+ executeQuery(session, "delete clone blocks", snapshotIds, "delete from " + CloneBlock.class.getSimpleName() + " e where e.snapshotId in (:ids)");
+ }
+
+ /**
* Delete SNAPSHOTS table
*/
public static void deleteSnapshots(DatabaseSession session, List<Integer> snapshotIds) {
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots-result.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots-result.xml
index 912541667d8..23847972836 100644
--- a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots-result.xml
+++ b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots-result.xml
@@ -108,4 +108,7 @@
<!--parent_dependency_id="[null]" project_snapshot_id="1"-->
<!--dep_usage="INHERITS" dep_weight="1" from_scope="FIL" to_scope="FIL"/>-->
-</dataset> \ No newline at end of file
+ <!--<clone_blocks id="1" project_snapshot_id="1" snapshot_id="3" hash="bb" index_in_file="0" start_line="0" end_line="0" />-->
+ <!--<clone_blocks id="2" project_snapshot_id="1" snapshot_id="4" hash="bb" index_in_file="0" start_line="0" end_line="0" />-->
+
+</dataset>
diff --git a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots.xml b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots.xml
index 2b92c63361a..6f2a149c513 100644
--- a/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots.xml
+++ b/plugins/sonar-dbcleaner-plugin/src/test/resources/org/sonar/plugins/dbcleaner/api/PurgeUtilsTest/purgeSnapshots.xml
@@ -108,4 +108,7 @@
parent_dependency_id="[null]" project_snapshot_id="1"
dep_usage="INHERITS" dep_weight="1" from_scope="FIL" to_scope="FIL" />
-</dataset> \ No newline at end of file
+ <clone_blocks id="1" project_snapshot_id="1" snapshot_id="3" hash="bb" index_in_file="0" start_line="0" end_line="0" />
+ <clone_blocks id="2" project_snapshot_id="1" snapshot_id="4" hash="bb" index_in_file="0" start_line="0" end_line="0" />
+
+</dataset>
diff --git a/sonar-core/src/main/java/org/sonar/jpa/entity/CloneBlock.java b/sonar-core/src/main/java/org/sonar/jpa/entity/CloneBlock.java
index b4de0db290a..7589a9947dd 100644
--- a/sonar-core/src/main/java/org/sonar/jpa/entity/CloneBlock.java
+++ b/sonar-core/src/main/java/org/sonar/jpa/entity/CloneBlock.java
@@ -25,8 +25,6 @@ import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
-import org.sonar.api.database.model.ResourceModel;
-
/**
* @since 2.11
*/
@@ -44,12 +42,12 @@ public class CloneBlock {
@Column(name = "snapshot_id", updatable = false, nullable = false)
private Integer snapshotId;
+ @Column(name = "project_snapshot_id", updatable = false, nullable = false)
+ private Integer projectSnapshotId;
+
@Column(name = "hash", updatable = false, nullable = false, length = BLOCK_HASH_SIZE)
private String hash;
- @Column(name = "resource_key", updatable = false, nullable = false, length = ResourceModel.KEY_SIZE)
- private String resourceKey;
-
@Column(name = "index_in_file", updatable = false, nullable = false)
private Integer indexInFile;
@@ -62,11 +60,11 @@ public class CloneBlock {
public CloneBlock() {
}
- public CloneBlock(Integer snapshotId, String hash, String resourceKey, Integer indexInFile, Integer startLine, Integer endLine) {
+ public CloneBlock(Integer projectSnapshotId, Integer snapshotId, String hash, Integer indexInFile, Integer startLine, Integer endLine) {
+ this.projectSnapshotId = projectSnapshotId;
this.snapshotId = snapshotId;
this.hash = hash;
this.indexInFile = indexInFile;
- this.resourceKey = resourceKey;
this.startLine = startLine;
this.endLine = endLine;
}
@@ -79,8 +77,8 @@ public class CloneBlock {
return snapshotId;
}
- public String getResourceKey() {
- return resourceKey;
+ public Integer getProjectSnapshotId() {
+ return projectSnapshotId;
}
public String getHash() {
diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/217_create_clone_blocks.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/217_create_clone_blocks.rb
index abd611c748a..4ea9a8343d1 100644
--- a/sonar-server/src/main/webapp/WEB-INF/db/migrate/217_create_clone_blocks.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/217_create_clone_blocks.rb
@@ -25,16 +25,17 @@ class CreateCloneBlocks < ActiveRecord::Migration
def self.up
create_table :clone_blocks do |t|
+ t.column :project_snapshot_id, :integer, :null => false
t.column :snapshot_id, :integer, :null => false
t.column :hash, :string, :null => false, :limit => 50
- t.column :resource_key, :string, :null => false, :limit => 400
t.column :index_in_file, :integer, :null => false
t.column :start_line, :integer, :null => false
t.column :end_line, :integer, :null => false
end
+ add_index :clone_blocks, :project_snapshot_id, :name => 'clone_blocks_project_snapshot'
+ add_index :clone_blocks, :snapshot_id, :name => 'clone_blocks_snapshot'
add_index :clone_blocks, :hash, :name => 'clone_blocks_hash'
- add_index :clone_blocks, [:snapshot_id, :resource_key], :name => 'clone_blocks_resource'
end
end
diff --git a/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl b/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl
index 1c8c3eb23fe..7ebfd7cdd4e 100644
--- a/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl
+++ b/sonar-testing-harness/src/main/resources/org/sonar/test/persistence/sonar-test.ddl
@@ -489,12 +489,13 @@ CREATE TABLE REVIEW_COMMENTS (
);
CREATE TABLE CLONE_BLOCKS (
+ PROJECT_SNAPSHOT_ID INTEGER,
SNAPSHOT_ID INTEGER,
HASH VARCHAR(50),
- RESOURCE_KEY VARCHAR(400),
INDEX_IN_FILE INTEGER NOT NULL,
START_LINE INTEGER NOT NULL,
END_LINE INTEGER NOT NULL
);
+CREATE INDEX CLONE_BLOCKS_PROJECT_SNAPSHOT ON CLONE_BLOCKS (PROJECT_SNAPSHOT_ID);
+CREATE INDEX CLONE_BLOCKS_SNAPSHOT ON CLONE_BLOCKS (SNAPSHOT_ID);
CREATE INDEX CLONE_BLOCKS_HASH ON CLONE_BLOCKS (HASH);
-CREATE INDEX CLONE_BLOCKS_RESOURCE ON CLONE_BLOCKS (SNAPSHOT_ID, RESOURCE_KEY);