aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-db/src/main/java/org/sonar
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2016-11-02 14:38:31 +0100
committerJulien Lancelot <julien.lancelot@sonarsource.com>2016-11-03 15:36:47 +0100
commit85bd0e6065d97319657535954d8a97c9ca161430 (patch)
treefe2513f0ab7f838a7f0886b007eb022a781dbb78 /sonar-db/src/main/java/org/sonar
parentd965fca5ff557a3d2cab134435ce05b8d8ab5df1 (diff)
downloadsonarqube-85bd0e6065d97319657535954d8a97c9ca161430.tar.gz
sonarqube-85bd0e6065d97319657535954d8a97c9ca161430.zip
SONAR-8325 Improve MeasureDao#selectByQuery performance
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)
Diffstat (limited to 'sonar-db/src/main/java/org/sonar')
-rw-r--r--sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java41
-rw-r--r--sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java113
2 files changed, 117 insertions, 37 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java
index 0536a8389d6..c298bb18ff1 100644
--- a/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java
@@ -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,
diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java
index 80b49427fcc..00b724df175 100644
--- a/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java
+++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureQuery.java
@@ -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;
}