aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core
diff options
context:
space:
mode:
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2014-12-02 15:54:24 +0100
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2014-12-02 16:25:49 +0100
commit6078d64d4cfb41032b4e17bec32905fa3d219ac3 (patch)
tree340bb34bee17ea6f090534175842d3ccf5a41067 /sonar-core
parentb85022a92061e8f320ea605309fa99107351d506 (diff)
downloadsonarqube-6078d64d4cfb41032b4e17bec32905fa3d219ac3.tar.gz
sonarqube-6078d64d4cfb41032b4e17bec32905fa3d219ac3.zip
SONAR-5804 delete file_sources when deleting a project or during the data cleaning step
Diffstat (limited to 'sonar-core')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java5
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java105
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/IdUuidPair.java50
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/IdUuidPairs.java50
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java6
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java23
-rw-r--r--sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java4
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml55
-rw-r--r--sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java5
-rw-r--r--sonar-core/src/test/java/org/sonar/core/purge/IdUuidPairsTest.java48
-rw-r--r--sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java33
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml5
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml79
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml19
14 files changed, 356 insertions, 131 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java
index 51128905fa0..2e0f073571e 100644
--- a/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java
+++ b/sonar-core/src/main/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTask.java
@@ -28,10 +28,12 @@ import org.sonar.api.config.Settings;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.utils.TimeUtils;
import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.IdUuidPair;
import org.sonar.core.purge.PurgeConfiguration;
import org.sonar.core.purge.PurgeDao;
import org.sonar.core.purge.PurgeProfiler;
import org.sonar.core.resource.ResourceDao;
+import org.sonar.core.resource.ResourceDto;
import org.sonar.plugins.dbcleaner.api.PurgeTask;
import static org.sonar.core.purge.PurgeConfiguration.newDefaultPurgeConfiguration;
@@ -57,7 +59,8 @@ public class DefaultPurgeTask implements PurgeTask {
@Override
public DefaultPurgeTask delete(long resourceId) {
- purgeDao.deleteResourceTree(resourceId);
+ ResourceDto project = resourceDao.getResource(resourceId);
+ purgeDao.deleteResourceTree(new IdUuidPair(project.getId(), project.getUuid()));
return this;
}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
index 410afd92970..43d1f26cefc 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/MyBatis.java
@@ -24,11 +24,7 @@ import com.google.common.io.Closeables;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.mapping.Environment;
-import org.apache.ibatis.session.Configuration;
-import org.apache.ibatis.session.ExecutorType;
-import org.apache.ibatis.session.SqlSession;
-import org.apache.ibatis.session.SqlSessionFactory;
-import org.apache.ibatis.session.SqlSessionFactoryBuilder;
+import org.apache.ibatis.session.*;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.ibatis.type.JdbcType;
import org.slf4j.LoggerFactory;
@@ -45,14 +41,7 @@ import org.sonar.core.component.db.SnapshotMapper;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.computation.db.AnalysisReportMapper;
import org.sonar.core.config.Logback;
-import org.sonar.core.dashboard.ActiveDashboardDto;
-import org.sonar.core.dashboard.ActiveDashboardMapper;
-import org.sonar.core.dashboard.DashboardDto;
-import org.sonar.core.dashboard.DashboardMapper;
-import org.sonar.core.dashboard.WidgetDto;
-import org.sonar.core.dashboard.WidgetMapper;
-import org.sonar.core.dashboard.WidgetPropertyDto;
-import org.sonar.core.dashboard.WidgetPropertyMapper;
+import org.sonar.core.dashboard.*;
import org.sonar.core.dependency.DependencyDto;
import org.sonar.core.dependency.DependencyMapper;
import org.sonar.core.dependency.ResourceSnapshotDto;
@@ -61,56 +50,23 @@ import org.sonar.core.duplication.DuplicationMapper;
import org.sonar.core.duplication.DuplicationUnitDto;
import org.sonar.core.graph.jdbc.GraphDto;
import org.sonar.core.graph.jdbc.GraphDtoMapper;
-import org.sonar.core.issue.db.ActionPlanDto;
-import org.sonar.core.issue.db.ActionPlanMapper;
-import org.sonar.core.issue.db.ActionPlanStatsDto;
-import org.sonar.core.issue.db.ActionPlanStatsMapper;
-import org.sonar.core.issue.db.IssueChangeDto;
-import org.sonar.core.issue.db.IssueChangeMapper;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.issue.db.IssueFilterDto;
-import org.sonar.core.issue.db.IssueFilterFavouriteDto;
-import org.sonar.core.issue.db.IssueFilterFavouriteMapper;
-import org.sonar.core.issue.db.IssueFilterMapper;
-import org.sonar.core.issue.db.IssueMapper;
-import org.sonar.core.measure.db.MeasureDto;
-import org.sonar.core.measure.db.MeasureFilterDto;
-import org.sonar.core.measure.db.MeasureFilterMapper;
-import org.sonar.core.measure.db.MeasureMapper;
-import org.sonar.core.measure.db.MetricDto;
-import org.sonar.core.measure.db.MetricMapper;
+import org.sonar.core.issue.db.*;
+import org.sonar.core.measure.db.*;
import org.sonar.core.notification.db.NotificationQueueDto;
import org.sonar.core.notification.db.NotificationQueueMapper;
-import org.sonar.core.permission.GroupWithPermissionDto;
-import org.sonar.core.permission.PermissionTemplateDto;
-import org.sonar.core.permission.PermissionTemplateGroupDto;
-import org.sonar.core.permission.PermissionTemplateMapper;
-import org.sonar.core.permission.PermissionTemplateUserDto;
-import org.sonar.core.permission.UserWithPermissionDto;
+import org.sonar.core.permission.*;
import org.sonar.core.persistence.dialect.Dialect;
import org.sonar.core.persistence.migration.v44.Migration44Mapper;
import org.sonar.core.persistence.migration.v45.Migration45Mapper;
import org.sonar.core.persistence.migration.v50.Migration50Mapper;
import org.sonar.core.properties.PropertiesMapper;
import org.sonar.core.properties.PropertyDto;
+import org.sonar.core.purge.IdUuidPair;
import org.sonar.core.purge.PurgeMapper;
import org.sonar.core.purge.PurgeableSnapshotDto;
-import org.sonar.core.qualitygate.db.ProjectQgateAssociationDto;
-import org.sonar.core.qualitygate.db.ProjectQgateAssociationMapper;
-import org.sonar.core.qualitygate.db.QualityGateConditionDto;
-import org.sonar.core.qualitygate.db.QualityGateConditionMapper;
-import org.sonar.core.qualitygate.db.QualityGateDto;
-import org.sonar.core.qualitygate.db.QualityGateMapper;
-import org.sonar.core.qualityprofile.db.ActiveRuleDto;
-import org.sonar.core.qualityprofile.db.ActiveRuleMapper;
-import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
-import org.sonar.core.qualityprofile.db.QualityProfileDto;
-import org.sonar.core.qualityprofile.db.QualityProfileMapper;
-import org.sonar.core.resource.ResourceDto;
-import org.sonar.core.resource.ResourceIndexDto;
-import org.sonar.core.resource.ResourceIndexerMapper;
-import org.sonar.core.resource.ResourceKeyUpdaterMapper;
-import org.sonar.core.resource.ResourceMapper;
+import org.sonar.core.qualitygate.db.*;
+import org.sonar.core.qualityprofile.db.*;
+import org.sonar.core.resource.*;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.rule.RuleMapper;
import org.sonar.core.rule.RuleParamDto;
@@ -123,17 +79,7 @@ import org.sonar.core.technicaldebt.db.CharacteristicMapper;
import org.sonar.core.technicaldebt.db.RequirementMigrationDto;
import org.sonar.core.template.LoadedTemplateDto;
import org.sonar.core.template.LoadedTemplateMapper;
-import org.sonar.core.user.AuthorDto;
-import org.sonar.core.user.AuthorMapper;
-import org.sonar.core.user.GroupDto;
-import org.sonar.core.user.GroupMapper;
-import org.sonar.core.user.GroupMembershipDto;
-import org.sonar.core.user.GroupMembershipMapper;
-import org.sonar.core.user.GroupRoleDto;
-import org.sonar.core.user.RoleMapper;
-import org.sonar.core.user.UserDto;
-import org.sonar.core.user.UserMapper;
-import org.sonar.core.user.UserRoleDto;
+import org.sonar.core.user.*;
import java.io.InputStream;
@@ -152,6 +98,21 @@ public class MyBatis implements BatchComponent, ServerComponent {
this.queue = queue;
}
+ public static void closeQuietly(SqlSession session) {
+ if (session != null) {
+ try {
+ session.close();
+ } catch (Exception e) {
+ LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e);
+ // do not re-throw the exception
+ }
+ }
+ }
+
+ private static JdbcTransactionFactory createTransactionFactory() {
+ return new JdbcTransactionFactory();
+ }
+
public MyBatis start() {
LogFactory.useSlf4jLogging();
@@ -218,6 +179,7 @@ public class MyBatis implements BatchComponent, ServerComponent {
loadAlias(conf, "RequirementMigration", RequirementMigrationDto.class);
loadAlias(conf, "Activity", ActivityDto.class);
loadAlias(conf, "AnalysisReport", AnalysisReportDto.class);
+ loadAlias(conf, "IdUuidPair", IdUuidPair.class);
// AuthorizationMapper has to be loaded before IssueMapper because this last one used it
loadMapper(conf, "org.sonar.core.user.AuthorizationMapper");
@@ -279,17 +241,6 @@ public class MyBatis implements BatchComponent, ServerComponent {
return new DbSession(queue, session);
}
- public static void closeQuietly(SqlSession session) {
- if (session != null) {
- try {
- session.close();
- } catch (Exception e) {
- LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e);
- // do not re-throw the exception
- }
- }
- }
-
private void loadMappers(Configuration mybatisConf, Class<?>... mapperClasses) {
for (Class mapperClass : mapperClasses) {
loadMapper(mybatisConf, mapperClass);
@@ -325,8 +276,4 @@ public class MyBatis implements BatchComponent, ServerComponent {
private void loadAlias(Configuration conf, String alias, Class dtoClass) {
conf.getTypeAliasRegistry().registerAlias(alias, dtoClass);
}
-
- private static JdbcTransactionFactory createTransactionFactory() {
- return new JdbcTransactionFactory();
- }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPair.java b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPair.java
new file mode 100644
index 00000000000..f19ef88611f
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPair.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.core.purge;
+
+public class IdUuidPair {
+ private Long id;
+ private String uuid;
+
+ public IdUuidPair() {
+ }
+
+ public IdUuidPair(long id, String uuid) {
+ this.id = id;
+ this.uuid = uuid;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public void setUuid(String uuid) {
+ this.uuid = uuid;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPairs.java b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPairs.java
new file mode 100644
index 00000000000..1ad2939d073
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/purge/IdUuidPairs.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.core.purge;
+
+import com.google.common.collect.Lists;
+
+import java.util.List;
+
+public class IdUuidPairs {
+ private IdUuidPairs() {
+ }
+
+ public static List<Long> ids(List<IdUuidPair> pairs) {
+ List<Long> ids = Lists.newArrayList();
+
+ for (IdUuidPair idUuidPair : pairs) {
+ ids.add(idUuidPair.getId());
+ }
+
+ return ids;
+ }
+
+ public static List<String> uuids(List<IdUuidPair> idUuidPairList) {
+ List<String> uuids = Lists.newArrayList();
+
+ for (IdUuidPair idUuidPair : idUuidPairList) {
+ uuids.add(idUuidPair.getUuid());
+ }
+
+ return uuids;
+ }
+}
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java
index 3a4e0ac18e6..a68c3fa58ce 100644
--- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java
+++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java
@@ -279,4 +279,10 @@ class PurgeCommands {
profiler.stop();
}
+ public void deleteFileSources(String rootUuid) {
+ profiler.start("deleteFileSources (file_sources)");
+ purgeMapper.deleteFileSourcesByProjectUuid(rootUuid);
+ session.commit();
+ profiler.stop();
+ }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
index a7bde27f95e..c43f3df6d93 100644
--- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeDao.java
@@ -41,11 +41,11 @@ import java.util.List;
* @since 2.14
*/
public class PurgeDao {
+ private static final Logger LOG = LoggerFactory.getLogger(PurgeDao.class);
private final MyBatis mybatis;
private final ResourceDao resourceDao;
- private static final Logger LOG = LoggerFactory.getLogger(PurgeDao.class);
- private PurgeProfiler profiler;
private final System2 system2;
+ private PurgeProfiler profiler;
public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, PurgeProfiler profiler, System2 system2) {
this.mybatis = mybatis;
@@ -134,9 +134,9 @@ public class PurgeDao {
session.select("org.sonar.core.purge.PurgeMapper.selectResourceIdsToDisable", project.getId(), new ResultHandler() {
@Override
public void handleResult(ResultContext resultContext) {
- Long resourceId = (Long) resultContext.getResultObject();
- if (resourceId != null) {
- disableResource(resourceId, purgeMapper);
+ IdUuidPair resourceIdUuid = (IdUuidPair) resultContext.getResultObject();
+ if (resourceIdUuid.getId() != null) {
+ disableResource(resourceIdUuid, purgeMapper);
}
}
});
@@ -162,17 +162,22 @@ public class PurgeDao {
return result;
}
- public PurgeDao deleteResourceTree(long rootProjectId) {
+ public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid) {
final DbSession session = mybatis.openSession(true);
final PurgeMapper mapper = session.getMapper(PurgeMapper.class);
try {
- deleteProject(rootProjectId, mapper, new PurgeCommands(session, profiler));
+ deleteProject(rootIdUuid.getId(), mapper, new PurgeCommands(session, profiler));
+ deleteFileSources(rootIdUuid.getUuid(), new PurgeCommands(session, profiler));
return this;
} finally {
MyBatis.closeQuietly(session);
}
}
+ private void deleteFileSources(String rootUuid, PurgeCommands commands) {
+ commands.deleteFileSources(rootUuid);
+ }
+
private void deleteProject(long rootProjectId, PurgeMapper mapper, PurgeCommands commands) {
List<Long> childrenIds = mapper.selectProjectIdsByRootId(rootProjectId);
for (Long childId : childrenIds) {
@@ -183,9 +188,11 @@ public class PurgeDao {
commands.deleteResources(resourceIds);
}
- private void disableResource(long resourceId, PurgeMapper mapper) {
+ private void disableResource(IdUuidPair resourceIdUuid, PurgeMapper mapper) {
+ long resourceId = resourceIdUuid.getId();
mapper.deleteResourceIndex(Arrays.asList(resourceId));
mapper.setSnapshotIsLastToFalse(resourceId);
+ mapper.deleteFileSourcesByUuid(resourceIdUuid.getUuid());
mapper.disableResource(resourceId);
mapper.resolveResourceIssuesNotAlreadyResolved(resourceId, new Date(system2.now()));
}
diff --git a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
index b3c26d95a07..f498b122496 100644
--- a/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
@@ -103,4 +103,8 @@ public interface PurgeMapper {
void deleteOldClosedIssueChanges(@Param("rootProjectId") long rootProjectId, @Nullable @Param("toDate") Date toDate);
void deleteOldClosedIssues(@Param("rootProjectId") long rootProjectId, @Nullable @Param("toDate") Date toDate);
+
+ void deleteFileSourcesByProjectUuid(String rootProjectUuid);
+
+ void deleteFileSourcesByUuid(String fileUuid);
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
index a7a82c75d0a..c0173090485 100644
--- a/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
@@ -47,7 +47,7 @@
</if>
</where>
</select>
-
+
<select id="selectSnapshotIdsByResource" parameterType="map" resultType="long">
select s.id from snapshots s
<where>
@@ -72,8 +72,8 @@
not exists(select e.id from events e where e.snapshot_id=s.id)
</select>
- <select id="selectResourceIdsToDisable" resultType="long" parameterType="long">
- select p.id from projects p
+ <select id="selectResourceIdsToDisable" resultType="IdUuidPair" parameterType="long">
+ select p.id, p.uuid from projects p
where (p.id=#{id} or p.root_id=#{id}) and p.enabled=${_true}
and not exists(select s.project_id from snapshots s where s.islast=${_true} and s.project_id=p.id)
</select>
@@ -93,28 +93,28 @@
<delete id="deleteSnapshotMeasures" parameterType="map">
delete from project_measures where snapshot_id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
<delete id="deleteSnapshotSource" parameterType="map">
delete from snapshot_sources where snapshot_id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
<delete id="deleteSnapshotGraphs" parameterType="map">
delete from graphs where snapshot_id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
<delete id="deleteSnapshotDependenciesFromSnapshotId" parameterType="map">
delete from dependencies where from_snapshot_id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
@@ -135,36 +135,37 @@
<delete id="deleteSnapshotDuplications" parameterType="map">
delete from duplications_index where snapshot_id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
<delete id="deleteSnapshotEvents" parameterType="map">
delete from events where snapshot_id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
<delete id="deleteSnapshot" parameterType="map">
delete from snapshots where id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
<delete id="deleteSnapshotWastedMeasures" parameterType="map">
delete from project_measures
<where>
- snapshot_id in
- <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
+ snapshot_id in
+ <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
#{snapshotId}
- </foreach>
- and (rule_id is not null or person_id is not null
- <if test="mids.size()>0">
- or metric_id in
- <foreach item="mid" index="index" collection="mids" open="(" separator="," close=")">#{mid}</foreach>
- </if>)
+ </foreach>
+ and (rule_id is not null or person_id is not null
+ <if test="mids.size()>0">
+ or metric_id in
+ <foreach item="mid" index="index" collection="mids" open="(" separator="," close=")">#{mid}</foreach>
+ </if>
+ )
</where>
</delete>
@@ -177,7 +178,8 @@
</update>
<update id="resolveResourceIssuesNotAlreadyResolved" parameterType="map">
- UPDATE issues SET status='CLOSED',resolution='REMOVED',updated_at=#{date},issue_close_date=#{date}, issue_update_date=#{date}
+ UPDATE issues SET status='CLOSED',resolution='REMOVED',updated_at=#{date},issue_close_date=#{date},
+ issue_update_date=#{date}
WHERE component_id=#{resourceId} AND resolution IS NULL
</update>
@@ -272,16 +274,16 @@
<delete id="deleteSnapshotData" parameterType="map">
delete from snapshot_data where snapshot_id in
<foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
- #{snapshotId}
+ #{snapshotId}
</foreach>
</delete>
<delete id="deleteResourceIssueChanges" parameterType="map">
delete from issue_changes ic
where exists (select * from issues i where i.kee=ic.issue_key and i.component_id in
- <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=",">
- #{resourceId}
- </foreach>
+ <foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=",">
+ #{resourceId}
+ </foreach>
)
</delete>
@@ -310,6 +312,13 @@
</foreach>
</delete>
+ <delete id="deleteFileSourcesByProjectUuid">
+ delete from file_sources where project_uuid=#{rootProjectUuid}
+ </delete>
+
+ <delete id="deleteFileSourcesByUuid">
+ delete from file_sources where file_uuid=#{fileUuid}
+ </delete>
<delete id="deleteOldClosedIssueChanges" parameterType="map">
delete from issue_changes ic
diff --git a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java
index 5871fb71761..c03d4ada988 100644
--- a/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/computation/dbcleaner/DefaultPurgeTaskTest.java
@@ -30,6 +30,7 @@ import org.sonar.api.config.Settings;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
import org.sonar.core.computation.dbcleaner.period.DefaultPeriodCleaner;
+import org.sonar.core.purge.IdUuidPair;
import org.sonar.core.purge.PurgeConfiguration;
import org.sonar.core.purge.PurgeDao;
import org.sonar.core.purge.PurgeProfiler;
@@ -139,8 +140,10 @@ public class DefaultPurgeTaskTest {
@Test
public void call_dao_delete_when_deleting() throws Exception {
+ when(resourceDao.getResource(123L)).thenReturn(new ResourceDto().setId(123L).setUuid("A"));
+
sut.delete(123L);
- verify(purgeDao, times(1)).deleteResourceTree(123L);
+ verify(purgeDao, times(1)).deleteResourceTree(any(IdUuidPair.class));
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/purge/IdUuidPairsTest.java b/sonar-core/src/test/java/org/sonar/core/purge/IdUuidPairsTest.java
new file mode 100644
index 00000000000..5fc436735b2
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/purge/IdUuidPairsTest.java
@@ -0,0 +1,48 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.core.purge;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+public class IdUuidPairsTest {
+ @Test
+ public void extract_ids() throws Exception {
+ List<IdUuidPair> idUuidPairList = Lists.newArrayList(new IdUuidPair(1L, "ABCD"), new IdUuidPair(2L, "EFGH"));
+
+ List<Long> ids = IdUuidPairs.ids(idUuidPairList);
+
+ assertThat(ids).containsOnly(1L, 2L);
+ }
+
+ @Test
+ public void extract_uuids() {
+ List<IdUuidPair> idUuidPairList = Lists.newArrayList(new IdUuidPair(1L, "ABCD"), new IdUuidPair(2L, "EFGH"));
+
+ List<String> uuids = IdUuidPairs.uuids(idUuidPairList);
+
+ assertThat(uuids).containsOnly("ABCD", "EFGH");
+ }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java
index fd598dfd8bd..e0bc253992d 100644
--- a/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/purge/PurgeDaoTest.java
@@ -39,6 +39,15 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
PurgeDao dao;
+ private static PurgeableSnapshotDto getById(List<PurgeableSnapshotDto> snapshots, long id) {
+ for (PurgeableSnapshotDto snapshot : snapshots) {
+ if (snapshot.getSnapshotId() == id) {
+ return snapshot;
+ }
+ }
+ return null;
+ }
+
@Before
public void createDao() {
system2 = mock(System2.class);
@@ -55,13 +64,20 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
}
@Test
- public void shouldPurgeProject() {
+ public void should_purge_project() {
setupData("shouldPurgeProject");
dao.purge(new PurgeConfiguration(1L, new String[0], 30));
checkTables("shouldPurgeProject", "projects", "snapshots");
}
@Test
+ public void delete_file_sources_of_disabled_resources() {
+ setupData("delete_file_sources_of_disabled_resources");
+ dao.purge(new PurgeConfiguration(1L, new String[0], 30, system2));
+ checkTables("delete_file_sources_of_disabled_resources", "file_sources");
+ }
+
+ @Test
public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() {
setupData("shouldDeleteHistoricalDataOfDirectoriesAndFiles");
dao.purge(new PurgeConfiguration(1L, new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30));
@@ -96,20 +112,11 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
assertThat(getById(snapshots, 5L).hasEvents()).isTrue();
}
- private static PurgeableSnapshotDto getById(List<PurgeableSnapshotDto> snapshots, long id) {
- for (PurgeableSnapshotDto snapshot : snapshots) {
- if (snapshot.getSnapshotId() == id) {
- return snapshot;
- }
- }
- return null;
- }
-
@Test
- public void shouldDeleteProject() {
+ public void should_delete_project_and_associated_data() {
setupData("shouldDeleteProject");
- dao.deleteResourceTree(1L);
- assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes");
+ dao.deleteResourceTree(new IdUuidPair(1L, "A"));
+ assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes", "file_sources");
}
@Test
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml
new file mode 100644
index 00000000000..c6eb7974211
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <file_sources id="2" project_uuid="ABCD" file_uuid="KLMN" data="[null]" line_hashes="[null]" data_hash="321654988"
+ created_at="123456789" updated_at="123456789"/>
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml
new file mode 100644
index 00000000000..c461e9d5a40
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/delete_file_sources_of_disabled_resources.xml
@@ -0,0 +1,79 @@
+<dataset>
+
+ <!-- the project -->
+ <projects id="1" enabled="[true]" root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]"
+ module_uuid_path="[null]" created_at="[null]"
+ long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]"
+ deprecated_kee="[null]" authorization_updated_at="[null]"/>
+
+ <!-- the directory -->
+ <projects id="2" enabled="[true]" root_id="1" uuid="EFGH" project_uuid="ABCD" module_uuid="ABCD"
+ module_uuid_path="[null]" created_at="[null]"
+ long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]"
+ deprecated_kee="[null]" authorization_updated_at="[null]"/>
+
+ <!-- the files -->
+ <projects id="3" enabled="[true]" root_id="1" uuid="GHIJ" project_uuid="ABCD" module_uuid="ABCD"
+ module_uuid_path="ABCD" created_at="[null]"
+ long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]"
+ deprecated_kee="[null]" authorization_updated_at="[null]"/>
+ <projects id="4" enabled="[true]" root_id="1" uuid="KLMN" project_uuid="ABCD" module_uuid="ABCD"
+ module_uuid_path="ABCD" created_at="[null]"
+ long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/DeletedFile.java"
+ name="my/dir/DeletedFile.java"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]"
+ deprecated_kee="[null]" authorization_updated_at="[null]"/>
+
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[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="2008-12-02 13:58:00.00"
+ build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <snapshots id="2"
+ project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00"
+ build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <snapshots id="3"
+ project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00"
+ build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <!-- isLast is true, don't want to delete associated source lines -->
+ <snapshots id="4"
+ project_id="4" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ 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="2008-12-02 13:58:00.00"
+ build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <file_sources id="1" project_uuid="ABCD" file_uuid="GHIJ" data="[null]" line_hashes="[null]" data_hash="321654987"
+ created_at="123456789" updated_at="123456789"/>
+ <file_sources id="2" project_uuid="ABCD" file_uuid="KLMN" data="[null]" line_hashes="[null]" data_hash="321654988"
+ created_at="123456789" updated_at="123456789"/>
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml
index 34b5391a7c2..91e1c3c1c58 100644
--- a/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/purge/PurgeDaoTest/shouldDeleteProject.xml
@@ -4,7 +4,8 @@
<projects id="1" enabled="[true]" root_id="[null]"
uuid="A" project_uuid="A" module_uuid="[null]" module_uuid_path="[null]"
long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"
+ authorization_updated_at="[null]"/>
<snapshots id="1" project_id="1" parent_snapshot_id="[null]" root_project_id="[null]" root_snapshot_id="[null]"
status="P" islast="[false]" purge_status="[null]"
@@ -18,7 +19,7 @@
version="[null]" path="[null]"/>
<action_plans id="1" kee="ABCD" project_id="1" name="SHORT_TERM" description="[null]" deadline="[null]"
- user_login="igor" status="[null]" created_at="[null]" updated_at="[null]" />
+ user_login="igor" status="[null]" created_at="[null]" updated_at="[null]"/>
<issues id="1" kee="ABCDE" component_id="1" status="CLOSED" resolution="[null]" line="200" severity="BLOCKER"
reporter="perceval" assignee="arthur" rule_id="500"
@@ -44,13 +45,15 @@
issue_close_date="2013-04-16"
/>
- <issue_changes id="1" kee="[null]" issue_key="ABCDF" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc"/>
+ <issue_changes id="1" kee="[null]" issue_key="ABCDF" created_at="[null]" updated_at="[null]" user_login="admin"
+ change_type="comment" change_data="abc"/>
<!-- modules -->
<projects id="2" enabled="[true]" root_id="1"
uuid="B" project_uuid="A" module_uuid="A" module_uuid_path="A"
long_name="[null]" scope="PRJ" qualifier="BRC" kee="module1" name="module1"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"
+ authorization_updated_at="[null]"/>
<snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
status="P" islast="[false]" purge_status="[null]"
@@ -67,7 +70,8 @@
<projects id="3" enabled="[false]" root_id="1"
uuid="C" project_uuid="A" module_uuid="A" module_uuid_path="A"
long_name="[null]" scope="PRJ" qualifier="BRC" kee="module2" name="module2"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"
+ authorization_updated_at="[null]"/>
<snapshots id="3" project_id="3" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
status="P" islast="[true]" purge_status="[null]"
@@ -84,7 +88,8 @@
<projects id="4" enabled="[false]" root_id="3"
uuid="D" project_uuid="A" module_uuid="C" module_uuid_path="A.C"
long_name="[null]" scope="FIL" qualifier="FIL" kee="module2:File.java" name="File"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"
+ authorization_updated_at="[null]"/>
<snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1"
status="P" islast="[true]" purge_status="[null]"
@@ -96,4 +101,6 @@
depth="[null]" scope="FIL" qualifier="FIL" created_at="2008-12-02 13:58:00.00"
build_date="2008-12-02 13:58:00.00"
version="[null]" path="[null]"/>
+ <file_sources id="1" project_uuid="A" file_uuid="D" data="[null]" line_hashes="[null]" data_hash="321654987"
+ created_at="123456789" updated_at="123456789"/>
</dataset>