aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core/src/main
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2011-12-20 21:32:31 +0100
committersimonbrandhof <simon.brandhof@gmail.com>2011-12-20 21:32:31 +0100
commiteae7223b4cdfbce089c4f30a31692ae8130df600 (patch)
tree936eb6cf351052b30e3bc735a4ea834fa38d712c /sonar-core/src/main
parent3abd667d979c3899a4f529a6e0dbf0e0dddb8245 (diff)
downloadsonarqube-eae7223b4cdfbce089c4f30a31692ae8130df600.tar.gz
sonarqube-eae7223b4cdfbce089c4f30a31692ae8130df600.zip
SONAR-983 resources are indexed during analysis
* Rename the column RESOURCE_INDEX.PROJECT_ID to ROOT_PROJECT_ID * Increase the size of RESOURCE_INDEX.PROJECT_ID * Clean resource index from dbcleaner plugin * Experimental: indexes all the existing resources during upgrade from sonar < 2.13
Diffstat (limited to 'sonar-core/src/main')
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexDto.java10
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerDao.java135
-rw-r--r--sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerMapper.java10
-rw-r--r--sonar-core/src/main/resources/org/sonar/persistence/resource/ResourceIndexerMapper.xml25
-rw-r--r--sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl4
5 files changed, 132 insertions, 52 deletions
diff --git a/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexDto.java b/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexDto.java
index 5272747b0ec..e1622a105ba 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexDto.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexDto.java
@@ -25,7 +25,7 @@ public final class ResourceIndexDto {
private int position;
private int nameSize;
private int resourceId;
- private int projectId;
+ private int rootProjectId;
public String getKey() {
return key;
@@ -54,12 +54,12 @@ public final class ResourceIndexDto {
return this;
}
- public int getProjectId() {
- return projectId;
+ public int getRootProjectId() {
+ return rootProjectId;
}
- public ResourceIndexDto setProjectId(int i) {
- this.projectId = i;
+ public ResourceIndexDto setRootProjectId(int i) {
+ this.rootProjectId = i;
return this;
}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerDao.java b/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerDao.java
index 485539a2e5a..3cc2900d356 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerDao.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerDao.java
@@ -19,14 +19,18 @@
*/
package org.sonar.persistence.resource;
+import com.google.common.collect.Lists;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.persistence.DatabaseUtils;
import org.sonar.persistence.MyBatis;
+import java.util.List;
+
public class ResourceIndexerDao {
public static final int MINIMUM_KEY_SIZE = 3;
@@ -37,68 +41,117 @@ public class ResourceIndexerDao {
this.mybatis = mybatis;
}
- void index(ResourceDto resource, SqlSession session) {
- String name = resource.getName();
- if (StringUtils.isBlank(name)) {
- return;
- }
- String normalizedName = normalize(name);
- if (normalizedName.length() >= MINIMUM_KEY_SIZE) {
- ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
-
- Integer rootId;
- if (resource.getRootId() != null) {
- ResourceDto root = mapper.selectRootId(resource.getRootId());
- if (root != null) {
- rootId = (Integer) ObjectUtils.defaultIfNull(root.getRootId(), root.getId());
- } else {
- rootId = resource.getRootId();
- }
- } else {
- rootId = resource.getId();
- }
-
- ResourceIndexDto dto = new ResourceIndexDto()
- .setResourceId(resource.getId())
- .setProjectId(rootId)
- .setNameSize(name.length());
-
- for (int position = 0; position <= normalizedName.length() - MINIMUM_KEY_SIZE; position++) {
- dto.setPosition(position);
- dto.setKey(StringUtils.substring(normalizedName, position));
- mapper.insert(dto);
- }
-
- session.commit();
- }
- }
-
- public void index(String resourceName, int resourceId, int projectId) {
+ public ResourceIndexerDao index(String resourceName, int resourceId, int rootProjectId) {
SqlSession sqlSession = mybatis.openSession();
try {
- index(new ResourceDto().setId(resourceId).setName(resourceName).setRootId(projectId), sqlSession);
+ index(new ResourceDto().setId(resourceId).setName(resourceName).setRootId(rootProjectId), sqlSession, true);
} finally {
sqlSession.close();
}
+ return this;
}
- public void index(ResourceIndexerFilter filter) {
+ public ResourceIndexerDao index(ResourceIndexerFilter filter) {
final SqlSession sqlSession = mybatis.openSession(ExecutorType.BATCH);
try {
sqlSession.select("selectResourcesToIndex", filter, new ResultHandler() {
public void handleResult(ResultContext context) {
ResourceDto resource = (ResourceDto) context.getResultObject();
- index(resource, sqlSession);
+
+ // The column PROJECTS.ROOT_ID references the module but not the root project in a multi-modules project.
+ boolean correctRootProjectId = false;
+
+ index(resource, sqlSession, correctRootProjectId);
}
});
} finally {
sqlSession.close();
}
+ return this;
+ }
+
+ public ResourceIndexerDao delete(List<Integer> resourceIds) {
+ final SqlSession sqlSession = mybatis.openSession();
+ try {
+ ResourceIndexerMapper mapper = sqlSession.getMapper(ResourceIndexerMapper.class);
+ List<List<Integer>> partitionsOfResourceIds = Lists.partition(resourceIds, DatabaseUtils.MAX_IN_ELEMENTS);
+ for (List<Integer> partitionOfResourceIds : partitionsOfResourceIds) {
+ if (!partitionOfResourceIds.isEmpty()) {
+ mapper.deleteByResourceIds(partitionOfResourceIds);
+ }
+ }
+ sqlSession.commit();
+
+ } finally {
+ sqlSession.close();
+ }
+ return this;
+ }
+
+ void index(ResourceDto resource, SqlSession session, boolean correctProjectRootId) {
+ String name = resource.getName();
+ if (StringUtils.isBlank(name) || resource.getId() == null) {
+ return;
+ }
+
+ String key = toKey(name);
+ if (key.length() >= MINIMUM_KEY_SIZE) {
+ ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
+ boolean toBeIndexed = sanitizeIndex(resource, key, mapper);
+ if (toBeIndexed) {
+
+ ResourceIndexDto dto = new ResourceIndexDto()
+ .setResourceId(resource.getId())
+ .setRootProjectId(loadRootProjectId(resource, mapper, correctProjectRootId))
+ .setNameSize(name.length());
+
+ for (int position = 0; position <= key.length() - MINIMUM_KEY_SIZE; position++) {
+ dto.setPosition(position);
+ dto.setKey(StringUtils.substring(key, position));
+ mapper.insert(dto);
+ }
+
+ session.commit();
+ }
+ }
+ }
+
+ private Integer loadRootProjectId(ResourceDto resource, ResourceIndexerMapper mapper, boolean correctProjectRootId) {
+ if (correctProjectRootId) {
+ return resource.getRootId();
+ }
+ Integer rootId;
+ if (resource.getRootId() != null) {
+ ResourceDto root = mapper.selectRootId(resource.getRootId());
+ if (root != null) {
+ rootId = (Integer) ObjectUtils.defaultIfNull(root.getRootId(), root.getId());
+ } else {
+ rootId = resource.getRootId();
+ }
+ } else {
+ rootId = resource.getId();
+ }
+ return rootId;
+ }
+
+ /**
+ * Return true if the resource must be indexed, false if the resource is already indexed.
+ * If the resource is indexed with a different key, then this index is dropped and the
+ * resource must be indexed again.
+ */
+ private boolean sanitizeIndex(ResourceDto resource, String key, ResourceIndexerMapper mapper) {
+ ResourceIndexDto masterIndex = mapper.selectMasterIndexByResourceId(resource.getId());
+ if (masterIndex != null && !StringUtils.equals(key, masterIndex.getKey())) {
+ // resource has been renamed -> drop existing indexes
+ mapper.deleteByResourceId(resource.getId());
+ masterIndex = null;
+ }
+ return masterIndex == null;
}
- static String normalize(String input) {
+ static String toKey(String input) {
return StringUtils.lowerCase(input);
}
}
diff --git a/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerMapper.java b/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerMapper.java
index 209126ce466..beec37e4bfd 100644
--- a/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerMapper.java
+++ b/sonar-core/src/main/java/org/sonar/persistence/resource/ResourceIndexerMapper.java
@@ -19,9 +19,19 @@
*/
package org.sonar.persistence.resource;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
public interface ResourceIndexerMapper {
ResourceDto selectRootId(int id);
+ ResourceIndexDto selectMasterIndexByResourceId(int resourceId);
+
+ void deleteByResourceId(int resourceId);
+
+ void deleteByResourceIds(@Param("resourceIds") List<Integer> resourceIds);
+
void insert(ResourceIndexDto dto);
}
diff --git a/sonar-core/src/main/resources/org/sonar/persistence/resource/ResourceIndexerMapper.xml b/sonar-core/src/main/resources/org/sonar/persistence/resource/ResourceIndexerMapper.xml
index 5b0c389d3d1..94ac6e57a95 100644
--- a/sonar-core/src/main/resources/org/sonar/persistence/resource/ResourceIndexerMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/persistence/resource/ResourceIndexerMapper.xml
@@ -3,7 +3,7 @@
<mapper namespace="org.sonar.persistence.resource.ResourceIndexerMapper">
- <select id="selectResourcesToIndex" parameterType="map" resultType="resource">
+ <select id="selectResourcesToIndex" parameterType="map" resultType="Resource">
select id, root_id as "rootId", name
from projects
<where>
@@ -18,16 +18,33 @@
</where>
</select>
- <select id="selectRootId" parameterType="int" resultType="resource">
+ <select id="selectRootId" parameterType="int" resultType="Resource">
select id, root_id as "rootId"
from projects
where id=#{id}
</select>
+ <select id="selectMasterIndexByResourceId" parameterType="int" resultType="ResourceIndex">
+ select kee as "key", resource_id as "resourceId"
+ from resource_index
+ where resource_id=#{id} and position=0
+ </select>
+
+ <delete id="deleteByResourceId" parameterType="int">
+ delete from resource_index
+ where resource_id=#{id}
+ </delete>
+
+ <delete id="deleteByResourceIds" parameterType="map">
+ delete from resource_index
+ where resource_id in
+ <foreach item="i" index="index" collection="resourceIds" open="(" separator="," close=")">#{i}</foreach>
+ </delete>
+
<insert id="insert" parameterType="ResourceIndex" useGeneratedKeys="false">
- insert into resource_index (kee, position, name_size, resource_id, project_id)
- values (#{key}, #{position}, #{nameSize}, #{resourceId}, #{projectId})
+ insert into resource_index (kee, position, name_size, resource_id, root_project_id)
+ values (#{key}, #{position}, #{nameSize}, #{resourceId}, #{rootProjectId})
</insert>
</mapper>
diff --git a/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl b/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl
index 02ae63063d2..879e426a883 100644
--- a/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl
+++ b/sonar-core/src/main/resources/org/sonar/persistence/schema-derby.ddl
@@ -460,11 +460,11 @@ CREATE TABLE "LOADED_TEMPLATES" (
);
CREATE TABLE "RESOURCE_INDEX" (
- "KEE" VARCHAR(100) NOT NULL,
+ "KEE" VARCHAR(400) NOT NULL,
"POSITION" INTEGER NOT NULL,
"NAME_SIZE" INTEGER NOT NULL,
"RESOURCE_ID" INTEGER NOT NULL,
- "PROJECT_ID" INTEGER NOT NULL
+ "ROOT_PROJECT_ID" INTEGER NOT NULL
);
CREATE TABLE "ACTION_PLANS" (