Skip to content

Commit

Permalink
SONAR-8089 Merge ComponentDao#selectChildren and selectDescendants
Browse files Browse the repository at this point in the history
  • Loading branch information
julienlancelot committed Nov 8, 2016
1 parent 617497c commit b67b21e
Show file tree
Hide file tree
Showing 10 changed files with 170 additions and 339 deletions.
Expand Up @@ -19,26 +19,6 @@
*/ */
package org.sonar.server.component.ws; package org.sonar.server.component.ws;


import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format;
import static java.util.Collections.emptyMap;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
import static org.sonar.server.component.ComponentFinder.ParamNames.BASE_COMPONENT_ID_AND_KEY;
import static org.sonar.server.component.ws.ComponentDtoToWsComponent.componentDtoToWsComponent;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.ACTION_TREE;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BASE_COMPONENT_ID;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BASE_COMPONENT_KEY;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_STRATEGY;

import com.google.common.base.Predicates; import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
Expand All @@ -65,6 +45,26 @@
import org.sonarqube.ws.WsComponents.TreeWsResponse; import org.sonarqube.ws.WsComponents.TreeWsResponse;
import org.sonarqube.ws.client.component.TreeWsRequest; import org.sonarqube.ws.client.component.TreeWsRequest;


import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Sets.newHashSet;
import static java.lang.String.format;
import static java.util.Collections.emptyMap;
import static org.sonar.core.util.Uuids.UUID_EXAMPLE_02;
import static org.sonar.server.component.ComponentFinder.ParamNames.BASE_COMPONENT_ID_AND_KEY;
import static org.sonar.server.component.ws.ComponentDtoToWsComponent.componentDtoToWsComponent;
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException;
import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001;
import static org.sonar.server.ws.WsParameterBuilder.createQualifiersParameter;
import static org.sonar.server.ws.WsParameterBuilder.QualifierParameterContext.newQualifierParameterContext;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.ACTION_TREE;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BASE_COMPONENT_ID;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_BASE_COMPONENT_KEY;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_STRATEGY;

