From: Julien Lancelot Date: Mon, 4 May 2015 14:41:00 +0000 (+0200) Subject: SONAR-6464 Optimize query that return file source hashes in /batch/project WS X-Git-Tag: 5.2-RC1~2071 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=251f4d5bce46fb9b57895e90c86e0e3dfbeb4bba;p=sonarqube.git SONAR-6464 Optimize query that return file source hashes in /batch/project WS --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java index baac3ce42b2..1f463b5a253 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java @@ -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.newHashMap(), treeModuleSettings, hasScanPerm, session); - addFileData(session, ref, modulesTree, module.uuid()); + List 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 moduleChildren, String moduleKey) { + private void addFileData(DbSession session, ProjectRepositories ref, List moduleChildren, List files) { Map 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); diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java index 6f41f9280ae..c6cdff23f41 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java @@ -107,6 +107,10 @@ public class ComponentDao extends BaseDao return mapper(session).selectDescendantFiles(rootComponentUuid, Scopes.FILE, true); } + public List selectEnabledFilesFromProject(DbSession session, String rootComponentUuid) { + return mapper(session).selectEnabledFilesFromProject(rootComponentUuid); + } + public List getByIds(final DbSession session, Collection ids) { return DaoUtils.executeLargeInputs(ids, new Function, List>() { @Override diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java index 8c55ee6ce1d..6f62417470b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java @@ -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 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()); diff --git a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java index 648f2a7cf9d..cfbfb4291b3 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java @@ -71,13 +71,18 @@ public interface ComponentMapper { * Return all descendant modules (including itself) from a given component uuid and scope */ List 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 selectEnabledFilesFromProject(@Param("projectUuid") String projectUuid); + + /** + * Return all descendant files from a given module uuid and scope */ List 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 diff --git a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml index 91a3bc460a6..f70496ea9ca 100644 --- a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml @@ -143,8 +143,7 @@ - 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} p.enabled = ${_true} @@ -165,6 +164,17 @@ + +