]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6464 Optimize query that return file source hashes in /batch/project WS
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 4 May 2015 14:41:00 +0000 (16:41 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Mon, 4 May 2015 14:50:33 +0000 (16:50 +0200)
server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java
server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java
server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java
sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java
sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml

index baac3ce42b21bca1b7416aa57bbc1efdb0a609c8..1f463b5a253aeb2ce6ae4ed5710742f62a1d0fb3 100644 (file)
@@ -56,7 +56,11 @@ import org.sonar.server.user.UserSession;
 
 import javax.annotation.Nullable;
 
-import java.util.*;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Maps.newHashMap;
@@ -110,7 +114,10 @@ public class ProjectRepositoryLoader implements ServerComponent {
         TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, modulesTree, modulesTreeSettings, module);
 
         addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.<String, String>newHashMap(), treeModuleSettings, hasScanPerm, session);
-        addFileData(session, ref, modulesTree, module.uuid());
+        List<FilePathWithHashDto> files = module.isRootProject() ?
+          dbClient.componentDao().selectEnabledFilesFromProject(session, module.uuid()) :
+          dbClient.componentDao().selectEnabledDescendantFiles(session, module.uuid());
+        addFileData(session, ref, modulesTree, files);
 
         // FIXME need real value but actually only used to know if there is a previous analysis in local issue tracking mode so any value is
         // ok
@@ -282,13 +289,13 @@ public class ProjectRepositoryLoader implements ServerComponent {
     }
   }
 
-  private void addFileData(DbSession session, ProjectRepositories ref, List<ComponentDto> moduleChildren, String moduleKey) {
+  private void addFileData(DbSession session, ProjectRepositories ref, List<ComponentDto> moduleChildren, List<FilePathWithHashDto> files) {
     Map<String, String> moduleKeysByUuid = newHashMap();
     for (ComponentDto module : moduleChildren) {
       moduleKeysByUuid.put(module.uuid(), module.key());
     }
 
-    for (FilePathWithHashDto file : dbClient.componentDao().selectEnabledDescendantFiles(session, moduleKey)) {
+    for (FilePathWithHashDto file : files) {
       // TODO should query E/S to know if blame is missing on this file
       FileData fileData = new FileData(file.getSrcHash(), true);
       ref.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData);
index 6f41f9280ae159f1bda8a0f0ab5de8d9187fc222..c6cdff23f41dbabd502b65131f6e9aa3a7bff03d 100644 (file)
@@ -107,6 +107,10 @@ public class ComponentDao extends BaseDao<ComponentMapper, ComponentDto, String>
     return mapper(session).selectDescendantFiles(rootComponentUuid, Scopes.FILE, true);
   }
 
+  public List<FilePathWithHashDto> selectEnabledFilesFromProject(DbSession session, String rootComponentUuid) {
+    return mapper(session).selectEnabledFilesFromProject(rootComponentUuid);
+  }
+
   public List<ComponentDto> getByIds(final DbSession session, Collection<Long> ids) {
     return DaoUtils.executeLargeInputs(ids, new Function<List<Long>, List<ComponentDto>>() {
       @Override
index 8c55ee6ce1d7846c08449566bf55c42074e8c159..6f62417470be87319fb0727dd6cfda70f1d5106e 100644 (file)
@@ -383,7 +383,7 @@ public class ComponentDaoTest extends AbstractDaoTestCase {
   }
 
   @Test
-  public void select_enabled_module_files_tree() throws Exception {
+  public void select_enabled_module_files_tree_from_module() throws Exception {
     setupData("select_module_files_tree");
 
     // From root project
@@ -413,6 +413,29 @@ public class ComponentDaoTest extends AbstractDaoTestCase {
     assertThat(dao.selectEnabledDescendantFiles(session, "unknown")).isEmpty();
   }
 
+  @Test
+  public void select_enabled_module_files_tree_from_project() throws Exception {
+    setupData("select_module_files_tree");
+
+    // From root project
+    List<FilePathWithHashDto> files = dao.selectEnabledFilesFromProject(session, "ABCD");
+    assertThat(files).extracting("uuid").containsOnly("EFGHI", "HIJK");
+    assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI");
+    assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK");
+    assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java");
+
+    // From module
+    assertThat(dao.selectEnabledFilesFromProject(session, "EFGH")).isEmpty();
+
+    // From sub module
+    assertThat(dao.selectEnabledFilesFromProject(session, "FGHI")).isEmpty();
+
+    // From directory
+    assertThat(dao.selectEnabledFilesFromProject(session, "GHIJ")).isEmpty();
+
+    assertThat(dao.selectEnabledFilesFromProject(session, "unknown")).isEmpty();
+  }
+
   @Test
   public void insert() {
     when(system2.now()).thenReturn(DateUtils.parseDate("2014-06-18").getTime());
index 648f2a7cf9dd91425c222572348bee81e24aca4b..cfbfb4291b372759cadba7b8850e190d0d5f60be 100644 (file)
@@ -71,13 +71,18 @@ public interface ComponentMapper {
    * Return all descendant modules (including itself) from a given component uuid and scope
    */
   List<ComponentDto> selectDescendantModules(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope,
-                                             @Param(value = "excludeDisabled") boolean excludeDisabled);
+    @Param(value = "excludeDisabled") boolean excludeDisabled);
 
   /**
-   * Return all descendant files from a given component uuid and scope
+   * Return all files from a given project uuid and scope
+   */
+  List<FilePathWithHashDto> selectEnabledFilesFromProject(@Param("projectUuid") String projectUuid);
+
+  /**
+   * Return all descendant files from a given module uuid and scope
    */
   List<FilePathWithHashDto> selectDescendantFiles(@Param("moduleUuid") String moduleUuid, @Param(value = "scope") String scope,
-                                                  @Param(value = "excludeDisabled") boolean excludeDisabled);
+    @Param(value = "excludeDisabled") boolean excludeDisabled);
 
   /**
    * Return uuids and project uuids from list of qualifiers
index 91a3bc460a6bf8ce3cc9986585a11ae8b64b038f..f70496ea9ca49000ba42e1e1a4c0ae4f85d9c931 100644 (file)
   </select>
 
   <sql id="modulesTreeQuery">
-    INNER JOIN projects root_project ON root_project.uuid = p.project_uuid AND root_project.enabled = ${_true}
-    INNER JOIN projects module ON module.project_uuid = root_project.uuid AND module.uuid = #{moduleUuid} AND module.scope='PRJ' AND module.enabled = ${_true}
+    INNER JOIN projects module ON module.project_uuid = p.project_uuid AND module.uuid = #{moduleUuid} AND module.scope='PRJ' AND module.enabled = ${_true}
     <where>
       <if test="excludeDisabled">
         p.enabled = ${_true}
     </where>
   </sql>
 
+  <select id="selectEnabledFilesFromProject" parameterType="map" resultType="FilePathWithHash">
+    SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash
+    FROM projects p
+    INNER JOIN file_sources fs ON fs.file_uuid=p.uuid
+    <where>
+      AND p.project_uuid=#{projectUuid}
+      AND p.enabled=${_true}
+      AND p.scope='FIL'
+    </where>
+  </select>
+
   <select id="selectDescendantFiles" parameterType="map" resultType="FilePathWithHash">
     SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash
     FROM projects p