public class TreeAction implements ComponentsWsAction { public class TreeAction implements ComponentsWsAction {
private static final int MAX_SIZE = 500; private static final int MAX_SIZE = 500;
private static final int QUERY_MINIMUM_LENGTH = 3; private static final int QUERY_MINIMUM_LENGTH = 3;
Expand Down Expand Up @@ -158,13 +158,13 @@ private TreeWsResponse doHandle(TreeWsRequest treeWsRequest) {
int total; int total;
switch (treeWsRequest.getStrategy()) { switch (treeWsRequest.getStrategy()) {
case CHILDREN_STRATEGY: case CHILDREN_STRATEGY:
components = dbClient.componentDao().selectChildren(dbSession, query); components = dbClient.componentDao().selectDescendants(dbSession, query);
total = dbClient.componentDao().countChildren(dbSession, query); total = components.size();
break; break;
case LEAVES_STRATEGY: case LEAVES_STRATEGY:
case ALL_STRATEGY: case ALL_STRATEGY:
components = dbClient.componentDao().selectDescendants(dbSession, query); components = dbClient.componentDao().selectDescendants(dbSession, query);
total = dbClient.componentDao().countDescendants(dbSession, query); total = components.size();
break; break;
default: default:
throw new IllegalStateException("Unknown component tree strategy"); throw new IllegalStateException("Unknown component tree strategy");
Expand Down
Expand Up @@ -41,30 +41,30 @@
import org.sonar.core.util.CloseableIterator; import org.sonar.core.util.CloseableIterator;
import org.sonar.db.DbClient; import org.sonar.db.DbClient;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentTreeQuery; import org.sonar.db.component.ComponentTreeQuery;
import org.sonar.db.component.ComponentTreeQuery.Strategy;
import org.sonar.db.source.FileSourceDto; import org.sonar.db.source.FileSourceDto;
import org.sonar.server.computation.task.projectanalysis.analysis.Analysis;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder; import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
import org.sonar.server.computation.task.projectanalysis.component.Component; import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit; import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
import org.sonar.server.computation.task.projectanalysis.component.DepthTraversalTypeAwareCrawler; import org.sonar.server.computation.task.projectanalysis.component.DepthTraversalTypeAwareCrawler;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder; import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitorAdapter; import org.sonar.server.computation.task.projectanalysis.component.TypeAwareVisitorAdapter;
import org.sonar.server.computation.task.projectanalysis.filemove.FileSimilarity.File; import org.sonar.server.computation.task.projectanalysis.filemove.FileSimilarity.File;
import org.sonar.server.computation.task.projectanalysis.analysis.Analysis;
import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepository; import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepository;
import org.sonar.server.computation.task.step.ComputationStep; import org.sonar.server.computation.task.step.ComputationStep;


import static com.google.common.base.Splitter.on; import static com.google.common.base.Splitter.on;
import static com.google.common.collect.FluentIterable.from; import static com.google.common.collect.FluentIterable.from;
import static java.util.Arrays.asList; import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER; import static org.sonar.server.computation.task.projectanalysis.component.ComponentVisitor.Order.POST_ORDER;


public class FileMoveDetectionStep implements ComputationStep { public class FileMoveDetectionStep implements ComputationStep {
protected static final int MIN_REQUIRED_SCORE = 85; protected static final int MIN_REQUIRED_SCORE = 85;
private static final Logger LOG = Loggers.get(FileMoveDetectionStep.class); private static final Logger LOG = Loggers.get(FileMoveDetectionStep.class);
private static final List<String> FILE_QUALIFIERS = asList(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE); private static final List<String> FILE_QUALIFIERS = asList(Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE);
private static final List<String> SORT_FIELDS = singletonList("name");
private static final Splitter LINES_HASHES_SPLITTER = on('\n'); private static final Splitter LINES_HASHES_SPLITTER = on('\n');


private final AnalysisMetadataHolder analysisMetadataHolder; private final AnalysisMetadataHolder analysisMetadataHolder;
Expand Down Expand Up @@ -152,15 +152,14 @@ private Map<String, DbComponent> getDbFilesByKey() {
try (DbSession dbSession = dbClient.openSession(false)) { try (DbSession dbSession = dbClient.openSession(false)) {
// FIXME no need to use such a complex query, joining on SNAPSHOTS and retrieving all column of table PROJECTS, replace with dedicated // FIXME no need to use such a complex query, joining on SNAPSHOTS and retrieving all column of table PROJECTS, replace with dedicated
// mapper method // mapper method
return from(dbClient.componentDao().selectDescendants( List<ComponentDto> componentDtos = dbClient.componentDao().selectDescendants(
dbSession, dbSession,
ComponentTreeQuery.builder() ComponentTreeQuery.builder()
.setBaseUuid(rootHolder.getRoot().getUuid()) .setBaseUuid(rootHolder.getRoot().getUuid())
.setQualifiers(FILE_QUALIFIERS) .setQualifiers(FILE_QUALIFIERS)
.setSortFields(SORT_FIELDS) .setStrategy(Strategy.LEAVES)
.setPageSize(Integer.MAX_VALUE) .build());
.setPage(1) return from(componentDtos)
.build()))
.transform(componentDto -> new DbComponent(componentDto.getId(), componentDto.key(), componentDto.uuid(), componentDto.path())) .transform(componentDto -> new DbComponent(componentDto.getId(), componentDto.key(), componentDto.uuid(), componentDto.path()))
.uniqueIndex(DbComponent::getKey); .uniqueIndex(DbComponent::getKey);
} }
Expand Down
Expand Up @@ -172,13 +172,13 @@ private ComponentDtosAndTotal searchComponents(DbSession dbSession, ComponentTre
switch (strategy) { switch (strategy) {
case CHILDREN_STRATEGY: case CHILDREN_STRATEGY:
return new ComponentDtosAndTotal( return new ComponentDtosAndTotal(
dbClient.componentDao().selectChildren(dbSession, dbQuery), dbClient.componentDao().selectDescendants(dbSession, dbQuery),
dbClient.componentDao().countChildren(dbSession, dbQuery)); 0);
case LEAVES_STRATEGY: case LEAVES_STRATEGY:
case ALL_STRATEGY: case ALL_STRATEGY:
return new ComponentDtosAndTotal( return new ComponentDtosAndTotal(
dbClient.componentDao().selectDescendants(dbSession, dbQuery), dbClient.componentDao().selectDescendants(dbSession, dbQuery),
dbClient.componentDao().countDescendants(dbSession, dbQuery)); 0);
default: default:
throw new IllegalStateException("Unknown component tree strategy"); throw new IllegalStateException("Unknown component tree strategy");
} }
Expand Down
Expand Up @@ -44,11 +44,11 @@
import org.sonar.db.component.ComponentTreeQuery; import org.sonar.db.component.ComponentTreeQuery;
import org.sonar.db.source.FileSourceDao; import org.sonar.db.source.FileSourceDao;
import org.sonar.db.source.FileSourceDto; import org.sonar.db.source.FileSourceDto;
import org.sonar.server.computation.task.projectanalysis.analysis.Analysis;
import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule; import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.component.Component; import org.sonar.server.computation.task.projectanalysis.component.Component;
import org.sonar.server.computation.task.projectanalysis.component.ReportComponent; import org.sonar.server.computation.task.projectanalysis.component.ReportComponent;
import org.sonar.server.computation.task.projectanalysis.analysis.Analysis; import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolderRule;
import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepositoryRule; import org.sonar.server.computation.task.projectanalysis.source.SourceLinesRepositoryRule;


import static com.google.common.base.Joiner.on; import static com.google.common.base.Joiner.on;
Expand Down Expand Up @@ -287,9 +287,6 @@ public void execute_retrieves_only_file_and_unit_tests_from_last_snapshot() {


ComponentTreeQuery query = captor.getValue(); ComponentTreeQuery query = captor.getValue();
assertThat(query.getBaseUuid()).isEqualTo(PROJECT.getUuid()); assertThat(query.getBaseUuid()).isEqualTo(PROJECT.getUuid());
assertThat(query.getPage()).isEqualTo(1);
assertThat(query.getPageSize()).isEqualTo(Integer.MAX_VALUE);
assertThat(query.getSqlSort()).isEqualTo("LOWER(p.name) ASC, p.name ASC");
assertThat(query.getQualifiers()).containsOnly(FILE, UNIT_TEST_FILE); assertThat(query.getQualifiers()).containsOnly(FILE, UNIT_TEST_FILE);
} }


Expand Down
64 changes: 3 additions & 61 deletions sonar-db/src/main/java/org/sonar/db/component/ComponentDao.java
Expand Up @@ -34,15 +34,12 @@
import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes; import org.sonar.api.resources.Scopes;
import org.sonar.db.Dao; import org.sonar.db.Dao;
import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.RowNotFoundException; import org.sonar.db.RowNotFoundException;
import org.sonar.db.WildcardPosition;


import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.Maps.newHashMapWithExpectedSize; import static com.google.common.collect.Maps.newHashMapWithExpectedSize;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
import static org.sonar.api.utils.Paging.offset;
import static org.sonar.db.DatabaseUtils.executeLargeInputs; import static org.sonar.db.DatabaseUtils.executeLargeInputs;
import static org.sonar.db.DatabaseUtils.executeLargeUpdates; import static org.sonar.db.DatabaseUtils.executeLargeUpdates;


Expand Down Expand Up @@ -167,73 +164,18 @@ public List<ComponentDto> selectAncestors(DbSession dbSession, ComponentDto comp
} }


/** /**
* Select the children of a base component, given by its UUID. The components that are not present in last * Select the children or the leaves of a base component, given by its UUID. The components that are not present in last
* analysis are ignored.
*
* An empty list is returned if the base component does not exist or if the base component is a leaf.
*/
public List<ComponentDto> selectChildren(DbSession dbSession, ComponentTreeQuery query) {
Optional<ComponentDto> componentOpt = selectByUuid(dbSession, query.getBaseUuid());
if (!componentOpt.isPresent()) {
return emptyList();
}
ComponentDto component = componentOpt.get();
RowBounds rowBounds = new RowBounds(offset(query.getPage(), query.getPageSize()), query.getPageSize());
return mapper(dbSession).selectChildren(query, uuidPathForChildrenQuery(component), rowBounds);
}

/**
* Count the children of a base component, given by its UUID. The components that are not present in last
* analysis are ignored.
*
* Zero is returned if the base component does not exist or if the base component is a leaf.
*/
public int countChildren(DbSession dbSession, ComponentTreeQuery query) {
Optional<ComponentDto> componentOpt = selectByUuid(dbSession, query.getBaseUuid());
if (!componentOpt.isPresent()) {
return 0;
}
ComponentDto component = componentOpt.get();
return mapper(dbSession).countChildren(query, uuidPathForChildrenQuery(component));
}

private static String uuidPathForChildrenQuery(ComponentDto component) {
return component.getUuidPath() + component.uuid() + ".";
}

/**
* Select the descendants of a base component, given by its UUID. The components that are not present in last
* analysis are ignored. * analysis are ignored.
* *
* An empty list is returned if the base component does not exist or if the base component is a leaf. * An empty list is returned if the base component does not exist or if the base component is a leaf.
*/ */
public List<ComponentDto> selectDescendants(DbSession dbSession, ComponentTreeQuery query) { public List<ComponentDto> selectDescendants(DbSession dbSession, ComponentTreeQuery query) {
Optional<ComponentDto> componentOpt = selectByUuid(dbSession, query.getBaseUuid()); Optional<ComponentDto> componentOpt = selectByUuid(dbSession, query.getBaseUuid());
if (!componentOpt.isPresent()) { if (!componentOpt.isPresent()) {
return Collections.emptyList(); return emptyList();
}
ComponentDto component = componentOpt.get();
RowBounds rowBounds = new RowBounds(offset(query.getPage(), query.getPageSize()), query.getPageSize());
return mapper(dbSession).selectDescendants(query, uuidPathForDescendantsQuery(component), rowBounds);
}

/**
* Count the descendants of a base component, given by its UUID. The components that are not present in last
* analysis are ignored.
*
* Zero is returned if the base component does not exist or if the base component is a leaf.
*/
public int countDescendants(DbSession dbSession, ComponentTreeQuery query) {
Optional<ComponentDto> componentOpt = selectByUuid(dbSession, query.getBaseUuid());
if (!componentOpt.isPresent()) {
return 0;
} }
ComponentDto component = componentOpt.get(); ComponentDto component = componentOpt.get();
return mapper(dbSession).countDescendants(query, uuidPathForDescendantsQuery(component)); return mapper(dbSession).selectDescendants(query, query.getUuidPath(component));
}

private static String uuidPathForDescendantsQuery(ComponentDto component) {
return DatabaseUtils.buildLikeValue(component.getUuidPath() + component.uuid() + ".", WildcardPosition.AFTER);
} }


public ComponentDto selectOrFailByKey(DbSession session, String key) { public ComponentDto selectOrFailByKey(DbSession session, String key) {
Expand Down
Expand Up @@ -64,13 +64,7 @@ public interface ComponentMapper {


List<ComponentDto> selectAncestors(@Param("query") ComponentTreeQuery query, @Param("baseUuidPathLike") String baseUuidPathLike); List<ComponentDto> selectAncestors(@Param("query") ComponentTreeQuery query, @Param("baseUuidPathLike") String baseUuidPathLike);


List<ComponentDto> selectChildren(@Param("query") ComponentTreeQuery query, @Param("baseUuidPath") String baseUuidPath, RowBounds rowBounds); List<ComponentDto> selectDescendants(@Param("query") ComponentTreeQuery query, @Param("baseUuidPath") String baseUuidPath);

int countChildren(@Param("query") ComponentTreeQuery query, @Param("baseUuidPath") String baseUuidPath);

List<ComponentDto> selectDescendants(@Param("query") ComponentTreeQuery query, @Param("baseUuidPathLike") String baseUuidPathLike, RowBounds rowBounds);

int countDescendants(@Param("query") ComponentTreeQuery query, @Param("baseUuidPathLike") String baseUuidPathLike);


/** /**
* Return all project (PRJ/TRK) uuids * Return all project (PRJ/TRK) uuids
Expand Down

0 comments on commit b67b21e

Please sign in to comment.