import java.util.Optional;
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
+import org.sonar.db.version.Select;
import static org.sonar.db.DatabaseUtils.executeLargeInputs;
return Optional.ofNullable(Iterables.getOnlyElement(measures, null));
}
+ /**
+ * 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}.
+ * <p>
+ * In addition, this method returns measures which are not associated to any developer, unless one is specified in
+ * {@link MeasureQuery#personId}.
+ * </p>
+ * <p>
+ * Returned measure can optionally be filtered metric (either by specifying {@link MeasureQuery#metricIds}
+ * or {@link MeasureQuery#metricKeys}).
+ * </p>
+ */
public List<MeasureDto> selectByQuery(DbSession dbSession, MeasureQuery query) {
if (query.returnsEmpty()) {
return Collections.emptyList();
});
}
+ public List<MeasureDto> selectByQuery(DbSession dbSession, MeasureQuery query, Select.RowHandler rowHandler) {
+ if (query.returnsEmpty()) {
+ return Collections.emptyList();
+ }
+ if (query.getComponentUuids() == null) {
+ return mapper(dbSession).selectByQuery(query, rowHandler);
+ }
+ return executeLargeInputs(query.getComponentUuids(), componentUuids -> {
+ MeasureQuery pageQuery = MeasureQuery.copyWithSubsetOfComponentUuids(query, componentUuids);
+ return mapper(dbSession).selectByQuery(pageQuery, rowHandler);
+ });
+ }
+
public List<PastMeasureDto> selectPastMeasures(DbSession dbSession,
String componentUuid,
String analysisUuid,
import java.util.List;
import org.apache.ibatis.annotations.Param;
+import org.sonar.db.version.Select;
public interface MeasureMapper {
List<MeasureDto> selectByQuery(@Param("query") MeasureQuery query);
+ List<MeasureDto> selectByQuery(@Param("query") MeasureQuery query, Select.RowHandler rowHandler);
+
List<PastMeasureDto> selectPastMeasures(@Param("componentUuid") String componentUuid, @Param("analysisUuid") String analysisUuid, @Param("metricIds") List<Integer> metricIds);
void insert(MeasureDto measureDto);
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 java.util.Collections.singletonList;
+import static java.util.Objects.requireNonNull;
public class MeasureQuery {
-
- @CheckForNull
private final String analysisUuid;
-
private final List<String> componentUuids;
-
@CheckForNull
private final Collection<Integer> metricIds;
-
@CheckForNull
private final Collection<String> metricKeys;
-
@CheckForNull
private final Long personId;
private MeasureQuery(Builder builder) {
- this(builder.componentUuids, builder.analysisUuid, builder.metricIds, builder.metricKeys, builder.personId);
+ this(builder.analysisUuid, builder.componentUuids, builder.metricIds, builder.metricKeys, builder.personId);
}
- private MeasureQuery(List<String> componentUuids,
- @Nullable String analysisUuid,
+ private MeasureQuery(@Nullable String analysisUuid,
+ List<String> componentUuids,
@Nullable Collection<Integer> metricIds,
@Nullable Collection<String> metricKeys,
@Nullable Long personId) {
- checkState(componentUuids != null, "Component UUIDs must be set");
+ requireNonNull(componentUuids, "Component UUIDs must be set");
checkState(metricIds == null || metricKeys == null, "Metric IDs and keys must not be set both");
- this.componentUuids = componentUuids;
this.analysisUuid = analysisUuid;
+ this.componentUuids = componentUuids;
this.metricIds = metricIds;
this.metricKeys = metricKeys;
this.personId = personId;
}
- public List<String> getComponentUuids() {
- return componentUuids;
- }
-
- @CheckForNull
public String getAnalysisUuid() {
return analysisUuid;
}
+ public List<String> getComponentUuids() {
+ return componentUuids;
+ }
+
@CheckForNull
public Collection<Integer> getMetricIds() {
return metricIds;
|| (metricKeys != null && metricKeys.isEmpty());
}
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ 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);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(analysisUuid, componentUuids, metricIds, metricKeys, personId);
+ }
+
public static Builder builder() {
return new Builder();
}
static MeasureQuery copyWithSubsetOfComponentUuids(MeasureQuery query, List<String> componentUuids) {
- return new MeasureQuery(componentUuids, query.analysisUuid, query.metricIds, query.metricKeys, query.personId);
+ return new MeasureQuery(query.analysisUuid, componentUuids, query.metricIds, query.metricKeys, query.personId);
}
public static final class Builder {
- private List<String> componentUuids;
private String analysisUuid;
+ private List<String> componentUuids;
private Collection<Integer> metricIds;
private Collection<String> metricKeys;
private Long personId;
// see MeasureQuery#builder()
}
+ public Builder setAnalysisUuid(String analysisUuid) {
+ this.analysisUuid = analysisUuid;
+ return this;
+ }
+
public Builder setComponentUuids(List<String> componentUuids) {
this.componentUuids = componentUuids;
return this;
return this;
}
- public Builder setAnalysisUuid(String s) {
- this.analysisUuid = s;
- return this;
- }
-
/**
* All the measures are returned if parameter is {@code null}.
*/
</sql>
<select id="selectByQuery" parameterType="map" resultType="Measure">
- select <include refid="measureColumns"/>
- from project_measures pm
- inner join snapshots analysis on analysis.uuid = pm.analysis_uuid
+ select
+ <include refid="measureColumns"/>
+ from
+ project_measures pm
+ inner join snapshots analysis on analysis.uuid = pm.analysis_uuid
+ <if test="query.getMetricKeys() != null">
+ inner join metrics m on m.id = pm.metric_id
+ </if>
where
- pm.component_uuid in
- <foreach item="componentUuid" collection="query.getComponentUuids()" open="(" separator="," close=")">
- #{componentUuid}
- </foreach>
- <choose>
- <when test="query.getAnalysisUuid() != null">
- and analysis.uuid in <foreach item="analysisUuid" collection="query.getAnalysisUuid()" open="(" separator="," close=")">#{analysisUuid}</foreach>
- </when>
- <otherwise>
- and analysis.islast=${_true}
- </otherwise>
- </choose>
- <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 pm.metric_id in (select id from metrics where 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 test="query.getAnalysisUuid() == null">
+ analysis.islast=${_true}
+ </if>
+ <if test="query.getAnalysisUuid() != null">
+ analysis.uuid = #{query.analysisUuid}
+ </if>
+ and pm.component_uuid in
+ <foreach item="componentUuid" collection="query.getComponentUuids()" open="(" separator="," close=")">
+ #{componentUuid}
+ </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>
</select>
<select id="selectPastMeasures" parameterType="map" resultType="org.sonar.db.measure.PastMeasureDto">
private static final int COMPLEXITY_METRIC_ID = 11;
private static final int NCLOC_METRIC_ID = 12;
private static final long A_PERSON_ID = 444L;
+ public static final String LAST_ANALYSIS_UUID = "A1";
+ public static final String OTHER_ANALYSIS_UUID = "A2";
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void test_inserted_and_selected_columns() {
- insertAnalysis("A1", true);
+ insertAnalysis(LAST_ANALYSIS_UUID, true);
MeasureDto inserted = new MeasureDto()
- .setAnalysisUuid("A1")
+ .setAnalysisUuid(LAST_ANALYSIS_UUID)
.setMetricId(2)
.setDeveloperId(3L)
.setComponentUuid("C4")
@Test
public void selectByQuery() {
- insertAnalysis("A1", false);
- insertAnalysis("A2", true);
+ insertAnalysis(LAST_ANALYSIS_UUID, true);
+ insertAnalysis(OTHER_ANALYSIS_UUID, false);
// component C1
- insertMeasure("M1", "A1", "C1", NCLOC_METRIC_ID);
- insertMeasure("M2", "A2", "C1", NCLOC_METRIC_ID);
- insertMeasure("M3", "A2", "C1", COVERAGE_METRIC_ID);
- insertMeasureOnPerson("M4", "A2", "C1", NCLOC_METRIC_ID, A_PERSON_ID);
+ insertMeasure("M1", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
+ insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
+ insertMeasure("M3", LAST_ANALYSIS_UUID, "C1", COVERAGE_METRIC_ID);
+ insertMeasureOnPerson("M4", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID, A_PERSON_ID);
+ insertMeasureOnPerson("M5", OTHER_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID, 123L);
// component C2
- insertMeasure("M5", "A2", "C2", NCLOC_METRIC_ID);
+ insertMeasure("M6", LAST_ANALYSIS_UUID, "C2", NCLOC_METRIC_ID);
db.commit();
verifyZeroMeasures(MeasureQuery.builder().setComponentUuids(emptyList()));
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("MISSING_COMPONENT"));
- // all measures of component C1
+ // all measures of component C1 of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1"), "M2", "M3");
+ // all measures of component C1 of non last analysis
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID), "M1");
+ // all measures of component C1 of last analysis by UUID
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID), "M2", "M3");
- // ncloc measure of component C1
+ // ncloc measure of component C1 of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setMetricId(NCLOC_METRIC_ID), "M2");
+ // ncloc measure of component C1 of non last analysis
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setMetricId(NCLOC_METRIC_ID), "M1");
+ // ncloc measure of component C1 of last analysis by UUID
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setMetricId(NCLOC_METRIC_ID), "M2");
- // multiple measures of component C1
+ // multiple measures of component C1 of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M2", "M3");
+ // multiple measures of component C1 of non last analysis
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M1");
+ // multiple measures of component C1 of last analysis by UUID
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setMetricIds(asList(NCLOC_METRIC_ID, COVERAGE_METRIC_ID)), "M2", "M3");
- // missing measure of component C1
+ // missing measure of component C1 of last analysis
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setMetricId(COMPLEXITY_METRIC_ID));
-
- // ncloc measures of components C1, C2 and C3 (which does not exist)
- verifyMeasures(MeasureQuery.builder().setComponentUuids(asList("C1", "C2", "C3")), "M2", "M3", "M5");
-
- // measures of missing developer of component C1
+ // missing measure of component C1 of non last analysis
+ verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setMetricId(COMPLEXITY_METRIC_ID));
+ // missing measure of component C1 of last analysis by UUID
+ 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");
+ // 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");
+ // 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");
+
+ // measures of missing developer of component C1 of last analysis
verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setPersonId(123L));
+ // measures of missing developer of component C1 of non last analysis
+ verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(OTHER_ANALYSIS_UUID).setPersonId(123L), "M5");
+ // measures of missing developer of component C1 of last analysis by UUID
+ verifyZeroMeasures(MeasureQuery.builder().setComponentUuid("C1").setAnalysisUuid(LAST_ANALYSIS_UUID).setPersonId(123L));
- // developer measures of component C1
+ // developer measures of component C1 of last analysis
verifyMeasures(MeasureQuery.builder().setComponentUuid("C1").setPersonId(A_PERSON_ID), "M4");
+ // developer measures of component C1 of non last analysis
+ 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");
}
@Test
public void selectSingle() {
- insertAnalysis("A1", true);
- insertMeasure("M1", "A1", "C1", NCLOC_METRIC_ID);
- insertMeasure("M2", "A1", "C1", COMPLEXITY_METRIC_ID);
+ insertAnalysis(LAST_ANALYSIS_UUID, true);
+ insertMeasure("M1", LAST_ANALYSIS_UUID, "C1", NCLOC_METRIC_ID);
+ insertMeasure("M2", LAST_ANALYSIS_UUID, "C1", COMPLEXITY_METRIC_ID);
db.commit();
assertThat(selectSingle(MeasureQuery.builder().setComponentUuids(emptyList()))).isNotPresent();