]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4461 Displaying more than 2000 issues in the Issues code viewer fail on SQL...
authorJulien Lancelot <julien.lancelot@gmail.com>
Mon, 1 Jul 2013 09:37:55 +0000 (11:37 +0200)
committerJulien Lancelot <julien.lancelot@gmail.com>
Tue, 2 Jul 2013 11:21:41 +0000 (13:21 +0200)
15 files changed:
sonar-core/src/main/java/org/sonar/core/issue/db/ActionPlanDao.java
sonar-core/src/main/java/org/sonar/core/issue/db/ActionPlanMapper.java
sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeDao.java
sonar-core/src/main/java/org/sonar/core/issue/db/IssueChangeMapper.java
sonar-core/src/main/java/org/sonar/core/issue/db/IssueDao.java
sonar-core/src/main/java/org/sonar/core/resource/ResourceDao.java
sonar-core/src/main/java/org/sonar/core/resource/ResourceMapper.java
sonar-core/src/main/resources/org/sonar/core/issue/db/ActionPlanMapper.xml
sonar-core/src/main/resources/org/sonar/core/issue/db/IssueChangeMapper.xml
sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml
sonar-core/src/main/resources/org/sonar/core/resource/ResourceMapper.xml
sonar-core/src/test/java/org/sonar/core/issue/db/ActionPlanDaoTest.java
sonar-core/src/test/java/org/sonar/core/issue/db/IssueChangeDaoTest.java
sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java
sonar-core/src/test/java/org/sonar/core/resource/ResourceDaoTest.java

index 5e00190c152490f0c5023a5e9aadb1fa8d105dfb..1cd9ca14c572882902439c5d57fbc54c12c1085b 100644 (file)
@@ -88,8 +88,13 @@ public class ActionPlanDao implements BatchComponent, ServerComponent {
     }
     SqlSession session = mybatis.openSession();
     try {
+      List<ActionPlanDto> dtosList = newArrayList();
       List<List<String>> keysPartition = Lists.partition(newArrayList(keys), 1000);
-      return session.getMapper(ActionPlanMapper.class).findByKeys(keysPartition);
+      for (List<String> partition : keysPartition) {
+        List<ActionPlanDto> dtos = session.getMapper(ActionPlanMapper.class).findByKeys(partition);
+        dtosList.addAll(dtos);
+      }
+      return dtosList;      
     } finally {
       MyBatis.closeQuietly(session);
     }
