]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7780 add MeasureQuery.analysisUuid
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Mon, 4 Jul 2016 15:30:20 +0000 (17:30 +0200)
committerSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Thu, 7 Jul 2016 15:06:59 +0000 (17:06 +0200)
required by Governance

sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java
sonar-db/src/main/java/org/sonar/db/measure/MeasureMapper.java
sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java
sonar-db/src/main/resources/org/sonar/db/measure/MeasureMapper.xml
sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java

index 2e27a2c9509aa1a1e9fec92303f3493b9b4fd050..ebaaa1042e8089839441154892fffc3a1a3aca92 100644 (file)
@@ -27,6 +27,7 @@ import java.util.List;
 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;
 
@@ -37,6 +38,19 @@ public class MeasureDao implements Dao {
     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();
@@ -50,6 +64,19 @@ public class MeasureDao implements Dao {
     });
   }
 
+  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,
index 734ab6e7d49652aeec22c169bbdcb39749b24bf8..7a6aa3a34bd1d565c05500b80e21d6d11cf7c267 100644 (file)
@@ -21,11 +21,14 @@ package org.sonar.db.measure;
 
 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);
index 2d6604b8e68697f9ea6b2351955678fbbd189175..80b49427fccb99a65233c272fb22ceeefbc89703 100644 (file)
@@ -21,56 +21,51 @@ 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 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;
@@ -92,17 +87,38 @@ public class MeasureQuery {
       || (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;
@@ -111,6 +127,11 @@ public class MeasureQuery {
       // see MeasureQuery#builder()
     }
 
+    public Builder setAnalysisUuid(String analysisUuid) {
+      this.analysisUuid = analysisUuid;
+      return this;
+    }
+
     public Builder setComponentUuids(List<String> componentUuids) {
       this.componentUuids = componentUuids;
       return this;
@@ -121,11 +142,6 @@ public class MeasureQuery {
       return this;
     }
 
-    public Builder setAnalysisUuid(String s) {
-      this.analysisUuid = s;
-      return this;
-    }
-
     /**
      * All the measures are returned if parameter is {@code null}.
      */
index 7e7c0dca712ab6ea32e986afdfd9d0e7526df6d1..26a8278ede016d9f0584e208675cc36a61cf07d7 100644 (file)
   </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">
index c2865ca4a76f9037bfe92b14aa648f7d020ea534..b0f6db7870d9a5d07f20f47a8ba0c37443d3dad5 100644 (file)
@@ -38,6 +38,8 @@ public class MeasureDaoTest {
   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();
@@ -49,10 +51,10 @@ public class MeasureDaoTest {
 
   @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")
@@ -90,47 +92,76 @@ public class MeasureDaoTest {
 
   @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();