It now accepts either a list of projects or a project with a list of components, but no more a list of components of any projects It's no more possible to query a list of any components, because when doing that the performance are very bad (it would probably requires to add a column PROJECT_MEASURES.PROJECT_UUID)tags/6.2-RC1
@@ -209,8 +209,8 @@ public class ComponentTreeDataLoader { | |||
Map<Integer, MetricDto> metricsById = Maps.uniqueIndex(metrics, MetricDtoFunctions.toId()); | |||
MeasureQuery measureQuery = MeasureQuery.builder() | |||
.setPersonId(developerId) | |||
.setComponentUuids(componentUuids) | |||
.setMetricIds(metricsById.keySet()) | |||
.setComponentUuids(baseComponent.projectUuid(), componentUuids) | |||
.setMetricIds(new ArrayList<>(metricsById.keySet())) | |||
.build(); | |||
List<MeasureDto> measureDtos = dbClient.measureDao().selectByQuery(dbSession, measureQuery); | |||
@@ -153,7 +153,7 @@ public class SearchAction implements MeasuresWsAction { | |||
private List<MeasureDto> searchMeasures() { | |||
return dbClient.measureDao().selectByQuery(dbSession, MeasureQuery.builder() | |||
.setComponentUuids(projects.stream().map(ComponentDto::uuid).collect(toList())) | |||
.setProjectUuids(projects.stream().map(ComponentDto::uuid).collect(toList())) | |||
.setMetricIds(metrics.stream().map(MetricDto::getId).collect(toList())) | |||
.build()); | |||
} |
@@ -62,7 +62,7 @@ public class SearchMyProjectsDataLoader { | |||
List<SnapshotDto> snapshots = dbClient.snapshotDao().selectLastAnalysesByRootComponentUuids(dbSession, projectUuids); | |||
MetricDto gateStatusMetric = dbClient.metricDao().selectOrFailByKey(dbSession, CoreMetrics.ALERT_STATUS_KEY); | |||
MeasureQuery measureQuery = MeasureQuery.builder() | |||
.setComponentUuids(projectUuids) | |||
.setProjectUuids(projectUuids) | |||
.setMetricId(gateStatusMetric.getId()) | |||
.build(); | |||
List<MeasureDto> qualityGates = dbClient.measureDao().selectByQuery(dbSession, measureQuery); |
@@ -48,6 +48,7 @@ import org.sonarqube.ws.WsQualityGates.ProjectStatusWsResponse; | |||
import org.sonarqube.ws.client.qualitygate.ProjectStatusWsRequest; | |||
import static com.google.common.base.Strings.isNullOrEmpty; | |||
import static java.util.Collections.singletonList; | |||
import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; | |||
import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; | |||
import static org.sonar.server.ws.WsUtils.checkRequest; | |||
@@ -162,7 +163,7 @@ public class ProjectStatusAction implements QualityGatesWsAction { | |||
private Optional<String> getQualityGateDetailsMeasureData(DbSession dbSession, ComponentDto project) { | |||
MeasureQuery measureQuery = MeasureQuery.builder() | |||
.setComponentUuid(project.projectUuid()) | |||
.setProjectUuids(singletonList(project.projectUuid())) | |||
.setMetricKey(CoreMetrics.QUALITY_GATE_DETAILS_KEY) | |||
.build(); | |||
List<MeasureDto> measures = dbClient.measureDao().selectByQuery(dbSession, measureQuery); |
@@ -41,8 +41,11 @@ public class MeasureDao implements Dao { | |||
/** | |||
* Selects the measures of either the last analysis (when {@link MeasureQuery#analysisUuid} is {@code null}) or of the | |||
* specified analysis (given by {@link MeasureQuery#analysisUuid}) for the component UUIDs specified in | |||
* {@link MeasureQuery#componentUuids}. | |||
* specified analysis (given by {@link MeasureQuery#analysisUuid}). | |||
* The components can be specified either as : | |||
* - A list of projects in {@link MeasureQuery#projectUuids} | |||
* - A list of components in {@link MeasureQuery#componentUuids} with one mandatory project in {@link MeasureQuery#projectUuids} | |||
* - One single component in {@link MeasureQuery#componentUuids} | |||
* <p> | |||
* In addition, this method returns measures which are not associated to any developer, unless one is specified in | |||
* {@link MeasureQuery#personId}. | |||
@@ -56,22 +59,29 @@ public class MeasureDao implements Dao { | |||
if (query.returnsEmpty()) { | |||
return Collections.emptyList(); | |||
} | |||
if (query.getComponentUuids() == null) { | |||
return mapper(dbSession).selectByQuery(query); | |||
if (query.getComponentUuids() != null) { | |||
return executeLargeInputs( | |||
query.getComponentUuids(), | |||
componentUuids -> { | |||
MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfComponentUuids(query, componentUuids); | |||
return mapper(dbSession).selectByQuery(pageQuery); | |||
}); | |||
} else if (query.getProjectUuids() != null) { | |||
return executeLargeInputs( | |||
query.getProjectUuids(), | |||
projectUuids -> { | |||
MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfProjectUuids(query, projectUuids); | |||
return mapper(dbSession).selectByQuery(pageQuery); | |||
}); | |||
} | |||
return executeLargeInputs(query.getComponentUuids(), componentUuids -> { | |||
MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfComponentUuids(query, componentUuids); | |||
return mapper(dbSession).selectByQuery(pageQuery); | |||
}); | |||
return mapper(dbSession).selectByQuery(query); | |||
} | |||
public void selectByQuery(DbSession dbSession, MeasureQuery query, ResultHandler resultHandler) { | |||
if (query.returnsEmpty()) { | |||
return; | |||
} | |||
if (query.getComponentUuids() == null) { | |||
mapper(dbSession).selectByQuery(query, resultHandler); | |||
} else { | |||
if (query.getComponentUuids() != null) { | |||
executeLargeInputsWithoutOutput( | |||
query.getComponentUuids(), | |||
componentUuids -> { | |||
@@ -79,7 +89,16 @@ public class MeasureDao implements Dao { | |||
mapper(dbSession).selectByQuery(pageQuery, resultHandler); | |||
return null; | |||
}); | |||
} else if (query.getProjectUuids() != null) { | |||
executeLargeInputsWithoutOutput( | |||
query.getProjectUuids(), | |||
projectUuids -> { | |||
MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfProjectUuids(query, projectUuids); | |||
mapper(dbSession).selectByQuery(pageQuery, resultHandler); | |||
return null; | |||
}); | |||
} | |||
mapper(dbSession).selectByQuery(query, resultHandler); | |||
} | |||
public List<PastMeasureDto> selectPastMeasures(DbSession dbSession, |
@@ -19,39 +19,50 @@ | |||
*/ | |||
package org.sonar.db.measure; | |||
import java.util.Collection; | |||
import java.util.List; | |||
import java.util.Objects; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import static com.google.common.base.Preconditions.checkState; | |||
import static java.util.Collections.singleton; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static java.util.Collections.singletonList; | |||
import static java.util.Objects.requireNonNull; | |||
public class MeasureQuery { | |||
private final String analysisUuid; | |||
@CheckForNull | |||
private final List<String> projectUuids; | |||
@CheckForNull | |||
private final List<String> componentUuids; | |||
@CheckForNull | |||
private final Collection<Integer> metricIds; | |||
private final List<Integer> metricIds; | |||
@CheckForNull | |||
private final Collection<String> metricKeys; | |||
private final List<String> metricKeys; | |||
@CheckForNull | |||
private final Long personId; | |||
private MeasureQuery(Builder builder) { | |||
this(builder.analysisUuid, builder.componentUuids, builder.metricIds, builder.metricKeys, builder.personId); | |||
this(builder.analysisUuid, builder.projectUuids, builder.componentUuids, builder.metricIds, builder.metricKeys, builder.personId); | |||
} | |||
private MeasureQuery(@Nullable String analysisUuid, | |||
List<String> componentUuids, | |||
@Nullable Collection<Integer> metricIds, | |||
@Nullable Collection<String> metricKeys, | |||
@Nullable List<String> projectUuids, | |||
@Nullable List<String> componentUuids, | |||
@Nullable List<Integer> metricIds, | |||
@Nullable List<String> metricKeys, | |||
@Nullable Long personId) { | |||
requireNonNull(componentUuids, "Component UUIDs must be set"); | |||
checkState(metricIds == null || metricKeys == null, "Metric IDs and keys must not be set both"); | |||
checkArgument(metricIds == null || metricKeys == null, "Metric IDs and keys must not be set both"); | |||
checkArgument(projectUuids != null || componentUuids != null, "At least one filter on component UUID is expected"); | |||
checkArgument(componentUuids == null || componentUuids.size() == 1 || (projectUuids != null && projectUuids.size() == 1), | |||
"Component UUIDs can only be used when a single project UUID is set"); | |||
this.analysisUuid = analysisUuid; | |||
this.projectUuids = projectUuids; | |||
this.componentUuids = componentUuids; | |||
this.metricIds = metricIds; | |||
this.metricKeys = metricKeys; | |||
@@ -62,17 +73,33 @@ public class MeasureQuery { | |||
return analysisUuid; | |||
} | |||
@CheckForNull | |||
public List<String> getProjectUuids() { | |||
return projectUuids; | |||
} | |||
@CheckForNull | |||
public String getProjectUuid() { | |||
return isOnComponents() ? projectUuids.get(0) : null; | |||
} | |||
@CheckForNull | |||
public List<String> getComponentUuids() { | |||
return componentUuids; | |||
} | |||
@CheckForNull | |||
public Collection<Integer> getMetricIds() { | |||
public String getComponentUuid() { | |||
return isOnSingleComponent() ? componentUuids.get(0) : null; | |||
} | |||
@CheckForNull | |||
public List<Integer> getMetricIds() { | |||
return metricIds; | |||
} | |||
@CheckForNull | |||
public Collection<String> getMetricKeys() { | |||
public List<String> getMetricKeys() { | |||
return metricKeys; | |||
} | |||
@@ -82,11 +109,24 @@ public class MeasureQuery { | |||
} | |||
public boolean returnsEmpty() { | |||
return componentUuids.isEmpty() | |||
return (projectUuids != null && projectUuids.isEmpty()) | |||
|| (componentUuids != null && componentUuids.isEmpty()) | |||
|| (metricIds != null && metricIds.isEmpty()) | |||
|| (metricKeys != null && metricKeys.isEmpty()); | |||
} | |||
public boolean isOnProjects() { | |||
return projectUuids != null && componentUuids == null; | |||
} | |||
public boolean isOnComponents() { | |||
return projectUuids != null && projectUuids.size() == 1 && componentUuids != null; | |||
} | |||
public boolean isOnSingleComponent() { | |||
return projectUuids == null && componentUuids != null && componentUuids.size() == 1; | |||
} | |||
@Override | |||
public boolean equals(@Nullable Object o) { | |||
if (this == o) { | |||
@@ -97,10 +137,11 @@ public class MeasureQuery { | |||
} | |||
MeasureQuery that = (MeasureQuery) o; | |||
return Objects.equals(analysisUuid, that.analysisUuid) && | |||
Objects.equals(componentUuids, that.componentUuids) && | |||
Objects.equals(metricIds, that.metricIds) && | |||
Objects.equals(metricKeys, that.metricKeys) && | |||
Objects.equals(personId, that.personId); | |||
Objects.equals(projectUuids, that.projectUuids) && | |||
Objects.equals(componentUuids, that.componentUuids) && | |||
Objects.equals(metricIds, that.metricIds) && | |||
Objects.equals(metricKeys, that.metricKeys) && | |||
Objects.equals(personId, that.personId); | |||
} | |||
@Override | |||
@@ -112,15 +153,20 @@ public class MeasureQuery { | |||
return new Builder(); | |||
} | |||
static MeasureQuery copyWithSubsetOfProjectUuids(MeasureQuery query, List<String> projectUuids) { | |||
return new MeasureQuery(query.analysisUuid, projectUuids, query.componentUuids, query.metricIds, query.metricKeys, query.personId); | |||
} | |||
static MeasureQuery copyWithSubsetOfComponentUuids(MeasureQuery query, List<String> componentUuids) { | |||
return new MeasureQuery(query.analysisUuid, componentUuids, query.metricIds, query.metricKeys, query.personId); | |||
return new MeasureQuery(query.analysisUuid, query.projectUuids, componentUuids, query.metricIds, query.metricKeys, query.personId); | |||
} | |||
public static final class Builder { | |||
private String analysisUuid; | |||
private List<String> projectUuids; | |||
private List<String> componentUuids; | |||
private Collection<Integer> metricIds; | |||
private Collection<String> metricKeys; | |||
private List<Integer> metricIds; | |||
private List<String> metricKeys; | |||
private Long personId; | |||
private Builder() { | |||
@@ -132,11 +178,26 @@ public class MeasureQuery { | |||
return this; | |||
} | |||
public Builder setComponentUuids(List<String> componentUuids) { | |||
/** | |||
* List of projects | |||
*/ | |||
public Builder setProjectUuids(@Nullable List<String> projectUuids) { | |||
this.projectUuids = projectUuids; | |||
return this; | |||
} | |||
/** | |||
* List of components of a project | |||
*/ | |||
public Builder setComponentUuids(String projectUuid, List<String> componentUuids) { | |||
setProjectUuids(singletonList(requireNonNull(projectUuid))); | |||
this.componentUuids = componentUuids; | |||
return this; | |||
} | |||
/** | |||
* Single component | |||
*/ | |||
public Builder setComponentUuid(String componentUuid) { | |||
this.componentUuids = singletonList(componentUuid); | |||
return this; | |||
@@ -145,26 +206,26 @@ public class MeasureQuery { | |||
/** | |||
* All the measures are returned if parameter is {@code null}. | |||
*/ | |||
public Builder setMetricIds(@Nullable Collection<Integer> metricIds) { | |||
public Builder setMetricIds(@Nullable List<Integer> metricIds) { | |||
this.metricIds = metricIds; | |||
return this; | |||
} | |||
public Builder setMetricId(int metricId) { | |||
this.metricIds = singleton(metricId); | |||
this.metricIds = singletonList(metricId); | |||
return this; | |||
} | |||
/** | |||
* All the measures are returned if parameter is {@code null}. | |||
*/ | |||
public Builder setMetricKeys(@Nullable Collection<String> s) { | |||
public Builder setMetricKeys(@Nullable List<String> s) { | |||
this.metricKeys = s; | |||
return this; | |||
} | |||
public Builder setMetricKey(String s) { | |||
this.metricKeys = singleton(s); | |||
this.metricKeys = singletonList(s); | |||
return this; | |||
} | |||
@@ -29,41 +29,55 @@ | |||
select | |||
<include refid="measureColumns"/> | |||
from | |||
project_measures pm | |||
inner join projects p on p.uuid=pm.component_uuid | |||
inner join snapshots analysis on analysis.component_uuid = p.project_uuid and analysis.uuid = pm.analysis_uuid | |||
<if test="query.getMetricKeys() != null"> | |||
inner join metrics m on m.id = pm.metric_id | |||
</if> | |||
project_measures pm | |||
inner join snapshots analysis on analysis.uuid = pm.analysis_uuid | |||
<if test="query.isOnComponents()"> | |||
inner join projects p on p.project_uuid=analysis.component_uuid and p.uuid=pm.component_uuid | |||
and p.project_uuid=#{query.projectUuid} | |||
and p.uuid in | |||
<foreach item="componentUuid" collection="query.getComponentUuids()" open="(" separator="," close=")"> | |||
#{componentUuid} | |||
</foreach> | |||
</if> | |||
<if test="query.isOnSingleComponent()"> | |||
inner join projects p on p.project_uuid=analysis.component_uuid and p.uuid=pm.component_uuid | |||
and p.uuid=#{query.componentUuid} | |||
</if> | |||
<if test="query.getMetricKeys() != null"> | |||
inner join metrics m on m.id = pm.metric_id | |||
</if> | |||
where | |||
<if test="query.getAnalysisUuid() == null"> | |||
analysis.islast=${_true} | |||
</if> | |||
<if test="query.getAnalysisUuid() != null"> | |||
analysis.uuid = #{query.analysisUuid} | |||
</if> | |||
and p.uuid in | |||
<foreach item="componentUuid" collection="query.getComponentUuids()" open="(" separator="," close=")"> | |||
#{componentUuid} | |||
<if test="query.getAnalysisUuid() == null"> | |||
analysis.islast=${_true} | |||
</if> | |||
<if test="query.getAnalysisUuid() != null"> | |||
analysis.uuid = #{query.analysisUuid} | |||
</if> | |||
<if test="query.isOnProjects()"> | |||
and analysis.component_uuid=pm.component_uuid | |||
and analysis.component_uuid in | |||
<foreach item="projectUuid" collection="query.getProjectUuids()" open="(" separator="," close=")"> | |||
#{projectUuid} | |||
</foreach> | |||
<if test="query.getMetricIds() != null"> | |||
and pm.metric_id in | |||
<foreach item="metricId" collection="query.getMetricIds()" open="(" separator="," close=")">#{metricId}</foreach> | |||
</if> | |||
<if test="query.getMetricKeys() != null"> | |||
and m.name in | |||
<foreach item="metricKey" collection="query.getMetricKeys()" open="(" separator="," close=")"> | |||
#{metricKey} | |||
</foreach> | |||
</if> | |||
<choose> | |||
<when test="query.getPersonId() != null"> | |||
and person_id = #{query.personId} | |||
</when> | |||
<otherwise> | |||
and person_id is null | |||
</otherwise> | |||
</choose> | |||
</if> | |||
<if test="query.getMetricIds() != null"> | |||
and pm.metric_id in | |||
<foreach item="metricId" collection="query.getMetricIds()" open="(" separator="," close=")">#{metricId}</foreach> | |||
</if> | |||
<if test="query.getMetricKeys() != null"> | |||
and m.name in | |||
<foreach item="metricKey" collection="query.getMetricKeys()" open="(" separator="," close=")"> | |||
#{metricKey} | |||
</foreach> | |||
</if> | |||
<choose> | |||
<when test="query.getPersonId() != null"> | |||
and person_id = #{query.personId} | |||
</when> | |||
<otherwise> | |||
and person_id is null | |||
</otherwise> | |||
</choose> | |||
</select> | |||
<select id="selectPastMeasures" parameterType="map" resultType="org.sonar.db.measure.PastMeasureDto"> |
@@ -105,12 +105,24 @@ public class MeasureDaoTest { | |||
@Test | |||
public void selectByQuery() { | |||
ComponentDto project = db.components().insertProject(); | |||
ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project)); | |||
ComponentDto project1 = db.components().insertProject(); | |||
ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project1)); | |||
db.components().insertComponent(newFileDto(module).setUuid("C1")); | |||
db.components().insertComponent(newFileDto(module).setUuid("C2")); | |||
insertAnalysis(LAST_ANALYSIS_UUID, project.uuid(), true); | |||
insertAnalysis(OTHER_ANALYSIS_UUID, project.uuid(), false); | |||
insertAnalysis(LAST_ANALYSIS_UUID, project1.uuid(), true); | |||
insertAnalysis(OTHER_ANALYSIS_UUID, project1.uuid(), false); | |||
String project2LastAnalysisUuid = "P2_LAST_ANALYSIS"; | |||
ComponentDto project2 = db.components().insertProject(); | |||
insertAnalysis(project2LastAnalysisUuid, project2.uuid(), true); | |||
// project 1 | |||
insertMeasure("P1_M1", LAST_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID); | |||
insertMeasure("P1_M1", LAST_ANALYSIS_UUID, project1.uuid(), COVERAGE_METRIC_ID); | |||
insertMeasure("P1_M3", OTHER_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID); | |||
// project 2 | |||
insertMeasure("P2_M1", project2LastAnalysisUuid, project2.uuid(), NCLOC_METRIC_ID); | |||
insertMeasure("P2_M2", project2LastAnalysisUuid, project2.uuid(), COVERAGE_METRIC_ID); | |||
// component C1 | |||
insertMeasure("M1", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID); | |||
insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID); | |||
@@ -121,8 +133,10 @@ public class MeasureDaoTest { | |||
insertMeasure("M6", LAST_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID); | |||
db.commit(); | |||
verifyZeroMeasures(MeasureQuery.builder().setComponentUuids(emptyList())); | |||
verifyZeroMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), emptyList())); | |||
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("MISSING_COMPONENT")); | |||
verifyZeroMeasures(MeasureQuery.builder().setProjectUuids(emptyList())); | |||
verifyZeroMeasures(MeasureQuery.builder().setProjectUuids(singletonList("MISSING_COMPONENT"))); | |||
// all measures of component C1 of last analysis | |||
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1"), "M2", "M3"); | |||
@@ -153,11 +167,11 @@ public class MeasureDaoTest { | |||
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setMetricId(COMPLEXITY_METRIC_ID)); | |||
// ncloc measures of components C1, C2 and C3 (which does not exist) of last analysis | |||
verifyMeasures(MeasureQuery.builder().setComponentUuids(asList("C1", "C2", "C3")), "M2", "M3", "M6"); | |||
verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")), "M2", "M3", "M6"); | |||
// ncloc measures of components C1, C2 and C3 (which does not exist) of non last analysis | |||
verifyMeasures(MeasureQuery.builder().setComponentUuids(asList("C1", "C2", "C3")).setAnalysisUuid(OTHER_ANALYSIS_UUID), "M1"); | |||
verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(OTHER_ANALYSIS_UUID), "M1"); | |||
// ncloc measures of components C1, C2 and C3 (which does not exist) of last analysis by UUID | |||
verifyMeasures(MeasureQuery.builder().setComponentUuids(asList("C1", "C2", "C3")).setAnalysisUuid(LAST_ANALYSIS_UUID), "M2", "M3", "M6"); | |||
verifyMeasures(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(LAST_ANALYSIS_UUID), "M2", "M3", "M6"); | |||
// measures of missing developer of component C1 of last analysis | |||
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setPersonId(123L)); | |||
@@ -172,15 +186,38 @@ public class MeasureDaoTest { | |||
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setPersonId(A_PERSON_ID)); | |||
// developer measures of component C1 of last analysis by UUID | |||
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setPersonId(A_PERSON_ID), "M4"); | |||
// projects measures of last analysis | |||
verifyMeasures(MeasureQuery.builder().setProjectUuids(singletonList(project1.uuid())).setMetricId(NCLOC_METRIC_ID), "P1_M1"); | |||
verifyMeasures(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid())).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), | |||
"P1_M1", "P2_M1", "P2_M2", "P2_M2"); | |||
verifyMeasures(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid(), "UNKNOWN")).setMetricId(NCLOC_METRIC_ID), "P1_M1", "P2_M1"); | |||
// projects measures of none last analysis | |||
verifyMeasures(MeasureQuery.builder().setProjectUuids(singletonList(project1.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(OTHER_ANALYSIS_UUID), "P1_M3"); | |||
verifyMeasures(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(OTHER_ANALYSIS_UUID), "P1_M3"); | |||
} | |||
@Test | |||
public void selectByQuery_with_handler() { | |||
ComponentDto project = db.components().insertProject(); | |||
db.components().insertComponent(newFileDto(project).setUuid("C1")); | |||
db.components().insertComponent(newFileDto(project).setUuid("C2")); | |||
insertAnalysis(LAST_ANALYSIS_UUID, project.uuid(), true); | |||
insertAnalysis(OTHER_ANALYSIS_UUID, project.uuid(), false); | |||
ComponentDto project1 = db.components().insertProject(); | |||
ComponentDto module = db.components().insertComponent(ComponentTesting.newModuleDto(project1)); | |||
db.components().insertComponent(newFileDto(module).setUuid("C1")); | |||
db.components().insertComponent(newFileDto(module).setUuid("C2")); | |||
insertAnalysis(LAST_ANALYSIS_UUID, project1.uuid(), true); | |||
insertAnalysis(OTHER_ANALYSIS_UUID, project1.uuid(), false); | |||
String project2LastAnalysisUuid = "P2_LAST_ANALYSIS"; | |||
ComponentDto project2 = db.components().insertProject(); | |||
insertAnalysis(project2LastAnalysisUuid, project2.uuid(), true); | |||
// project 1 | |||
insertMeasure("P1_M1", LAST_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID); | |||
insertMeasure("P1_M1", LAST_ANALYSIS_UUID, project1.uuid(), COVERAGE_METRIC_ID); | |||
insertMeasure("P1_M3", OTHER_ANALYSIS_UUID, project1.uuid(), NCLOC_METRIC_ID); | |||
// project 2 | |||
insertMeasure("P2_M1", project2LastAnalysisUuid, project2.uuid(), NCLOC_METRIC_ID); | |||
insertMeasure("P2_M2", project2LastAnalysisUuid, project2.uuid(), COVERAGE_METRIC_ID); | |||
// component C1 | |||
insertMeasure("M1", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID); | |||
insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID); | |||
@@ -191,8 +228,10 @@ public class MeasureDaoTest { | |||
insertMeasure("M6", LAST_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID); | |||
db.commit(); | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(emptyList())); | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(project1.uuid(), emptyList())); | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setComponentUuid("MISSING_COMPONENT")); | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setProjectUuids(emptyList())); | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setProjectUuids(singletonList("MISSING_COMPONENT"))); | |||
// all measures of component C1 of last analysis | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuid("C1"), "M2", "M3"); | |||
@@ -224,11 +263,11 @@ public class MeasureDaoTest { | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setMetricId(COMPLEXITY_METRIC_ID)); | |||
// ncloc measures of components C1, C2 and C3 (which does not exist) of last analysis | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(asList("C1", "C2", "C3")), "M2", "M3", "M6"); | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")), "M2", "M3", "M6"); | |||
// ncloc measures of components C1, C2 and C3 (which does not exist) of non last analysis | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(asList("C1", "C2", "C3")).setAnalysisUuid(OTHER_ANALYSIS_UUID), "M1"); | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(OTHER_ANALYSIS_UUID), "M1"); | |||
// ncloc measures of components C1, C2 and C3 (which does not exist) of last analysis by UUID | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(asList("C1", "C2", "C3")).setAnalysisUuid(LAST_ANALYSIS_UUID), "M2", "M3", "M6"); | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuids(project1.uuid(), asList("C1", "C2", "C3")).setAnalysisUuid(LAST_ANALYSIS_UUID), "M2", "M3", "M6"); | |||
// measures of missing developer of component C1 of last analysis | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setComponentUuid("C1").setPersonId(123L)); | |||
@@ -243,6 +282,17 @@ public class MeasureDaoTest { | |||
verifyZeroMeasuresWithHandler(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setPersonId(A_PERSON_ID)); | |||
// developer measures of component C1 of last analysis by UUID | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setPersonId(A_PERSON_ID), "M4"); | |||
// projects measures of last analysis | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setProjectUuids(singletonList(project1.uuid())).setMetricId(NCLOC_METRIC_ID), "P1_M1"); | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid())).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), | |||
"P1_M1", "P2_M1", "P2_M2", "P2_M2"); | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid(), "UNKNOWN")).setMetricId(NCLOC_METRIC_ID), "P1_M1", "P2_M1"); | |||
// projects measures of none last analysis | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setProjectUuids(singletonList(project1.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(OTHER_ANALYSIS_UUID), "P1_M3"); | |||
verifyMeasuresWithHandler(MeasureQuery.builder().setProjectUuids(asList(project1.uuid(), project2.uuid())).setMetricId(NCLOC_METRIC_ID).setAnalysisUuid(OTHER_ANALYSIS_UUID), | |||
"P1_M3"); | |||
} | |||
@Test | |||
@@ -254,7 +304,7 @@ public class MeasureDaoTest { | |||
insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", COMPLEXITY_METRIC_ID); | |||
db.commit(); | |||
assertThat(selectSingle(MeasureQuery.builder().setComponentUuids(emptyList()))).isNotPresent(); | |||
assertThat(selectSingle(MeasureQuery.builder().setComponentUuids(project.uuid(), emptyList()))).isNotPresent(); | |||
assertThat(selectSingle(MeasureQuery.builder().setComponentUuid("MISSING_COMPONENT"))).isNotPresent(); | |||
// select a single measure |
@@ -0,0 +1,140 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2016 SonarSource SA | |||
* mailto:contact AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* This program is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |||
* Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public License | |||
* along with this program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.db.measure; | |||
import java.util.Collections; | |||
import org.assertj.core.api.Java6Assertions; | |||
import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import static java.util.Arrays.asList; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
public class MeasureQueryTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
@Test | |||
public void create_query_from_projects() throws Exception { | |||
MeasureQuery query = MeasureQuery.builder().setProjectUuids(asList("PROJECT_1", "PROJECT_2")).build(); | |||
assertThat(query.getProjectUuids()).containsOnly("PROJECT_1", "PROJECT_2"); | |||
assertThat(query.isOnProjects()).isTrue(); | |||
assertThat(query.isOnComponents()).isFalse(); | |||
assertThat(query.isOnSingleComponent()).isFalse(); | |||
} | |||
@Test | |||
public void create_query_from_project_and_components() throws Exception { | |||
MeasureQuery query = MeasureQuery.builder().setComponentUuids("PROJECT_1", asList("FILE_1", "FILE_2")).build(); | |||
assertThat(query.getProjectUuids()).containsOnly("PROJECT_1"); | |||
assertThat(query.getProjectUuid()).isEqualTo("PROJECT_1"); | |||
assertThat(query.getComponentUuids()).containsOnly("FILE_1", "FILE_2"); | |||
assertThat(query.isOnProjects()).isFalse(); | |||
assertThat(query.isOnComponents()).isTrue(); | |||
assertThat(query.isOnSingleComponent()).isFalse(); | |||
} | |||
@Test | |||
public void create_query_from_single_component_uuid() throws Exception { | |||
MeasureQuery query = MeasureQuery.builder().setComponentUuid("FILE_1").build(); | |||
assertThat(query.getComponentUuids()).containsOnly("FILE_1"); | |||
assertThat(query.getComponentUuid()).isEqualTo("FILE_1"); | |||
assertThat(query.isOnProjects()).isFalse(); | |||
assertThat(query.isOnComponents()).isFalse(); | |||
assertThat(query.isOnSingleComponent()).isTrue(); | |||
} | |||
@Test | |||
public void create_query_from_metric_ids() throws Exception { | |||
MeasureQuery query = MeasureQuery.builder().setProjectUuids(asList("PROJECT_1", "PROJECT_2")).setMetricIds(asList(10, 11)).build(); | |||
assertThat(query.getMetricIds()).containsOnly(10, 11); | |||
assertThat(query.getMetricKeys()).isNull(); | |||
} | |||
@Test | |||
public void create_query_from_metric_keys() throws Exception { | |||
MeasureQuery query = MeasureQuery.builder().setProjectUuids(asList("PROJECT_1", "PROJECT_2")).setMetricKeys(asList("M1", "M2")).build(); | |||
assertThat(query.getMetricKeys()).containsOnly("M1", "M2"); | |||
assertThat(query.getMetricIds()).isNull(); | |||
} | |||
@Test | |||
public void create_query_from_person_id() throws Exception { | |||
MeasureQuery query = MeasureQuery.builder().setProjectUuids(asList("PROJECT_1", "PROJECT_2")).setPersonId(100L).build(); | |||
assertThat(query.getPersonId()).isEqualTo(100L); | |||
} | |||
@Test | |||
public void return_empty_when_metrics_are_empty() throws Exception { | |||
Java6Assertions.assertThat(MeasureQuery.builder() | |||
.setProjectUuids(asList("PROJECT_1", "PROJECT_2")) | |||
.setMetricKeys(Collections.emptyList()) | |||
.build().returnsEmpty()).isTrue(); | |||
Java6Assertions.assertThat(MeasureQuery.builder() | |||
.setProjectUuids(asList("PROJECT_1", "PROJECT_2")) | |||
.setMetricIds(Collections.emptyList()) | |||
.build().returnsEmpty()).isTrue(); | |||
} | |||
@Test | |||
public void return_empty_when_projects_are_empty() throws Exception { | |||
Java6Assertions.assertThat(MeasureQuery.builder() | |||
.setProjectUuids(Collections.emptyList()) | |||
.build().returnsEmpty()).isTrue(); | |||
} | |||
@Test | |||
public void return_empty_when_components_are_empty() throws Exception { | |||
Java6Assertions.assertThat(MeasureQuery.builder() | |||
.setComponentUuids("PROJECT", Collections.emptyList()) | |||
.build().returnsEmpty()).isTrue(); | |||
} | |||
@Test | |||
public void fail_when_no_component_uuid_filter() throws Exception { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("At least one filter on component UUID is expected"); | |||
MeasureQuery.builder().build(); | |||
} | |||
@Test | |||
public void fail_when_component_uuids_without_project_uuid() throws Exception { | |||
expectedException.expect(NullPointerException.class); | |||
MeasureQuery.builder().setComponentUuids(null, asList("FILE_1", "FILE_2")).build(); | |||
} | |||
@Test | |||
public void fail_when_using_metric_ids_and_metric_keys() throws Exception { | |||
expectedException.expect(IllegalArgumentException.class); | |||
expectedException.expectMessage("Metric IDs and keys must not be set both"); | |||
MeasureQuery.builder().setMetricIds(asList(10, 11)).setMetricKeys(asList("M1", "M2")).setProjectUuids(asList("PROJECT_1", "PROJECT_2")).build(); | |||
} | |||
} |