Replace streaming of projects by first loading all projects once, then load measures project by project
return this;
}
- public ProjectMeasuresDoc setMeasuresFromMap(Map<String, Object> measures) {
+ public ProjectMeasuresDoc setMeasuresFromMap(Map<String, Double> measures) {
setMeasures(
measures.entrySet().stream()
- .map(entry -> ImmutableMap.of(
+ .map(entry -> ImmutableMap.<String, Object>of(
ProjectMeasuresIndexDefinition.FIELD_MEASURES_KEY, entry.getKey(),
ProjectMeasuresIndexDefinition.FIELD_MEASURES_VALUE, entry.getValue()))
.collect(Collectors.toList()));
import org.elasticsearch.action.index.IndexRequest;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
+import org.sonar.db.measure.ProjectMeasuresIndexerIterator;
+import org.sonar.db.measure.ProjectMeasuresIndexerIterator.ProjectMeasures;
import org.sonar.server.es.BaseIndexer;
import org.sonar.server.es.BulkIndexer;
import org.sonar.server.es.EsClient;
}
private long doIndex(BulkIndexer bulk, long lastUpdatedAt, @Nullable String projectUuid) {
- try (DbSession dbSession = dbClient.openSession(false)) {
- ProjectMeasuresResultSetIterator rowIt = ProjectMeasuresResultSetIterator.create(dbClient, dbSession, lastUpdatedAt, projectUuid);
- long maxDate = doIndex(bulk, rowIt);
- rowIt.close();
- return maxDate;
+ try (DbSession dbSession = dbClient.openSession(false);
+ ProjectMeasuresIndexerIterator rowIt = ProjectMeasuresIndexerIterator.create(dbSession, lastUpdatedAt, projectUuid)) {
+ return doIndex(bulk, rowIt);
}
}
- private static long doIndex(BulkIndexer bulk, Iterator<ProjectMeasuresDoc> docs) {
+ private static long doIndex(BulkIndexer bulk, Iterator<ProjectMeasures> docs) {
bulk.start();
long maxDate = 0L;
while (docs.hasNext()) {
- ProjectMeasuresDoc doc = docs.next();
- bulk.add(newIndexRequest(doc));
+ ProjectMeasures doc = docs.next();
+ bulk.add(newIndexRequest(toProjectMeasuresDoc(doc)));
- Date analysisDate = doc.getAnalysedAt();
+ Long analysisDate = doc.getProject().getAnalysisDate();
// it's more efficient to sort programmatically than in SQL on some databases (MySQL for instance)
- maxDate = Math.max(maxDate, analysisDate == null ? 0L : analysisDate.getTime());
+ maxDate = Math.max(maxDate, analysisDate == null ? 0L : analysisDate);
}
bulk.stop();
return maxDate;
}
private static IndexRequest newIndexRequest(ProjectMeasuresDoc doc) {
- return new IndexRequest(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES, doc.getId())
- .routing(doc.getId())
- .parent(doc.getId())
+ String projectUuid = doc.getId();
+ return new IndexRequest(INDEX_PROJECT_MEASURES, TYPE_PROJECT_MEASURES, projectUuid)
+ .routing(projectUuid)
+ .parent(projectUuid)
.source(doc.getFields());
}
+
+ private static ProjectMeasuresDoc toProjectMeasuresDoc(ProjectMeasures projectMeasures) {
+ Long analysisDate = projectMeasures.getProject().getAnalysisDate();
+ return new ProjectMeasuresDoc()
+ .setId(projectMeasures.getProject().getUuid())
+ .setKey(projectMeasures.getProject().getKey())
+ .setName(projectMeasures.getProject().getName())
+ .setQualityGate(projectMeasures.getMeasures().getQualityGateStatus())
+ .setAnalysedAt(analysisDate == null ? null : new Date(analysisDate))
+ .setMeasuresFromMap(projectMeasures.getMeasures().getNumericMeasures());
+ }
}
+++ /dev/null
-/*
- * 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.server.component.es;
-
-import com.google.common.base.Joiner;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.resources.Qualifiers;
-import org.sonar.api.resources.Scopes;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.ResultSetIterator;
-
-import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
-import static org.sonar.api.measures.Metric.ValueType.DATA;
-import static org.sonar.api.measures.Metric.ValueType.DISTRIB;
-import static org.sonar.db.DatabaseUtils.repeatCondition;
-
-public class ProjectMeasuresResultSetIterator extends ResultSetIterator<ProjectMeasuresDoc> {
-
- private static final Joiner METRICS_JOINER = Joiner.on("','");
-
- private static final String SQL_PROJECTS = "SELECT p.uuid, p.kee, p.name, s.uuid, s.created_at FROM projects p " +
- "LEFT OUTER JOIN snapshots s ON s.component_uuid=p.uuid AND s.islast=? " +
- "WHERE p.enabled=? AND p.scope=? AND p.qualifier=?";
-
- private static final String DATE_FILTER = " AND s.created_at>?";
-
- private static final String PROJECT_FILTER = " AND p.uuid=?";
-
- private static final String SQL_METRICS = "SELECT m.id, m.name FROM metrics m " +
- "WHERE m.val_type NOT IN ('" + METRICS_JOINER.join(DATA.name(), DISTRIB.name()) + "') " +
- "AND m.enabled=? AND m.hidden=?";
-
- private static final String SQL_MEASURES = "SELECT pm.metric_id, pm.value, pm.variation_value_1, pm.text_value FROM project_measures pm " +
- "WHERE pm.component_uuid = ? AND pm.analysis_uuid = ? " +
- "AND pm.metric_id IN ({metricIds}) " +
- "AND (pm.value IS NOT NULL OR pm.variation_value_1 IS NOT NULL OR pm.text_value IS NOT NULL) " +
- "AND pm.person_id IS NULL ";
-
- private final DbSession dbSession;
- private final Map<Long, String> metrics;
-
- private ProjectMeasuresResultSetIterator(PreparedStatement stmt, DbSession dbSession, Map<Long, String> metrics) throws SQLException {
- super(stmt);
- this.dbSession = dbSession;
- this.metrics = metrics;
- }
-
- static ProjectMeasuresResultSetIterator create(DbClient dbClient, DbSession session, long afterDate, @Nullable String projectUuid) {
- try {
- PreparedStatement projectsStatement = createProjectsStatement(dbClient, session, afterDate, projectUuid);
- Map<Long, String> metricIds = selectMetricIds(session);
- return new ProjectMeasuresResultSetIterator(projectsStatement, session, metricIds);
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to execute request to select all project measures", e);
- }
- }
-
- private static PreparedStatement createProjectsStatement(DbClient dbClient, DbSession session, long afterDate, @Nullable String projectUuid) {
- try {
- String sql = SQL_PROJECTS;
- sql += afterDate <= 0L ? "" : DATE_FILTER;
- sql += projectUuid == null ? "" : PROJECT_FILTER;
- PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql);
- stmt.setBoolean(1, true);
- stmt.setBoolean(2, true);
- stmt.setString(3, Scopes.PROJECT);
- stmt.setString(4, Qualifiers.PROJECT);
- int index = 5;
- if (afterDate > 0L) {
- stmt.setLong(index, afterDate);
- index++;
- }
- if (projectUuid != null) {
- stmt.setString(index, projectUuid);
- }
- return stmt;
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to prepare SQL request to select all project measures", e);
- }
- }
-
- private static Map<Long, String> selectMetricIds(DbSession session) {
- Map<Long, String> metrics = new HashMap<>();
- try (PreparedStatement stmt = createMetricsStatement(session);
- ResultSet rs = stmt.executeQuery()) {
- while (rs.next()) {
- metrics.put(rs.getLong(1), rs.getString(2));
- }
- return metrics;
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to execute request to select all metrics", e);
- }
- }
-
- private static PreparedStatement createMetricsStatement(DbSession session) throws SQLException {
- PreparedStatement stmt = session.getConnection().prepareStatement(SQL_METRICS);
- stmt.setBoolean(1, true);
- stmt.setBoolean(2, false);
- return stmt;
- }
-
- @Override
- protected ProjectMeasuresDoc read(ResultSet rs) throws SQLException {
- String projectUuid = rs.getString(1);
- Measures measures = selectMeasures(projectUuid, getString(rs, 4));
- ProjectMeasuresDoc doc = new ProjectMeasuresDoc()
- .setId(projectUuid)
- .setKey(rs.getString(2))
- .setName(rs.getString(3))
- .setQualityGate(measures.getQualityGateStatus())
- .setMeasuresFromMap(measures.getNumericMeasures());
- long analysisDate = rs.getLong(5);
- doc.setAnalysedAt(rs.wasNull() ? null : new Date(analysisDate));
- return doc;
- }
-
- private Measures selectMeasures(String projectUuid, Optional<String> analysisUuid) {
- Measures measures = new Measures();
- if (!analysisUuid.isPresent()) {
- return measures;
- }
- try (PreparedStatement stmt = createMeasuresStatement(projectUuid, analysisUuid.get());
- ResultSet rs = stmt.executeQuery()) {
- while (rs.next()) {
- readMeasure(rs, measures);
- }
- return measures;
- } catch (Exception e) {
- throw new IllegalStateException(String.format("Fail to execute request to select measures of project %s, analysis %s", projectUuid, analysisUuid), e);
- }
- }
-
- private void readMeasure(ResultSet rs, Measures measures) throws SQLException {
- String metricKey = metrics.get(rs.getLong(1));
- Optional<Double> value = metricKey.startsWith("new_") ? getDouble(rs, 3) : getDouble(rs, 2);
- if (value.isPresent()) {
- measures.addNumericMeasure(metricKey, value.get());
- return;
- } else if (ALERT_STATUS_KEY.equals(metricKey)) {
- String textValue = rs.getString(4);
- if (!rs.wasNull()) {
- measures.setQualityGateStatus(textValue);
- return;
- }
- }
- throw new IllegalArgumentException("Measure has no value");
- }
-
- private PreparedStatement createMeasuresStatement(String projectUuid, String analysisUuid) throws SQLException {
- String sql = StringUtils.replace(SQL_MEASURES, "{metricIds}", repeatCondition("?", metrics.size(), ","));
- PreparedStatement stmt = dbSession.getConnection().prepareStatement(sql);
- stmt.setString(1, projectUuid);
- stmt.setString(2, analysisUuid);
- int index = 3;
- for (Long metricId : metrics.keySet()) {
- stmt.setLong(index, metricId);
- index++;
- }
- return stmt;
- }
-
- private static Optional<Double> getDouble(ResultSet rs, int index) {
- try {
- Double value = rs.getDouble(index);
- if (!rs.wasNull()) {
- return Optional.of(value);
- }
- return Optional.empty();
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to get double value", e);
- }
- }
-
- private static Optional<String> getString(ResultSet rs, int index) {
- try {
- String value = rs.getString(index);
- if (!rs.wasNull()) {
- return Optional.of(value);
- }
- return Optional.empty();
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to get string value", e);
- }
- }
-
- private static class Measures {
- private Map<String, Object> numericMeasures = new HashMap<>();
- private String qualityGateStatus;
-
- Measures addNumericMeasure(String metricKey, double value) {
- numericMeasures.put(metricKey, value);
- return this;
- }
-
- public Map<String, Object> getNumericMeasures() {
- return numericMeasures;
- }
-
- Measures setQualityGateStatus(@Nullable String qualityGateStatus) {
- this.qualityGateStatus = qualityGateStatus;
- return this;
- }
-
- @CheckForNull
- public String getQualityGateStatus() {
- return qualityGateStatus;
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.server.component.es;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-import java.util.Date;
-import java.util.Map;
-import javax.annotation.Nullable;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.sonar.api.measures.Metric;
-import org.sonar.api.utils.System2;
-import org.sonar.db.DbClient;
-import org.sonar.db.DbSession;
-import org.sonar.db.DbTester;
-import org.sonar.db.component.ComponentDbTester;
-import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.SnapshotDto;
-import org.sonar.db.measure.MeasureDto;
-import org.sonar.db.measure.MeasureTesting;
-import org.sonar.db.metric.MetricDto;
-import org.sonar.db.metric.MetricTesting;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.sonar.api.measures.Metric.ValueType.DATA;
-import static org.sonar.api.measures.Metric.ValueType.DISTRIB;
-import static org.sonar.api.measures.Metric.ValueType.INT;
-import static org.sonar.api.measures.Metric.ValueType.LEVEL;
-import static org.sonar.db.component.ComponentTesting.newDeveloper;
-import static org.sonar.db.component.ComponentTesting.newProjectDto;
-import static org.sonar.db.component.ComponentTesting.newView;
-import static org.sonar.db.component.SnapshotTesting.newAnalysis;
-import static org.sonar.server.computation.task.projectanalysis.measure.Measure.Level.WARN;
-
-public class ProjectMeasuresResultSetIteratorTest {
-
- @Rule
- public ExpectedException expectedException = ExpectedException.none();
-
- @Rule
- public DbTester dbTester = DbTester.create(System2.INSTANCE);
-
- DbClient dbClient = dbTester.getDbClient();
- DbSession dbSession = dbTester.getSession();
-
- ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
-
- @Test
- public void return_project_measure() {
- MetricDto metric1 = insertIntMetric("ncloc");
- MetricDto metric2 = insertIntMetric("coverage");
- ComponentDto project = newProjectDto().setKey("Project-Key").setName("Project Name");
- SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, metric1, 10d);
- insertMeasure(project, analysis, metric2, 20d);
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
-
- assertThat(docsById).hasSize(1);
- ProjectMeasuresDoc doc = docsById.get(project.uuid());
- assertThat(doc).isNotNull();
- assertThat(doc.getId()).isEqualTo(project.uuid());
- assertThat(doc.getKey()).isEqualTo("Project-Key");
- assertThat(doc.getName()).isEqualTo("Project Name");
- assertThat(doc.getAnalysedAt()).isNotNull().isEqualTo(new Date(analysis.getCreatedAt()));
- assertThat(doc.getMeasures()).containsOnly(
- ImmutableMap.of("key", "ncloc", "value", 10d),
- ImmutableMap.of("key", "coverage", "value", 20d));
- }
-
- @Test
- public void return_project_measure_having_leak() throws Exception {
- MetricDto metric = insertIntMetric("new_lines");
- ComponentDto project = newProjectDto();
- SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- insertMeasureOnLeak(project, analysis, metric, 10d);
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
-
- assertThat(docsById).hasSize(1);
- ProjectMeasuresDoc doc = docsById.get(project.uuid());
- assertThat(doc).isNotNull();
- assertThat(doc.getMeasures()).containsOnly(ImmutableMap.of("key", "new_lines", "value", 10d));
- }
-
- @Test
- public void return_quality_gate_status_measure() throws Exception {
- MetricDto metric = insertMetric("alert_status", LEVEL);
- ComponentDto project = newProjectDto();
- SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, metric, WARN.name());
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
-
- assertThat(docsById).hasSize(1);
- assertThat(docsById.get(project.uuid()).getQualityGate()).isEqualTo("WARN");
- }
-
- @Test
- public void does_not_return_none_numeric_metrics() throws Exception {
- MetricDto dataMetric = insertMetric("data", DATA);
- MetricDto distribMetric = insertMetric("distrib", DISTRIB);
- ComponentDto project = newProjectDto();
- SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, dataMetric, 10d);
- insertMeasure(project, analysis, distribMetric, 10d);
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
- assertThat(docsById).hasSize(1);
- ProjectMeasuresDoc doc = docsById.get(project.uuid());
- assertThat(doc.getMeasures()).isEmpty();
- }
-
- @Test
- public void does_not_return_disabled_and_hidden_metrics() throws Exception {
- MetricDto disabledMetric = insertMetric("disabled", false, false, INT);
- MetricDto hiddenMetric = insertMetric("hidden", true, true, INT);
- ComponentDto project = newProjectDto();
- SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, disabledMetric, 10d);
- insertMeasure(project, analysis, hiddenMetric, 10d);
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
- assertThat(docsById).hasSize(1);
- ProjectMeasuresDoc doc = docsById.get(project.uuid());
- assertThat(doc.getMeasures()).isEmpty();
- }
-
- @Test
- public void fail_when_measure_return_no_value() throws Exception {
- MetricDto metric = insertIntMetric("new_lines");
- ComponentDto project = newProjectDto();
- SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- insertMeasure(project, analysis, metric, 10d);
-
- expectedException.expect(IllegalStateException.class);
- createResultSetAndReturnDocsById();
- }
-
- @Test
- public void return_many_project_measures() {
- componentDbTester.insertProjectAndSnapshot(newProjectDto());
- componentDbTester.insertProjectAndSnapshot(newProjectDto());
- componentDbTester.insertProjectAndSnapshot(newProjectDto());
-
- assertThat(createResultSetAndReturnDocsById()).hasSize(3);
- }
-
- @Test
- public void return_project_without_analysis() throws Exception {
- ComponentDto project = componentDbTester.insertComponent(newProjectDto());
- dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setLast(false));
- dbSession.commit();
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById();
-
- assertThat(docsById).hasSize(1);
- ProjectMeasuresDoc doc = docsById.get(project.uuid());
- assertThat(doc.getAnalysedAt()).isNull();
- }
-
- @Test
- public void does_not_return_non_active_projects() throws Exception {
- // Disabled project
- componentDbTester.insertProjectAndSnapshot(newProjectDto().setEnabled(false));
- // Disabled project with analysis
- ComponentDto project = componentDbTester.insertComponent(newProjectDto().setEnabled(false));
- dbClient.snapshotDao().insert(dbSession, newAnalysis(project));
-
- // A view
- componentDbTester.insertProjectAndSnapshot(newView());
-
- // A developer
- componentDbTester.insertProjectAndSnapshot(newDeveloper("dev"));
-
- dbSession.commit();
-
- assertResultSetIsEmpty();
- }
-
- @Test
- public void return_only_docs_from_given_project() throws Exception {
- ComponentDto project = newProjectDto();
- SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
- componentDbTester.insertProjectAndSnapshot(newProjectDto());
- componentDbTester.insertProjectAndSnapshot(newProjectDto());
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(0L, project.uuid());
-
- assertThat(docsById).hasSize(1);
- ProjectMeasuresDoc doc = docsById.get(project.uuid());
- assertThat(doc).isNotNull();
- assertThat(doc.getId()).isEqualTo(project.uuid());
- assertThat(doc.getKey()).isNotNull().isEqualTo(project.getKey());
- assertThat(doc.getName()).isNotNull().isEqualTo(project.name());
- assertThat(doc.getAnalysedAt()).isNotNull().isEqualTo(new Date(analysis.getCreatedAt()));
- }
-
- @Test
- public void return_only_docs_after_date() throws Exception {
- ComponentDto project1 = newProjectDto();
- dbClient.componentDao().insert(dbSession, project1);
- dbClient.snapshotDao().insert(dbSession, newAnalysis(project1).setCreatedAt(1_000_000L));
- ComponentDto project2 = newProjectDto();
- dbClient.componentDao().insert(dbSession, project2);
- dbClient.snapshotDao().insert(dbSession, newAnalysis(project2).setCreatedAt(2_000_000L));
- dbSession.commit();
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(1_500_000L, null);
-
- assertThat(docsById).hasSize(1);
- assertThat(docsById.get(project2.uuid())).isNotNull();
- }
-
- @Test
- public void return_nothing_on_unknown_project() throws Exception {
- componentDbTester.insertProjectAndSnapshot(newProjectDto());
-
- Map<String, ProjectMeasuresDoc> docsById = createResultSetAndReturnDocsById(0L, "UNKNOWN");
-
- assertThat(docsById).isEmpty();
- }
-
- private Map<String, ProjectMeasuresDoc> createResultSetAndReturnDocsById() {
- return createResultSetAndReturnDocsById(0L, null);
- }
-
- private Map<String, ProjectMeasuresDoc> createResultSetAndReturnDocsById(long date, @Nullable String projectUuid) {
- ProjectMeasuresResultSetIterator it = ProjectMeasuresResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), date, projectUuid);
- Map<String, ProjectMeasuresDoc> docsById = Maps.uniqueIndex(it, ProjectMeasuresDoc::getId);
- it.close();
- return docsById;
- }
-
- private void assertResultSetIsEmpty() {
- assertThat(createResultSetAndReturnDocsById()).isEmpty();
- }
-
- private MetricDto insertIntMetric(String metricKey) {
- return insertMetric(metricKey, true, false, INT);
- }
-
- private MetricDto insertMetric(String metricKey, Metric.ValueType type) {
- return insertMetric(metricKey, true, false, type);
- }
-
- private MetricDto insertMetric(String metricKey, boolean enabled, boolean hidden, Metric.ValueType type) {
- MetricDto metric = dbClient.metricDao().insert(dbSession,
- MetricTesting.newMetricDto()
- .setKey(metricKey)
- .setEnabled(enabled)
- .setHidden(hidden)
- .setValueType(type.name()));
- dbSession.commit();
- return metric;
- }
-
- private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, double value) {
- return insertMeasure(project, analysis, metric, value, null);
- }
-
- private MeasureDto insertMeasureOnLeak(ComponentDto project, SnapshotDto analysis, MetricDto metric, double value) {
- return insertMeasure(project, analysis, metric, null, value);
- }
-
- private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, String value) {
- return insertMeasure(MeasureTesting.newMeasureDto(metric, project, analysis).setData(value));
- }
-
- private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, @Nullable Double value, @Nullable Double leakValue) {
- return insertMeasure(MeasureTesting.newMeasureDto(metric, project, analysis).setValue(value).setVariation(1, leakValue));
- }
-
- private MeasureDto insertMeasure(MeasureDto measure) {
- dbClient.measureDao().insert(dbSession, measure);
- dbSession.commit();
- return measure;
- }
-
-}
--- /dev/null
+/*
+ * 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 com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableSet;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.Scopes;
+import org.sonar.core.util.CloseableIterator;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.db.DbSession;
+
+import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
+import static org.sonar.api.measures.Metric.ValueType.BOOL;
+import static org.sonar.api.measures.Metric.ValueType.FLOAT;
+import static org.sonar.api.measures.Metric.ValueType.INT;
+import static org.sonar.api.measures.Metric.ValueType.LEVEL;
+import static org.sonar.api.measures.Metric.ValueType.MILLISEC;
+import static org.sonar.api.measures.Metric.ValueType.PERCENT;
+import static org.sonar.api.measures.Metric.ValueType.RATING;
+import static org.sonar.api.measures.Metric.ValueType.WORK_DUR;
+import static org.sonar.db.DatabaseUtils.repeatCondition;
+
+public class ProjectMeasuresIndexerIterator extends CloseableIterator<ProjectMeasuresIndexerIterator.ProjectMeasures> {
+
+ private static final Set<String> METRIC_TYPES = ImmutableSet.of(INT.name(), FLOAT.name(), PERCENT.name(), BOOL.name(), MILLISEC.name(), LEVEL.name(), RATING.name(),
+ WORK_DUR.name());
+
+ private static final Joiner METRICS_JOINER = Joiner.on("','");
+
+ private static final String SQL_PROJECTS = "SELECT p.uuid, p.kee, p.name, s.uuid, s.created_at FROM projects p " +
+ "LEFT OUTER JOIN snapshots s ON s.component_uuid=p.uuid AND s.islast=? " +
+ "WHERE p.enabled=? AND p.scope=? AND p.qualifier=?";
+
+ private static final String DATE_FILTER = " AND s.created_at>?";
+
+ private static final String PROJECT_FILTER = " AND p.uuid=?";
+
+ private static final String SQL_METRICS = "SELECT m.id, m.name FROM metrics m " +
+ "WHERE m.val_type IN ('" + METRICS_JOINER.join(METRIC_TYPES) + "') " +
+ "AND m.enabled=?";
+
+ private static final String SQL_MEASURES = "SELECT pm.metric_id, pm.value, pm.variation_value_1, pm.text_value FROM project_measures pm " +
+ "WHERE pm.component_uuid = ? AND pm.analysis_uuid = ? " +
+ "AND pm.metric_id IN ({metricIds}) " +
+ "AND (pm.value IS NOT NULL OR pm.variation_value_1 IS NOT NULL OR pm.text_value IS NOT NULL) " +
+ "AND pm.person_id IS NULL ";
+
+ private final PreparedStatement measuresStatement;
+ private final Map<Long, String> metricKeysByIds;
+ private final Iterator<Project> projects;
+
+ private ProjectMeasuresIndexerIterator(PreparedStatement measuresStatement, Map<Long, String> metricKeysByIds, List<Project> projects) throws SQLException {
+ this.measuresStatement = measuresStatement;
+ this.metricKeysByIds = metricKeysByIds;
+ this.projects = projects.iterator();
+ }
+
+ public static ProjectMeasuresIndexerIterator create(DbSession session, long afterDate, @Nullable String projectUuid) {
+ try {
+ Map<Long, String> metrics = selectMetricKeysByIds(session);
+ List<Project> projects = selectProjects(session, afterDate, projectUuid);
+ PreparedStatement projectsStatement = createMeasuresStatement(session, metrics.keySet());
+ return new ProjectMeasuresIndexerIterator(projectsStatement, metrics, projects);
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to execute request to select all project measures", e);
+ }
+ }
+
+ private static Map<Long, String> selectMetricKeysByIds(DbSession session) {
+ Map<Long, String> metrics = new HashMap<>();
+ try (PreparedStatement stmt = createMetricsStatement(session);
+ ResultSet rs = stmt.executeQuery()) {
+ while (rs.next()) {
+ metrics.put(rs.getLong(1), rs.getString(2));
+ }
+ return metrics;
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to execute request to select all metrics", e);
+ }
+ }
+
+ private static PreparedStatement createMetricsStatement(DbSession session) throws SQLException {
+ PreparedStatement stmt = session.getConnection().prepareStatement(SQL_METRICS);
+ stmt.setBoolean(1, true);
+ return stmt;
+ }
+
+ private static List<Project> selectProjects(DbSession session, long afterDate, @Nullable String projectUuid) {
+ List<Project> projects = new ArrayList<>();
+ try (PreparedStatement stmt = createProjectsStatement(session, afterDate, projectUuid);
+ ResultSet rs = stmt.executeQuery()) {
+ while (rs.next()) {
+ long analysisDate = rs.getLong(5);
+ Project project = new Project(rs.getString(1), rs.getString(2), rs.getString(3), getString(rs, 4).orElseGet(() -> null), rs.wasNull() ? null : analysisDate);
+ projects.add(project);
+ }
+ return projects;
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to execute request to select all projects", e);
+ }
+ }
+
+ private static PreparedStatement createProjectsStatement(DbSession session, long afterDate, @Nullable String projectUuid) {
+ try {
+ String sql = SQL_PROJECTS;
+ sql += afterDate <= 0L ? "" : DATE_FILTER;
+ sql += projectUuid == null ? "" : PROJECT_FILTER;
+ PreparedStatement stmt = session.getConnection().prepareStatement(sql);
+ stmt.setBoolean(1, true);
+ stmt.setBoolean(2, true);
+ stmt.setString(3, Scopes.PROJECT);
+ stmt.setString(4, Qualifiers.PROJECT);
+ int index = 5;
+ if (afterDate > 0L) {
+ stmt.setLong(index, afterDate);
+ index++;
+ }
+ if (projectUuid != null) {
+ stmt.setString(index, projectUuid);
+ }
+ return stmt;
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to prepare SQL request to select all project measures", e);
+ }
+ }
+
+ private static PreparedStatement createMeasuresStatement(DbSession session, Set<Long> metricIds) throws SQLException {
+ try {
+ String sql = StringUtils.replace(SQL_MEASURES, "{metricIds}", repeatCondition("?", metricIds.size(), ","));
+ PreparedStatement stmt = session.getConnection().prepareStatement(sql);
+ int index = 3;
+ for (Long metricId : metricIds) {
+ stmt.setLong(index, metricId);
+ index++;
+ }
+ return stmt;
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to prepare SQL request to select measures", e);
+ }
+ }
+
+ @Override
+ @CheckForNull
+ protected ProjectMeasures doNext() {
+ if (!projects.hasNext()) {
+ return null;
+ }
+ Project project = projects.next();
+ Measures measures = selectMeasures(project.getUuid(), project.getAnalysisUuid());
+ return new ProjectMeasures(project, measures);
+ }
+
+ private Measures selectMeasures(String projectUuid, @Nullable String analysisUuid) {
+ Measures measures = new Measures();
+ if (analysisUuid == null || metricKeysByIds.isEmpty()) {
+ return measures;
+ }
+ ResultSet rs = null;
+ try {
+ measuresStatement.setString(1, projectUuid);
+ measuresStatement.setString(2, analysisUuid);
+ rs = measuresStatement.executeQuery();
+ while (rs.next()) {
+ readMeasure(rs, measures);
+ }
+ return measures;
+ } catch (Exception e) {
+ throw new IllegalStateException(String.format("Fail to execute request to select measures of project %s, analysis %s", projectUuid, analysisUuid), e);
+ } finally {
+ DatabaseUtils.closeQuietly(rs);
+ }
+ }
+
+ private void readMeasure(ResultSet rs, Measures measures) throws SQLException {
+ String metricKey = metricKeysByIds.get(rs.getLong(1));
+ Optional<Double> value = metricKey.startsWith("new_") ? getDouble(rs, 3) : getDouble(rs, 2);
+ if (value.isPresent()) {
+ measures.addNumericMeasure(metricKey, value.get());
+ return;
+ } else if (ALERT_STATUS_KEY.equals(metricKey)) {
+ String textValue = rs.getString(4);
+ if (!rs.wasNull()) {
+ measures.setQualityGateStatus(textValue);
+ return;
+ }
+ }
+ throw new IllegalArgumentException("Measure has no value");
+ }
+
+ @Override
+ protected void doClose() throws Exception {
+ measuresStatement.close();
+ }
+
+ private static Optional<Double> getDouble(ResultSet rs, int index) {
+ try {
+ Double value = rs.getDouble(index);
+ if (!rs.wasNull()) {
+ return Optional.of(value);
+ }
+ return Optional.empty();
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to get double value", e);
+ }
+ }
+
+ private static Optional<String> getString(ResultSet rs, int index) {
+ try {
+ String value = rs.getString(index);
+ if (!rs.wasNull()) {
+ return Optional.of(value);
+ }
+ return Optional.empty();
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to get string value", e);
+ }
+ }
+
+ public static class Project {
+ private final String uuid;
+ private final String key;
+ private final String name;
+ private final String analysisUuid;
+ private final Long analysisDate;
+
+ public Project(String uuid, String key, String name, @Nullable String analysisUuid, @Nullable Long analysisDate) {
+ this.uuid = uuid;
+ this.key = key;
+ this.name = name;
+ this.analysisUuid = analysisUuid;
+ this.analysisDate = analysisDate;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @CheckForNull
+ public String getAnalysisUuid() {
+ return analysisUuid;
+ }
+
+ @CheckForNull
+ public Long getAnalysisDate() {
+ return analysisDate;
+ }
+ }
+
+ public static class Measures {
+
+ private Map<String, Double> numericMeasures = new HashMap<>();
+ private String qualityGateStatus;
+
+ Measures addNumericMeasure(String metricKey, double value) {
+ numericMeasures.put(metricKey, value);
+ return this;
+ }
+
+ public Map<String, Double> getNumericMeasures() {
+ return numericMeasures;
+ }
+
+ Measures setQualityGateStatus(@Nullable String qualityGateStatus) {
+ this.qualityGateStatus = qualityGateStatus;
+ return this;
+ }
+
+ @CheckForNull
+ public String getQualityGateStatus() {
+ return qualityGateStatus;
+ }
+ }
+
+ public static class ProjectMeasures {
+ private Project project;
+ private Measures measures;
+
+ public ProjectMeasures(Project project, Measures measures) {
+ this.project = project;
+ this.measures = measures;
+ }
+
+ public Project getProject() {
+ return project;
+ }
+
+ public Measures getMeasures() {
+ return measures;
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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 com.google.common.collect.Maps;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.measures.Metric;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.component.ComponentDbTester;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.component.SnapshotDto;
+import org.sonar.db.measure.ProjectMeasuresIndexerIterator.ProjectMeasures;
+import org.sonar.db.metric.MetricDto;
+import org.sonar.db.metric.MetricTesting;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+import static org.sonar.api.measures.Metric.Level.WARN;
+import static org.sonar.api.measures.Metric.ValueType.DATA;
+import static org.sonar.api.measures.Metric.ValueType.DISTRIB;
+import static org.sonar.api.measures.Metric.ValueType.INT;
+import static org.sonar.api.measures.Metric.ValueType.LEVEL;
+import static org.sonar.api.measures.Metric.ValueType.STRING;
+import static org.sonar.db.component.ComponentTesting.newDeveloper;
+import static org.sonar.db.component.ComponentTesting.newProjectDto;
+import static org.sonar.db.component.ComponentTesting.newView;
+import static org.sonar.db.component.SnapshotTesting.newAnalysis;
+
+public class ProjectMeasuresIndexerIteratorTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ DbClient dbClient = dbTester.getDbClient();
+ DbSession dbSession = dbTester.getSession();
+
+ ComponentDbTester componentDbTester = new ComponentDbTester(dbTester);
+
+ @Test
+ public void return_project_measure() {
+ MetricDto metric1 = insertIntMetric("ncloc");
+ MetricDto metric2 = insertIntMetric("coverage");
+ ComponentDto project = newProjectDto().setKey("Project-Key").setName("Project Name");
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ insertMeasure(project, analysis, metric1, 10d);
+ insertMeasure(project, analysis, metric2, 20d);
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
+
+ assertThat(docsById).hasSize(1);
+ ProjectMeasures doc = docsById.get(project.uuid());
+ assertThat(doc).isNotNull();
+ assertThat(doc.getProject().getUuid()).isEqualTo(project.uuid());
+ assertThat(doc.getProject().getKey()).isEqualTo("Project-Key");
+ assertThat(doc.getProject().getName()).isEqualTo("Project Name");
+ assertThat(doc.getProject().getAnalysisDate()).isNotNull().isEqualTo(analysis.getCreatedAt());
+ assertThat(doc.getMeasures().getNumericMeasures()).containsOnly(entry("ncloc", 10d), entry("coverage", 20d));
+ }
+
+ @Test
+ public void return_project_measure_having_leak() throws Exception {
+ MetricDto metric = insertIntMetric("new_lines");
+ ComponentDto project = newProjectDto();
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ insertMeasureOnLeak(project, analysis, metric, 10d);
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
+
+ assertThat(docsById.get(project.uuid()).getMeasures().getNumericMeasures()).containsOnly(entry("new_lines", 10d));
+ }
+
+ @Test
+ public void return_quality_gate_status_measure() throws Exception {
+ MetricDto metric = insertMetric("alert_status", LEVEL);
+ ComponentDto project = newProjectDto();
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ insertMeasure(project, analysis, metric, WARN.name());
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
+
+ assertThat(docsById.get(project.uuid()).getMeasures().getQualityGateStatus()).isEqualTo("WARN");
+ }
+
+ @Test
+ public void does_not_return_none_numeric_metrics() throws Exception {
+ MetricDto dataMetric = insertMetric("data", DATA);
+ MetricDto distribMetric = insertMetric("distrib", DISTRIB);
+ MetricDto stringMetric = insertMetric("string", STRING);
+ ComponentDto project = newProjectDto();
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ insertMeasure(project, analysis, dataMetric, "dat");
+ insertMeasure(project, analysis, distribMetric, "dis");
+ insertMeasure(project, analysis, stringMetric, "str");
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
+
+ assertThat(docsById.get(project.uuid()).getMeasures().getNumericMeasures()).isEmpty();
+ }
+
+ @Test
+ public void does_not_return_disabled_metrics() throws Exception {
+ MetricDto disabledMetric = insertMetric("disabled", false, false, INT);
+ ComponentDto project = newProjectDto();
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ insertMeasure(project, analysis, disabledMetric, 10d);
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
+
+ assertThat(docsById.get(project.uuid()).getMeasures().getNumericMeasures()).isEmpty();
+ }
+
+ @Test
+ public void fail_when_measure_return_no_value() throws Exception {
+ MetricDto metric = insertIntMetric("new_lines");
+ ComponentDto project = newProjectDto();
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ insertMeasure(project, analysis, metric, 10d);
+
+ expectedException.expect(IllegalStateException.class);
+ createResultSetAndReturnDocsById();
+ }
+
+ @Test
+ public void return_many_project_measures() {
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+
+ assertThat(createResultSetAndReturnDocsById()).hasSize(3);
+ }
+
+ @Test
+ public void return_project_without_analysis() throws Exception {
+ ComponentDto project = componentDbTester.insertComponent(newProjectDto());
+ dbClient.snapshotDao().insert(dbSession, newAnalysis(project).setLast(false));
+ dbSession.commit();
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById();
+
+ assertThat(docsById).hasSize(1);
+ ProjectMeasures doc = docsById.get(project.uuid());
+ assertThat(doc.getProject().getAnalysisDate()).isNull();
+ }
+
+ @Test
+ public void does_not_return_non_active_projects() throws Exception {
+ // Disabled project
+ componentDbTester.insertProjectAndSnapshot(newProjectDto().setEnabled(false));
+ // Disabled project with analysis
+ ComponentDto project = componentDbTester.insertComponent(newProjectDto().setEnabled(false));
+ dbClient.snapshotDao().insert(dbSession, newAnalysis(project));
+
+ // A view
+ componentDbTester.insertProjectAndSnapshot(newView());
+
+ // A developer
+ componentDbTester.insertProjectAndSnapshot(newDeveloper("dev"));
+
+ dbSession.commit();
+
+ assertResultSetIsEmpty();
+ }
+
+ @Test
+ public void return_only_docs_from_given_project() throws Exception {
+ ComponentDto project = newProjectDto();
+ SnapshotDto analysis = componentDbTester.insertProjectAndSnapshot(project);
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(0L, project.uuid());
+
+ assertThat(docsById).hasSize(1);
+ ProjectMeasures doc = docsById.get(project.uuid());
+ assertThat(doc).isNotNull();
+ assertThat(doc.getProject().getUuid()).isEqualTo(project.uuid());
+ assertThat(doc.getProject().getKey()).isNotNull().isEqualTo(project.getKey());
+ assertThat(doc.getProject().getName()).isNotNull().isEqualTo(project.name());
+ assertThat(doc.getProject().getAnalysisDate()).isNotNull().isEqualTo(analysis.getCreatedAt());
+ }
+
+ @Test
+ public void return_only_docs_after_date() throws Exception {
+ ComponentDto project1 = newProjectDto();
+ dbClient.componentDao().insert(dbSession, project1);
+ dbClient.snapshotDao().insert(dbSession, newAnalysis(project1).setCreatedAt(1_000_000L));
+ ComponentDto project2 = newProjectDto();
+ dbClient.componentDao().insert(dbSession, project2);
+ dbClient.snapshotDao().insert(dbSession, newAnalysis(project2).setCreatedAt(2_000_000L));
+ dbSession.commit();
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(1_500_000L, null);
+
+ assertThat(docsById).hasSize(1);
+ assertThat(docsById.get(project2.uuid())).isNotNull();
+ }
+
+ @Test
+ public void return_nothing_on_unknown_project() throws Exception {
+ componentDbTester.insertProjectAndSnapshot(newProjectDto());
+
+ Map<String, ProjectMeasures> docsById = createResultSetAndReturnDocsById(0L, "UNKNOWN");
+
+ assertThat(docsById).isEmpty();
+ }
+
+ private Map<String, ProjectMeasures> createResultSetAndReturnDocsById() {
+ return createResultSetAndReturnDocsById(0L, null);
+ }
+
+ private Map<String, ProjectMeasures> createResultSetAndReturnDocsById(long date, @Nullable String projectUuid) {
+ ProjectMeasuresIndexerIterator it = ProjectMeasuresIndexerIterator.create(dbTester.getSession(), date, projectUuid);
+ Map<String, ProjectMeasures> docsById = Maps.uniqueIndex(it, pm -> pm.getProject().getUuid());
+ it.close();
+ return docsById;
+ }
+
+ private void assertResultSetIsEmpty() {
+ assertThat(createResultSetAndReturnDocsById()).isEmpty();
+ }
+
+ private MetricDto insertIntMetric(String metricKey) {
+ return insertMetric(metricKey, true, false, INT);
+ }
+
+ private MetricDto insertMetric(String metricKey, Metric.ValueType type) {
+ return insertMetric(metricKey, true, false, type);
+ }
+
+ private MetricDto insertMetric(String metricKey, boolean enabled, boolean hidden, Metric.ValueType type) {
+ MetricDto metric = dbClient.metricDao().insert(dbSession,
+ MetricTesting.newMetricDto()
+ .setKey(metricKey)
+ .setEnabled(enabled)
+ .setHidden(hidden)
+ .setValueType(type.name()));
+ dbSession.commit();
+ return metric;
+ }
+
+ private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, double value) {
+ return insertMeasure(project, analysis, metric, value, null);
+ }
+
+ private MeasureDto insertMeasureOnLeak(ComponentDto project, SnapshotDto analysis, MetricDto metric, double value) {
+ return insertMeasure(project, analysis, metric, null, value);
+ }
+
+ private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, String value) {
+ return insertMeasure(MeasureTesting.newMeasureDto(metric, project, analysis).setData(value));
+ }
+
+ private MeasureDto insertMeasure(ComponentDto project, SnapshotDto analysis, MetricDto metric, @Nullable Double value, @Nullable Double leakValue) {
+ return insertMeasure(MeasureTesting.newMeasureDto(metric, project, analysis).setValue(value).setVariation(1, leakValue));
+ }
+
+ private MeasureDto insertMeasure(MeasureDto measure) {
+ dbClient.measureDao().insert(dbSession, measure);
+ dbSession.commit();
+ return measure;
+ }
+
+}
import javax.annotation.Nullable;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
-import org.sonar.api.batch.ScannerSide;
import org.sonar.api.batch.InstantiationStrategy;
+import org.sonar.api.batch.ScannerSide;
import org.sonar.api.ce.ComputeEngineSide;
import org.sonar.api.server.ServerSide;
* @param userManaged whether the metric is user managed
*/
private Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, @Nullable String domain,
- boolean userManaged) {
+ boolean userManaged) {
this.key = key;
this.description = description;
this.type = type;