]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4586 SonarQube purge on MSSQL can fail with the following error : "Prepared...
authorJulien Lancelot <julien.lancelot@gmail.com>
Fri, 23 Aug 2013 10:05:14 +0000 (12:05 +0200)
committerJulien Lancelot <julien.lancelot@gmail.com>
Fri, 23 Aug 2013 10:05:14 +0000 (12:05 +0200)
sonar-core/src/main/java/org/sonar/core/purge/PurgeCommands.java
sonar-core/src/main/java/org/sonar/core/purge/PurgeMapper.java
sonar-core/src/main/resources/org/sonar/core/purge/PurgeMapper.xml
sonar-core/src/test/java/org/sonar/core/purge/PurgeCommandsTest.java

index e37b0fef7047ac8cfb1b22fb8f0d9d1b6c7e9a35..38a07064e4915abf259bac66ef0108495e5ff49c 100644 (file)
@@ -158,7 +158,8 @@ class PurgeCommands {
     deleteSnapshots(purgeMapper.selectSnapshotIds(query));
   }
 
-  private void deleteSnapshots(final List<Long> snapshotIds) {
+  @VisibleForTesting
+  protected void deleteSnapshots(final List<Long> snapshotIds) {
 
     List<List<Long>> snapshotIdsPartition = Lists.partition(snapshotIds, MAX_SNAPSHOTS_PER_QUERY);
 
@@ -205,7 +206,8 @@ class PurgeCommands {
     purgeSnapshots(purgeMapper.selectSnapshotIds(query));
   }
 
-  private void purgeSnapshots(final List<Long> snapshotIds) {
+  @VisibleForTesting
+  protected void purgeSnapshots(final List<Long> snapshotIds) {
     // note that events are not deleted
     List<List<Long>> snapshotIdsPartition = Lists.partition(snapshotIds, MAX_SNAPSHOTS_PER_QUERY);
 
@@ -289,7 +291,11 @@ class PurgeCommands {
   private void deleteSnapshotDependencies(final List<List<Long>> snapshotIdsPartition) {
     profiler.start("deleteSnapshotDependencies (dependencies)");
     for (List<Long> partSnapshotIds : snapshotIdsPartition) {
-      purgeMapper.deleteSnapshotDependencies(partSnapshotIds);
+      // SONAR-4586
+      // On MsSQL, the maximum number of parameters allowed in a query is 2000, so we have to execute 3 queries instead of one with 3 or inside
+      purgeMapper.deleteSnapshotDependenciesFromSnapshotId(partSnapshotIds);
+      purgeMapper.deleteSnapshotDependenciesToSnapshotId(partSnapshotIds);
+      purgeMapper.deleteSnapshotDependenciesProjectSnapshotId(partSnapshotIds);
     }
     session.commit();
     profiler.stop();
index d7e3c2d034fac515625a712919a918670fc1a12c..da7a6b20c9629f9571df709fc7f5e215841010de 100644 (file)
@@ -36,7 +36,11 @@ public interface PurgeMapper {
 
   void deleteSnapshot(@Param("snapshotIds") List<Long> snapshotIds);
 
-  void deleteSnapshotDependencies(@Param("snapshotIds") List<Long> snapshotIds);
+  void deleteSnapshotDependenciesFromSnapshotId(@Param("snapshotIds") List<Long> snapshotIds);
+
+  void deleteSnapshotDependenciesToSnapshotId(@Param("snapshotIds") List<Long> snapshotIds);
+
+  void deleteSnapshotDependenciesProjectSnapshotId(@Param("snapshotIds") List<Long> snapshotIds);
 
   void deleteSnapshotDuplications(@Param("snapshotIds") List<Long> snapshotIds);
 
index ae75f3c77d6128a7125192c5b8699ab2026ca8d8..2501ff8bd0d6112b4c5decf25fbfb444c068ead1 100644 (file)
     </foreach>
   </delete>
 
-  <delete id="deleteSnapshotDependencies" parameterType="map">
+  <delete id="deleteSnapshotDependenciesFromSnapshotId" parameterType="map">
     delete from dependencies where from_snapshot_id in
     <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
         #{snapshotId}
     </foreach>
-    or to_snapshot_id in
+  </delete>
+
+  <delete id="deleteSnapshotDependenciesToSnapshotId" parameterType="map">
+    delete from dependencies where to_snapshot_id in
     <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
-        #{snapshotId}
+      #{snapshotId}
     </foreach>
-    or project_snapshot_id in
+  </delete>
+
+  <delete id="deleteSnapshotDependenciesProjectSnapshotId" parameterType="map">
+    delete from dependencies where project_snapshot_id in
     <foreach collection="snapshotIds" open="(" close=")" item="snapshotId" separator=",">
-        #{snapshotId}
+      #{snapshotId}
     </foreach>
   </delete>
 
index 1f4ec0a07ca56818107af4bf74187f35d0e13460..de1f6b5d4c6d9ca529ff80c63f9fe799bc68dcb6 100644 (file)
@@ -26,6 +26,9 @@ import org.sonar.core.persistence.AbstractDaoTestCase;
 import org.sonar.core.persistence.MyBatis;
 
 import java.util.Arrays;
+import java.util.List;
+
+import static com.google.common.collect.Lists.newArrayList;
 
 public class PurgeCommandsTest extends AbstractDaoTestCase {
 
@@ -53,6 +56,20 @@ public class PurgeCommandsTest extends AbstractDaoTestCase {
         "snapshots", "project_measures", "measure_data", "snapshot_sources", "duplications_index", "events", "dependencies", "snapshot_data");
   }
 
+  /**
+   * Test that SQL queries execution do not fail with a huge number of parameter
+   */
+  @Test
+  public void should_not_fail_when_deleting_huge_number_of_snapshots() {
+    SqlSession session = getMyBatis().openSession();
+    try {
+      new PurgeCommands(session, profiler).deleteSnapshots(getHugeNumberOfIds());
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+    // The goal of this test is only to check that the query do no fail, not to check result
+  }
+
   /**
    * Test that all related data is purged.
    */
@@ -83,6 +100,20 @@ public class PurgeCommandsTest extends AbstractDaoTestCase {
     checkTables("shouldDeleteWastedMeasuresWhenPurgingSnapshot", "project_measures");
   }
 
+  /**
+   * Test that SQL queries execution do not fail with a huge number of parameter
+   */
+  @Test
+  public void should_not_fail_when_purging_huge_number_of_snapshots() {
+    SqlSession session = getMyBatis().openSession();
+    try {
+      new PurgeCommands(session, profiler).purgeSnapshots(getHugeNumberOfIds());
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+    // The goal of this test is only to check that the query do no fail, not to check result
+  }
+
   @Test
   public void shouldDeleteResource() {
     setupData("shouldDeleteResource");
@@ -95,4 +126,26 @@ public class PurgeCommandsTest extends AbstractDaoTestCase {
     assertEmptyTables("projects", "snapshots", "events", "issues", "issue_changes", "authors");
   }
 
+  /**
+   * Test that SQL queries execution do not fail with a huge number of parameter
+   */
+  @Test
+  public void should_not_fail_when_deleting_huge_number_of_resources() {
+    SqlSession session = getMyBatis().openSession();
+    try {
+      new PurgeCommands(session, profiler).deleteResources(getHugeNumberOfIds());
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+    // The goal of this test is only to check that the query do no fail, not to check result
+  }
+
+  private List<Long> getHugeNumberOfIds(){
+    List<Long> hugeNbOfSnapshotIds = newArrayList();
+    for (long i=0; i<4500; i++) {
+      hugeNbOfSnapshotIds.add(i);
+    }
+    return hugeNbOfSnapshotIds;
+  }
+
 }