*/
package org.sonar.server.component.db;
+import com.google.common.collect.Lists;
import org.sonar.api.ServerComponent;
import org.sonar.api.utils.System2;
import org.sonar.core.component.AuthorizedComponentDto;
import javax.annotation.CheckForNull;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
+import static com.google.common.collect.Lists.newArrayList;
+
/**
* @since 4.3
*/
return mapper(session).findModulesByProject(projectKey);
}
+ public List<ComponentDto> findSubProjectsByComponentKeys(DbSession session, Collection<String> keys) {
+ return mapper(session).findSubProjectsByComponentKeys(keys);
+ }
+
+ public List<ComponentDto> getByIds(DbSession session, Collection<Long> ids) {
+ if (ids.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<ComponentDto> components = newArrayList();
+ List<List<Long>> partitionList = Lists.partition(newArrayList(ids), 1000);
+ for (List<Long> partition : partitionList) {
+ List<ComponentDto> dtos = mapper(session).findByIds(partition);
+ components.addAll(dtos);
+ }
+ return components;
+ }
+
+ protected List<ComponentDto> doGetByKeys(DbSession session, Collection<String> keys) {
+ return mapper(session).findByKeys(keys);
+ }
+
@CheckForNull
public AuthorizedComponentDto getNullableAuthorizedComponentById(Long id, DbSession session) {
return mapper(session).selectAuthorizedComponentById(id);
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import org.apache.ibatis.session.ResultContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.search.DbSynchronizationHandler;
import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.action.DeleteKey;
-import org.sonar.server.search.action.DeleteNestedItem;
-import org.sonar.server.search.action.InsertDto;
-import org.sonar.server.search.action.RefreshIndex;
-import org.sonar.server.search.action.UpsertDto;
-import org.sonar.server.search.action.UpsertNestedItem;
+import org.sonar.server.search.action.*;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
+
import java.io.Serializable;
import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
/**
}
public List<DTO> getByKeys(DbSession session, Collection<KEY> keys) {
- List<DTO> results = new ArrayList<DTO>();
- for (KEY key : keys) {
- DTO result = this.getNullableByKey(session, key);
- if (result != null) {
- results.add(result);
- }
+ if (keys.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<DTO> components = newArrayList();
+ List<List<KEY>> partitionList = Lists.partition(newArrayList(keys), 1000);
+ for (List<KEY> partition : partitionList) {
+ List<DTO> dtos = doGetByKeys(session, partition);
+ components.addAll(dtos);
}
- return results;
+ return components;
+ }
+
+ protected List<DTO> doGetByKeys(DbSession session, Collection<KEY> keys) {
+ throw notImplemented(this);
}
@Override
return getSynchronizationParams(date, Collections.<String, String>emptyMap());
}
- protected Map getSynchronizationParams(Date date, Map<String, String> params) {
+ protected Map<String, Object> getSynchronizationParams(Date date, Map<String, String> params) {
Map<String, Object> finalParams = newHashMap();
finalParams.put("date", new Timestamp(date.getTime()));
return finalParams;
public ComponentDao componentDao() {
return componentDao;
}
+
public SnapshotDao snapshotDao() {
return snapshotDao;
}
import org.sonar.server.db.BaseDao;
import org.sonar.server.search.IndexDefinition;
+import java.util.Collection;
import java.util.Date;
+import java.util.List;
import java.util.Map;
public class IssueDao extends BaseDao<IssueMapper, IssueDto, String> implements DaoComponent {
return mapper(session).selectByKey(key);
}
+ protected List<IssueDto> doGetByKeys(DbSession session, Collection<String> keys) {
+ return mapper(session).selectByKeys(keys);
+ }
+
@Override
protected IssueDto doUpdate(DbSession session, IssueDto issue) {
mapper(session).update(issue);
}
@Override
- protected Map getSynchronizationParams(Date date, Map<String, String> params) {
+ protected Map<String, Object> getSynchronizationParams(Date date, Map<String, String> params) {
Map<String, Object> finalParams = super.getSynchronizationParams(date, params);
finalParams.put(PROJECT_KEY, params.get(PROJECT_KEY));
return finalParams;
Set<RuleKey> ruleKeys = newHashSet();
Set<String> projectKeys = newHashSet();
Set<String> componentKeys = newHashSet();
+ Set<Long> componentIds = newHashSet();
Set<String> actionPlanKeys = newHashSet();
List<String> userLogins = newArrayList();
Map<String, User> usersByLogin = newHashMap();
ruleKeys.add(issue.ruleKey());
projectKeys.add(issue.projectKey());
componentKeys.add(issue.componentKey());
+// componentIds.add(issue.com());
actionPlanKeys.add(issue.actionPlanKey());
if (issue.reporter() != null) {
userLogins.add(issue.reporter());
usersByLogin = getUsersByLogin(session, userLogins);
List<ComponentDto> componentDtos = dbClient.componentDao().getByKeys(session, componentKeys);
+ List<ComponentDto> subProjectDtos = dbClient.componentDao().findSubProjectsByComponentKeys(session, componentKeys);
List<ComponentDto> projectDtos = dbClient.componentDao().getByKeys(session, projectKeys);
+ componentDtos.addAll(subProjectDtos);
componentDtos.addAll(projectDtos);
writeProjects(json, projectDtos);
writeComponents(json, componentDtos);
import java.util.Date;
import java.util.List;
+import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
assertThat(result.getAuthorizationUpdatedAt()).isEqualTo(DateUtils.parseDate("2014-06-18"));
}
+ @Test
+ public void find_by_keys() {
+ setupData("shared");
+
+ List<ComponentDto> results = dao.getByKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java");
+ assertThat(results).hasSize(1);
+
+ ComponentDto result = results.get(0);
+ assertThat(result).isNotNull();
+ assertThat(result.key()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
+ assertThat(result.path()).isEqualTo("src/org/struts/RequestContext.java");
+ assertThat(result.name()).isEqualTo("RequestContext.java");
+ assertThat(result.longName()).isEqualTo("org.struts.RequestContext");
+ assertThat(result.qualifier()).isEqualTo("FIL");
+ assertThat(result.scope()).isEqualTo("FIL");
+ assertThat(result.language()).isEqualTo("java");
+ assertThat(result.subProjectId()).isEqualTo(2);
+ assertThat(result.projectId()).isEqualTo(1);
+
+ assertThat(dao.getByKeys(session, "unknown")).isEmpty();
+ }
+
+ @Test
+ public void find_by_ids() {
+ setupData("shared");
+
+ List<ComponentDto> results = dao.getByIds(session, newArrayList(4L));
+ assertThat(results).hasSize(1);
+
+ ComponentDto result = results.get(0);
+ assertThat(result).isNotNull();
+ assertThat(result.key()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
+ assertThat(result.path()).isEqualTo("src/org/struts/RequestContext.java");
+ assertThat(result.name()).isEqualTo("RequestContext.java");
+ assertThat(result.longName()).isEqualTo("org.struts.RequestContext");
+ assertThat(result.qualifier()).isEqualTo("FIL");
+ assertThat(result.scope()).isEqualTo("FIL");
+ assertThat(result.language()).isEqualTo("java");
+ assertThat(result.subProjectId()).isEqualTo(2);
+ assertThat(result.projectId()).isEqualTo(1);
+
+ assertThat(dao.getByIds(session, newArrayList(123L))).isEmpty();
+ }
+
@Test
public void get_by_id() {
setupData("shared");
assertThat(dao.getParentModuleByKey("unknown", session)).isNull();
}
+ @Test
+ public void find_sub_projects_by_component_keys() throws Exception {
+ setupData("multi-modules");
+
+ // Sub project of a file
+ List<ComponentDto> results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core:src/org/struts/RequestContext.java"));
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data");
+
+ // Sub project of a directory
+ results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core:src/org/struts"));
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data");
+
+ // Sub project of a sub module
+ results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-data"));
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts");
+
+ // Sub project of a module
+ results = dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core"));
+ assertThat(results).hasSize(1);
+ assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts");
+
+ // Sub project of a project
+ assertThat(dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts"))).isEmpty();
+
+ // SUb projects of a component and a sub module
+ assertThat(dao.findSubProjectsByComponentKeys(session, newArrayList("org.struts:struts-core:src/org/struts/RequestContext.java", "org.struts:struts-data"))).hasSize(2);
+
+ assertThat(dao.findSubProjectsByComponentKeys(session, newArrayList("unknown"))).isEmpty();
+ }
+
@Test
public void get_nullable_authorized_component_by_id() {
setupData("shared");
import org.sonar.server.rule.RuleTesting;
import java.util.Date;
+import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
assertThat(issue.getRootComponentKey()).isEqualTo("struts");
}
+ @Test
+ public void get_by_keys() {
+ setupData("shared", "get_by_key");
+
+ List<IssueDto> issues = dao.getByKeys(session, "ABCDE");
+ assertThat(issues).hasSize(1);
+
+ IssueDto issue = issues.get(0);
+ assertThat(issue.getKee()).isEqualTo("ABCDE");
+ assertThat(issue.getId()).isEqualTo(100L);
+ assertThat(issue.getComponentId()).isEqualTo(401);
+ assertThat(issue.getRootComponentId()).isEqualTo(399);
+ assertThat(issue.getRuleId()).isEqualTo(500);
+ assertThat(issue.getLanguage()).isEqualTo("java");
+ assertThat(issue.getSeverity()).isEqualTo("BLOCKER");
+ assertThat(issue.isManualSeverity()).isFalse();
+ assertThat(issue.getMessage()).isNull();
+ assertThat(issue.getLine()).isEqualTo(200);
+ assertThat(issue.getEffortToFix()).isEqualTo(4.2);
+ assertThat(issue.getStatus()).isEqualTo("OPEN");
+ assertThat(issue.getResolution()).isEqualTo("FIXED");
+ assertThat(issue.getChecksum()).isEqualTo("XXX");
+ assertThat(issue.getAuthorLogin()).isEqualTo("karadoc");
+ assertThat(issue.getReporter()).isEqualTo("arthur");
+ assertThat(issue.getAssignee()).isEqualTo("perceval");
+ assertThat(issue.getIssueAttributes()).isEqualTo("JIRA=FOO-1234");
+ assertThat(issue.getIssueCreationDate()).isNotNull();
+ assertThat(issue.getIssueUpdateDate()).isNotNull();
+ assertThat(issue.getIssueCloseDate()).isNotNull();
+ assertThat(issue.getCreatedAt()).isNotNull();
+ assertThat(issue.getUpdatedAt()).isNotNull();
+ assertThat(issue.getRuleRepo()).isEqualTo("squid");
+ assertThat(issue.getRule()).isEqualTo("AvoidCycle");
+ assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getRootComponentKey()).isEqualTo("struts");
+ }
+
@Test
public void find_after_dates() throws Exception {
setupData("shared", "some_issues");
file = new ComponentDto()
.setKey("MyComponent")
- .setProjectId(project.getId());
+ .setSubProjectId(project.getId());
db.componentDao().insert(session, file);
db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file));
result.assertJson(this.getClass(), "issue_with_extra_fields.json", false);
}
+ @Test
+ public void components_contains_sub_projects() throws Exception {
+ ComponentDto project = new ComponentDto()
+ .setKey("ProjectHavingModule")
+ .setScope("PRJ");
+ db.componentDao().insert(session, project);
+ db.snapshotDao().insert(session, SnapshotTesting.createForComponent(project));
+
+ // project can be seen by anyone
+ tester.get(PermissionFacade.class).insertGroupPermission(project.getId(), DefaultGroups.ANYONE, UserRole.USER, session);
+ db.issueAuthorizationDao().synchronizeAfter(session, new Date(0));
+
+ ComponentDto module = new ComponentDto()
+ .setKey("ModuleHavingFile")
+ .setScope("PRJ")
+ .setSubProjectId(project.getId());
+ db.componentDao().insert(session, module);
+ db.snapshotDao().insert(session, SnapshotTesting.createForComponent(module));
+
+ ComponentDto file = new ComponentDto()
+ .setKey("FileLinkedToModule")
+ .setScope("FIL")
+ .setSubProjectId(module.getId());
+ db.componentDao().insert(session, file);
+ db.snapshotDao().insert(session, SnapshotTesting.createForComponent(file));
+
+ IssueDto issue = IssueTesting.newDto(rule, file, project);
+ db.issueDao().insert(session, issue);
+ session.commit();
+
+ WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
+ result.assertJson(this.getClass(), "components_contains_sub_projects.json", false);
+ }
+
@Test
public void display_facets() throws Exception {
IssueDto issue = IssueTesting.newDto(rule, file, project)
--- /dev/null
+{
+ "components": [
+ {
+ "key": "FileLinkedToModule"
+ },
+ {
+ "key": "ModuleHavingFile"
+ },
+ {
+ "key": "ProjectHavingModule"
+ }
+ ],
+ "projects": [
+ {
+ "key": "ProjectHavingModule"
+ }
+ ]
+}
private String name;
private String longName;
private String language;
- private Long projectId;
private Long subProjectId;
private boolean enabled = true;
private Date authorizationUpdatedAt;
+ // Return by join for the moment
+ private Long projectId;
+
public ComponentDto setId(Long id) {
super.setId(id);
return this;
import javax.annotation.CheckForNull;
+import java.util.Collection;
import java.util.List;
/**
*/
List<ComponentDto> findModulesByProject(@Param("projectKey") String projectKey);
+ /**
+ * Return sub project of component keys
+ */
+ List<ComponentDto> findSubProjectsByComponentKeys(@Param("keys") Collection<String> keys);
+
+ List<ComponentDto> findByIds(@Param("ids") Collection<Long> ids);
+
+ List<ComponentDto> findByKeys(@Param("keys") Collection<String> keys);
+
long countById(long id);
@CheckForNull
IssueDto selectByKey(String key);
+ List<IssueDto> selectByKeys(Collection<String> keys);
+
/**
* Return a paginated list of authorized issue ids for a user.
* If the role is null, then the authorisation check is disabled.
</where>
</select>
+ <select id="findByIds" parameterType="long" resultType="Component">
+ select <include refid="componentColumns"/>
+ from projects p
+ inner join snapshots s on s.project_id=p.id and s.islast=${_true}
+ <where>
+ p.enabled=${_true}
+ and p.id in
+ <foreach collection="ids" open="(" close=")" item="id" separator=",">
+ #{id}
+ </foreach>
+ </where>
+ </select>
+
+ <select id="findByKeys" parameterType="String" resultType="Component">
+ select <include refid="componentColumns"/>
+ from projects p
+ inner join snapshots s on s.project_id=p.id and s.islast=${_true}
+ <where>
+ p.enabled=${_true}
+ and p.kee in
+ <foreach collection="keys" open="(" close=")" item="key" separator=",">
+ #{key}
+ </foreach>
+ </where>
+ </select>
+
+ <select id="findSubProjectsByComponentKeys" parameterType="String" resultType="Component">
+ SELECT <include refid="componentColumns"/>
+ FROM projects p
+ INNER JOIN snapshots s ON s.project_id=p.id AND s.islast=${_true}
+ INNER JOIN projects child ON child.root_id=p.id AND child.enabled=${_true}
+ <where>
+ AND p.enabled=${_true}
+ AND p.scope='PRJ'
+ AND child.kee in
+ <foreach collection="keys" open="(" close=")" item="key" separator=",">
+ #{key}
+ </foreach>
+ </where>
+ </select>
+
<select id="selectAuthorizedComponentById" parameterType="long" resultType="AuthorizedComponent">
SELECT <include refid="authorizedComponentColumns"/>
FROM projects p
</foreach>
</select>
+ <select id="selectByKeys" parameterType="map" resultType="Issue">
+ select
+ <include refid="issueColumns"/>
+ from issues i
+ inner join rules r on r.id=i.rule_id
+ inner join projects p on p.id=i.component_id
+ inner join projects root on root.id=i.root_component_id
+ where i.kee in
+ <foreach collection="list" open="(" close=")" item="key" separator=",">
+ #{key}
+ </foreach>
+ </select>
+
<select id="selectIssues" parameterType="map" resultType="Issue">
select
<include refid="issueColumns"/>