index 4ea956c9a9a5f907dc53b3c10471a2298f40e373..7af6718c9a46f74e9704a3acf56c1227bb836e12 100644 (file)
@@ -35,7 +35,7 @@ public interface ActionPlanMapper {
 
   void delete(@Param("key") String key);
 
-  List<ActionPlanDto> findByKeys(@Param("keys") List<List<String>> keys);
+  List<ActionPlanDto> findByKeys(@Param("keys") List<String> keys);
 
   ActionPlanDto findByKey(@Param("key") String key);
 
index cf9e5c6a67853f74f97bd1da64bdf3a011a95748..8b5087caccd9eb7bc17253c6b7335db31d6d1419 100644 (file)
@@ -87,9 +87,13 @@ public class IssueChangeDao implements BatchComponent, ServerComponent {
       return Collections.emptyList();
     }
     IssueChangeMapper mapper = session.getMapper(IssueChangeMapper.class);
-
+    List<IssueChangeDto> dtosList = newArrayList();
     List<List<String>> keysPartition = Lists.partition(newArrayList(issueKeys), 1000);
-    return mapper.selectByIssuesAndType(keysPartition, changeType);
+    for (List<String> partition : keysPartition) {
+      List<IssueChangeDto> dtos = mapper.selectByIssuesAndType(partition, changeType);
+      dtosList.addAll(dtos);
+    }
+    return dtosList;
   }
 
   public boolean delete(String key) {
index edb57a03bcd8f803b65cf1c30a5c02c42aaea1e3..91a05b8854c0568bd25a657a41bf98d6779d3466 100644 (file)
@@ -43,7 +43,7 @@ public interface IssueChangeMapper {
   /**
    * Issue changes by chronological date of creation
    */
-  List<IssueChangeDto> selectByIssuesAndType(@Param("issueKeys") List<List<String>> issueKeys,
+  List<IssueChangeDto> selectByIssuesAndType(@Param("issueKeys") List<String> issueKeys,
                                              @Param("changeType") String changeType);
 
   List<IssueChangeDto> selectByIssue(String issueKey);
index 1fa8b6d024c5be5bf92aa77e4566375e5c50d107..928e84317fd5cddbcef3ec95b5c9e023490b0734 100644 (file)
@@ -35,10 +35,8 @@ import javax.annotation.Nullable;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Maps.newHashMap;
 
 /**
  * @since 3.6
@@ -101,25 +99,21 @@ public class IssueDao implements BatchComponent, ServerComponent {
 
   private List<IssueDto> selectIssueIds(IssueQuery query, @Nullable Integer userId, Integer maxResults, SqlSession session){
     IssueMapper mapper = session.getMapper(IssueMapper.class);
-    return mapper.selectIssues(query, query.componentRoots(), userId, query.requiredRole(), maxResults, true);
+    return mapper.selectIssueIds(query, query.componentRoots(), userId, query.requiredRole(), maxResults);
   }
 
   public List<IssueDto> selectIssues(IssueQuery query) {
     SqlSession session = mybatis.openSession();
     try {
-      return selectIssues(query, null, Integer.MAX_VALUE, session);
+      return selectIssues(query, null, session);
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
   public List<IssueDto> selectIssues(IssueQuery query, @Nullable Integer userId, SqlSession session){
-    return selectIssues(query, userId, query.maxResults(), session);
-  }
-
-  public List<IssueDto> selectIssues(IssueQuery query, @Nullable Integer userId, Integer maxResults, SqlSession session){
     IssueMapper mapper = session.getMapper(IssueMapper.class);
-    return mapper.selectIssues(query, query.componentRoots(), userId, query.requiredRole(), maxResults, false);
+    return mapper.selectIssues(query, query.componentRoots(), userId, query.requiredRole());
   }
 
   @VisibleForTesting
@@ -136,9 +130,12 @@ public class IssueDao implements BatchComponent, ServerComponent {
     if (ids.isEmpty()) {
       return Collections.emptyList();
     }
-    Object idsPartition = Lists.partition(newArrayList(ids), 1000);
-    Map<String, Object> params = newHashMap();
-    params.put("ids", idsPartition);
-    return session.selectList("org.sonar.core.issue.db.IssueMapper.selectByIds", params);
+    List<IssueDto> dtosList = newArrayList();
+    List<List<Long>> idsPartitionList = Lists.partition(newArrayList(ids), 1000);
+    for (List<Long> idsPartition : idsPartitionList) {
+      List<IssueDto> dtos = session.selectList("org.sonar.core.issue.db.IssueMapper.selectByIds", newArrayList(idsPartition));
+      dtosList.addAll(dtos);
+    }
+    return dtosList;
   }
 }
index bcb7514322d25e60aacfe57c23ebe955976322da..09c7e993a4f71d19455924a100b06566a1e35d37 100644 (file)
@@ -143,8 +143,14 @@ public class ResourceDao {
     }
     SqlSession session = mybatis.openSession();
     try {
+
+      List<ResourceDto> resources = newArrayList();
       List <List<Long>> idsPartition = Lists.partition(newArrayList(ids), 1000);
-      Collection<ResourceDto> resources =  session.getMapper(ResourceMapper.class).selectResourcesById(idsPartition);
+      for (List<Long> partition : idsPartition) {
+        List<ResourceDto> dtos = session.getMapper(ResourceMapper.class).selectResourcesById(partition);
+        resources.addAll(dtos);
+      }
+
       Collection<Component> components = newArrayList();
       for (ResourceDto resourceDto : resources) {
         components.add(toComponent(resourceDto));
index ea89cbfac58e5dd17785a63cc274d3f69d1d8445..2632a0d19291457ba72759b645c3c10a73eb122e 100644 (file)
@@ -56,7 +56,7 @@ public interface ResourceMapper {
   /**
    * @since3.6
    */
-  List<ResourceDto> selectResourcesById(@Param("ids") List <List<Long>> ids);
+  List<ResourceDto> selectResourcesById(@Param("ids") List<Long> ids);
 
   /**
    * @since 3.6
index 663284e21ac89f8bcbfd7c0bcfe14e751b2139d0..590b3147086414b33c4ec1e3bced69146e116a36 100644 (file)
     select <include refid="actionPlanColumns"/>
     from action_plans ap, projects p
     <where>
-      <foreach collection="keys" open="ap.kee in (" close=")" item="list" separator=") or ap.kee in (" >
-        <foreach collection="list" item="element" separator=",">
-          #{element}
-        </foreach>
+      and ap.kee in
+      <foreach collection="keys" open="(" close=")" item="key" separator=",">
+        #{key}
       </foreach>
       and ap.project_id=p.id
     </where>
index d9d778458a0b9bd2eeee0cff57683ad1b88e4da3..7afcc6e1ed45210e8436e9df8e3a24e623f6d94a 100644 (file)
     select
     <include refid="issueChangeColumns"/>
     from issue_changes c
-    where c.change_type=#{changeType} and (
-    <foreach collection="issueKeys" open="c.issue_key in (" close=")" item="list" separator=") or c.issue_key in (">
-      <foreach collection="list" item="element" separator=",">
-        #{element}
-      </foreach>
-    </foreach>)
+    where c.change_type=#{changeType} and c.issue_key in
+    <foreach collection="issueKeys" open="(" close=")" item="key" separator=",">
+      #{key}
+    </foreach>
     order by c.created_at
   </select>
 
index f407ec3289a20654de0b98c12b1f043abe2a28dd..fdd87b94a1e69ad5b80cad4bb56406681a9dc1ff 100644 (file)
     inner join projects p on p.id=i.component_id
     inner join projects root on root.id=i.root_component_id
     <where>
-      and
-      <foreach collection="ids" open="i.id in (" close=")" item="list" separator=") or i.id in (">
-        <foreach collection="list" item="element" separator=",">
-          #{element}
-        </foreach>
+      and i.id in
+      <foreach collection="list" open="(" close=")" item="id" separator=",">
+        #{id}
       </foreach>
     </where>
   </select>
index 394c9d56b734aa43c270801a3e69ae03d9b03d7c..c376df909d48f3b6322a031c191bca570b082211 100644 (file)
   </select>
 
   <select id="selectResourcesById" parameterType="map" resultMap="resourceResultMap">
-    select * from projects p where p.enabled=${_true} and
-    <foreach collection="ids" open="p.id in (" close=")" item="list" separator=") or p.id in (" >
-      <foreach collection="list" item="element" separator=",">
-        #{element}
-      </foreach>
+    select * from projects p where p.enabled=${_true}
+    and p.id in
+    <foreach collection="ids" open="(" close=")" item="key" separator=",">
+      #{key}
     </foreach>
 
   </select>
index aba46152c5423b102e79c96886e9eb35f7ae6a84..df72ee82542e26432502780bfe49bea1a0ac2fd6 100644 (file)
 
 package org.sonar.core.issue.db;
 
+import org.apache.ibatis.session.SqlSession;
 import org.junit.Before;
 import org.junit.Test;
 import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.persistence.MyBatis;
 
 import java.util.Collection;
+import java.util.List;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
@@ -86,6 +89,22 @@ public class ActionPlanDaoTest extends AbstractDaoTestCase {
     assertThat(result).hasSize(3);
   }
 
+  @Test
+  public void should_find_by_keys_on_huge_number_of_keys() {
+    setupData("shared");
+
+    SqlSession session = getMyBatis().openSession();
+    List<String> hugeNbOKeys = newArrayList();
+    for (int i=0; i<4500; i++) {
+      hugeNbOKeys.add("ABCD" + i);
+    }
+    List<ActionPlanDto> result = dao.findByKeys(hugeNbOKeys);
+    MyBatis.closeQuietly(session);
+
+    // The goal of this test is only to check that the query do no fail, not to check the number of results
+    assertThat(result).isEmpty();
+  }
+
   @Test
   public void should_find_open_by_project_id() {
     setupData("shared", "should_find_open_by_project_id");
index 95e524dfe4008d71d5efd064ba5915cf19480b2b..180684a170da7aa212bc035647b88bfcba60f613 100644 (file)
@@ -71,7 +71,7 @@ public class IssueChangeDaoTest extends AbstractDaoTestCase {
 
     SqlSession session = getMyBatis().openSession();
     List<String> hugeNbOfIssues = newArrayList();
-    for (int i=0; i<1500; i++) {
+    for (int i=0; i<4500; i++) {
       hugeNbOfIssues.add("ABCD"+i);
     }
     List<DefaultIssueComment> comments = dao.selectCommentsByIssues(session, hugeNbOfIssues);
index 180725f7150f43a98e10f284f9fab7b30bee6fed..69ac592d896742a4d920944e9bad386d0ef4164d 100644 (file)
@@ -322,7 +322,7 @@ public class IssueDaoTest extends AbstractDaoTestCase {
     setupData("shared");
 
     List<Long> hugeNbOfIssues = newArrayList();
-    for (long i=0; i<1500; i++) {
+    for (long i=0; i<4500; i++) {
       hugeNbOfIssues.add(i);
     }
     List<IssueDto> results = dao.selectByIds(hugeNbOfIssues);
index 94e9978f2f4cad408d4dddf09450ba2e0933dc75..1855d41a178750bdaa6ed247b7c3fd647886d587 100644 (file)
@@ -161,6 +161,20 @@ public class ResourceDaoTest extends AbstractDaoTestCase {
     assertThat(component.qualifier()).isNotNull();
   }
 
+  @Test
+  public void should_find_components_by_resource_ids_on_huge_number_of_ids() {
+    setupData("fixture");
+
+    List<Long> hugeNbOfIds = newArrayList();
+    for (long i=0; i<4500; i++) {
+      hugeNbOfIds.add(i);
+    }
+    Collection<Component> results = dao.findByIds(hugeNbOfIds);
+
+    // The goal of this test is only to check that the query do no fail, not to check the number of results
+    assertThat(results).isNotNull();
+  }
+
   @Test
   public void should_find_root_project_by_component_key() {
     setupData("fixture");