aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties1
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java17
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java7
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterResult.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterRow.java29
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSort.java15
-rw-r--r--sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java332
-rw-r--r--sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java8
-rw-r--r--sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java4
9 files changed, 268 insertions, 147 deletions
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
index 296540d7726..01429a561d7 100644
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
@@ -448,7 +448,6 @@ measure_filter.treemap.change=Change Treemap
measure_filter.add_column_button=Add Column
measure_filter.widget.unknown_filter_warning=This widget is configured to display a measure filter that doesn't exist anymore.
measure_filter.error.UNKNOWN=Unexpected error. Please contact the administrator.
-measure_filter.error.TOO_MANY_RESULTS=Too many results. Please refine your search.
#------------------------------------------------------------------------------
#
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java
index 746902aff25..a483e0f2b4b 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterCondition.java
@@ -81,17 +81,22 @@ public class MeasureFilterCondition {
return period;
}
- String valueColumn() {
+ StringBuilder appendSqlColumn(StringBuilder sb, int conditionIndex) {
+ sb.append("pmcond").append(conditionIndex);
if (period != null) {
- return "pm.variation_value_" + period;
+ sb.append(".variation_value_").append(period).toString();
+ } else {
+ sb.append(".value");
}
- return "pm.value";
+ return sb;
}
- StringBuilder appendSqlCondition(StringBuilder sql) {
- sql.append(" pm.metric_id=");
+ StringBuilder appendSqlCondition(StringBuilder sql, int conditionIndex) {
+ sql.append(" pmcond").append(conditionIndex).append(".metric_id=");
sql.append(metric.getId());
- sql.append(" AND ").append(valueColumn()).append(operator.getSql()).append(value);
+ sql.append(" AND ");
+ appendSqlColumn(sql, conditionIndex);
+ sql.append(operator.getSql()).append(value);
return sql;
}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java
index 84d3211ecf2..97146643ce9 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterEngine.java
@@ -36,7 +36,6 @@ public class MeasureFilterEngine implements ServerComponent {
private final MeasureFilterFactory factory;
private final MeasureFilterExecutor executor;
- private static final int MAX_ROWS = 5000;
public MeasureFilterEngine(MeasureFilterFactory factory, MeasureFilterExecutor executor) {
this.executor = executor;
@@ -57,11 +56,7 @@ public class MeasureFilterEngine implements ServerComponent {
try {
MeasureFilter filter = factory.create(filterMap);
List<MeasureFilterRow> rows = executor.execute(filter, context);
- if (rows.size() <= MAX_ROWS) {
- result.setRows(rows);
- } else {
- result.setError(MeasureFilterResult.Error.TOO_MANY_RESULTS);
- }
+ result.setRows(rows);
result.setDurationInMs(System.currentTimeMillis() - start);
log(context, result, logger);
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterResult.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterResult.java
index 118733e9e59..562e69a24e1 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterResult.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterResult.java
@@ -26,7 +26,7 @@ import java.util.List;
public class MeasureFilterResult {
public static enum Error {
- TOO_MANY_RESULTS, UNKNOWN
+ UNKNOWN
}
private List<MeasureFilterRow> rows = null;
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterRow.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterRow.java
index cf041422c42..a168e340111 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterRow.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterRow.java
@@ -19,11 +19,17 @@
*/
package org.sonar.core.measure;
+import org.apache.commons.lang.StringUtils;
+
+import java.sql.Date;
+
public class MeasureFilterRow {
private final long snapshotId;
private final long resourceId;
private final long resourceRootId;
- private String sortText;
+ private String sortText = null;
+ private Date sortDate = null;
+ private Double sortDouble = null;
MeasureFilterRow(long snapshotId, long resourceId, long resourceRootId) {
this.snapshotId = snapshotId;
@@ -47,8 +53,23 @@ public class MeasureFilterRow {
return sortText;
}
- MeasureFilterRow setSortText(String s) {
- this.sortText = s;
- return this;
+ void setSortText(String s) {
+ this.sortText = StringUtils.defaultString(s);
+ }
+
+ Date getSortDate() {
+ return sortDate;
+ }
+
+ void setSortDate(Date sortDate) {
+ this.sortDate = sortDate;
+ }
+
+ Double getSortDouble() {
+ return sortDouble;
+ }
+
+ void setSortDouble(Double sortDouble) {
+ this.sortDouble = sortDouble;
}
}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSort.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSort.java
index 3fc40ed04f1..682292dee8e 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSort.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSort.java
@@ -67,10 +67,18 @@ class MeasureFilterSort {
return metric;
}
- boolean isSortedByDatabase() {
+ boolean isOnMeasure() {
+ return metric != null;
+ }
+
+ boolean isOnNumericMeasure() {
return metric != null && metric.isNumericType();
}
+ boolean isOnDate() {
+ return Field.DATE.equals(field);
+ }
+
boolean isAsc() {
return asc;
}
@@ -102,9 +110,9 @@ class MeasureFilterSort {
break;
case METRIC:
if (metric.isNumericType()) {
- column = (period != null ? "pm.variation_value_" + period : "pm.value");
+ column = (period != null ? "pmsort.variation_value_" + period : "pmsort.value");
} else {
- column = "pm.text_value";
+ column = "pmsort.text_value";
}
break;
default:
@@ -112,5 +120,4 @@ class MeasureFilterSort {
}
return column;
}
-
}
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java
index f332a2f0d83..77d461fd99b 100644
--- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java
+++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java
@@ -22,12 +22,11 @@ package org.sonar.core.measure;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
+import com.google.common.primitives.Doubles;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.measures.Metric;
import org.sonar.core.persistence.Database;
import org.sonar.core.persistence.DatabaseUtils;
-import org.sonar.core.persistence.dialect.PostgreSql;
import org.sonar.core.resource.SnapshotDto;
import javax.annotation.Nullable;
@@ -37,25 +36,28 @@ import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.Comparator;
import java.util.List;
class MeasureFilterSql {
+ private static final int FETCH_SIZE = 1000;
private final Database database;
private final MeasureFilter filter;
private final MeasureFilterContext context;
- private final StringBuilder sql = new StringBuilder(1000);
+ private final String sql;
private final List<Date> dateParameters = Lists.newArrayList();
MeasureFilterSql(Database database, MeasureFilter filter, MeasureFilterContext context) {
this.database = database;
this.filter = filter;
this.context = context;
- init();
+ this.sql = generateSql();
}
List<MeasureFilterRow> execute(Connection connection) throws SQLException {
- PreparedStatement statement = connection.prepareStatement(sql.toString());
+ PreparedStatement statement = connection.prepareStatement(sql);
+ statement.setFetchSize(FETCH_SIZE);
ResultSet rs = null;
try {
for (int index = 0; index < dateParameters.size(); index++) {
@@ -71,196 +73,288 @@ class MeasureFilterSql {
}
String sql() {
- return sql.toString();
+ return sql;
}
- private void init() {
- sql.append("SELECT block.id, max(block.rid) AS rid, max(block.rootid) AS rootid, max(sortval) AS sortmax, CASE WHEN max(sortval) IS NULL THEN 1 ELSE 0 END AS sortflag ");
- for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
- sql.append(", max(crit_").append(index).append(")");
- }
- sql.append(" FROM (");
+ private String generateSql() {
+ StringBuilder sb = new StringBuilder(1000);
+ sb.append("SELECT s.id, s.project_id, s.root_project_id, ");
+ sb.append(filter.sort().column());
+ sb.append(" FROM snapshots s INNER JOIN projects p ON s.project_id=p.id ");
- appendSortBlock();
for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
MeasureFilterCondition condition = filter.getMeasureConditions().get(index);
- sql.append(" UNION ");
- appendConditionBlock(index, condition);
+ sb.append(" INNER JOIN project_measures pmcond").append(index);
+ sb.append(" ON s.id=pmcond").append(index).append(".snapshot_id AND ");
+ condition.appendSqlCondition(sb, index);
}
- sql.append(") block GROUP BY block.id ");
- if (!filter.getMeasureConditions().isEmpty()) {
- sql.append(" HAVING ");
- for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
- if (index > 0) {
- sql.append(" AND ");
- }
- sql.append(" max(crit_").append(index).append(") IS NOT NULL ");
- }
+ if (filter.isOnFavourites()) {
+ sb.append(" INNER JOIN properties props ON props.resource_id=s.project_id ");
}
- if (filter.sort().isSortedByDatabase()) {
- sql.append(" ORDER BY sortflag ASC, sortmax ");
- sql.append(filter.sort().isAsc() ? "ASC " : "DESC ");
+
+ if (filter.sort().isOnMeasure()) {
+ sb.append(" LEFT OUTER JOIN project_measures pmsort ON s.id=pmsort.snapshot_id AND pmsort.metric_id=");
+ sb.append(filter.sort().metric().getId());
+ sb.append(" AND pmsort.rule_id IS NULL AND pmsort.rule_priority IS NULL AND pmsort.characteristic_id IS NULL AND pmsort.person_id IS NULL ");
}
- }
- private void appendSortBlock() {
- sql.append(" SELECT s.id, s.project_id AS rid, s.root_project_id AS rootid, ").append(filter.sort().column()).append(" AS sortval ");
+ sb.append(" WHERE ");
+ appendResourceConditions(sb);
+
for (int index = 0; index < filter.getMeasureConditions().size(); index++) {
MeasureFilterCondition condition = filter.getMeasureConditions().get(index);
- sql.append(", ").append(nullSelect(condition.metric())).append(" AS crit_").append(index);
+ sb.append(" AND ");
+ condition.appendSqlCondition(sb, index);
}
- sql.append(" FROM snapshots s INNER JOIN projects p ON s.project_id=p.id ");
- if (filter.isOnFavourites()) {
- sql.append(" INNER JOIN properties props ON props.resource_id=s.project_id ");
- }
- if (filter.sort().onMeasures()) {
- sql.append(" LEFT OUTER JOIN project_measures pm ON s.id=pm.snapshot_id AND pm.metric_id=");
- sql.append(filter.sort().metric().getId());
- sql.append(" AND pm.rule_id IS NULL AND pm.rule_priority IS NULL AND pm.characteristic_id IS NULL AND pm.person_id IS NULL ");
- }
- sql.append(" WHERE ");
- appendResourceConditions();
- }
- private void appendConditionBlock(int conditionIndex, MeasureFilterCondition condition) {
- sql.append(" SELECT s.id, s.project_id AS rid, s.root_project_id AS rootid, null AS sortval ");
- for (int j = 0; j < filter.getMeasureConditions().size(); j++) {
- sql.append(", ");
- if (j == conditionIndex) {
- sql.append(condition.valueColumn());
- } else {
- sql.append(nullSelect(filter.getMeasureConditions().get(j).metric()));
- }
- sql.append(" AS crit_").append(j);
- }
- sql.append(" FROM snapshots s INNER JOIN projects p ON s.project_id=p.id INNER JOIN project_measures pm ON s.id=pm.snapshot_id ");
- if (filter.isOnFavourites()) {
- sql.append(" INNER JOIN properties props ON props.resource_id=s.project_id ");
- }
- sql.append(" WHERE ");
- appendResourceConditions();
- sql.append(" AND pm.rule_id IS NULL AND pm.rule_priority IS NULL AND pm.characteristic_id IS NULL AND pm.person_id IS NULL AND ");
- condition.appendSqlCondition(sql);
+ return sb.toString();
}
- private void appendResourceConditions() {
- sql.append(" s.status='P' AND s.islast=").append(database.getDialect().getTrueSqlValue());
+ private void appendResourceConditions(StringBuilder sb) {
+ sb.append(" s.status='P' AND s.islast=").append(database.getDialect().getTrueSqlValue());
if (context.getBaseSnapshot() == null) {
- sql.append(" AND p.copy_resource_id IS NULL ");
+ sb.append(" AND p.copy_resource_id IS NULL ");
}
if (!filter.getResourceQualifiers().isEmpty()) {
- sql.append(" AND s.qualifier IN ");
- appendInStatement(filter.getResourceQualifiers(), sql);
+ sb.append(" AND s.qualifier IN ");
+ appendInStatement(filter.getResourceQualifiers(), sb);
}
if (!filter.getResourceScopes().isEmpty()) {
- sql.append(" AND s.scope IN ");
- appendInStatement(filter.getResourceScopes(), sql);
+ sb.append(" AND s.scope IN ");
+ appendInStatement(filter.getResourceScopes(), sb);
}
if (!filter.getResourceLanguages().isEmpty()) {
- sql.append(" AND p.language IN ");
- appendInStatement(filter.getResourceLanguages(), sql);
+ sb.append(" AND p.language IN ");
+ appendInStatement(filter.getResourceLanguages(), sb);
}
- appendDateConditions();
- appendFavouritesCondition();
- appendResourceNameCondition();
- appendResourceKeyCondition();
- appendResourceBaseCondition();
+ appendDateConditions(sb);
+ appendFavouritesCondition(sb);
+ appendResourceNameCondition(sb);
+ appendResourceKeyCondition(sb);
+ appendResourceBaseCondition(sb);
}
- private void appendDateConditions() {
+ private void appendDateConditions(StringBuilder sb) {
if (filter.getFromDate() != null) {
- sql.append(" AND s.created_at >= ? ");
+ sb.append(" AND s.created_at >= ? ");
dateParameters.add(new Date(filter.getFromDate().getTime()));
}
if (filter.getToDate() != null) {
- sql.append(" AND s.created_at <= ? ");
+ sb.append(" AND s.created_at <= ? ");
dateParameters.add(new Date(filter.getToDate().getTime()));
}
}
- private void appendFavouritesCondition() {
+ private void appendFavouritesCondition(StringBuilder sb) {
if (filter.isOnFavourites()) {
- sql.append(" AND props.prop_key='favourite' AND props.resource_id IS NOT NULL AND props.user_id=");
- sql.append(context.getUserId());
- sql.append(" ");
+ sb.append(" AND props.prop_key='favourite' AND props.resource_id IS NOT NULL AND props.user_id=");
+ sb.append(context.getUserId());
+ sb.append(" ");
}
}
- private void appendResourceBaseCondition() {
+ private void appendResourceBaseCondition(StringBuilder sb) {
SnapshotDto baseSnapshot = context.getBaseSnapshot();
if (baseSnapshot != null) {
if (filter.isOnBaseResourceChildren()) {
- sql.append(" AND s.parent_snapshot_id=").append(baseSnapshot.getId());
+ sb.append(" AND s.parent_snapshot_id=").append(baseSnapshot.getId());
} else {
Long rootSnapshotId = (baseSnapshot.getRootId() != null ? baseSnapshot.getRootId() : baseSnapshot.getId());
- sql.append(" AND s.root_snapshot_id=").append(rootSnapshotId);
- sql.append(" AND s.path LIKE '").append(StringUtils.defaultString(baseSnapshot.getPath())).append(baseSnapshot.getId()).append(".%'");
+ sb.append(" AND s.root_snapshot_id=").append(rootSnapshotId);
+ sb.append(" AND s.path LIKE '").append(StringUtils.defaultString(baseSnapshot.getPath())).append(baseSnapshot.getId()).append(".%'");
}
}
}
- private void appendResourceKeyCondition() {
+ private void appendResourceKeyCondition(StringBuilder sb) {
if (StringUtils.isNotBlank(filter.getResourceKeyRegexp())) {
- sql.append(" AND UPPER(p.kee) LIKE '");
+ sb.append(" AND UPPER(p.kee) LIKE '");
// limitation : special characters _ and % are not escaped
String regexp = StringEscapeUtils.escapeSql(filter.getResourceKeyRegexp());
regexp = StringUtils.replaceChars(regexp, '*', '%');
regexp = StringUtils.replaceChars(regexp, '?', '_');
- sql.append(StringUtils.upperCase(regexp)).append("'");
+ sb.append(StringUtils.upperCase(regexp)).append("'");
}
}
- private void appendResourceNameCondition() {
+ private void appendResourceNameCondition(StringBuilder sb) {
if (StringUtils.isNotBlank(filter.getResourceName())) {
- sql.append(" AND s.project_id IN (SELECT rindex.resource_id FROM resource_index rindex WHERE rindex.kee like '");
- sql.append(StringEscapeUtils.escapeSql(StringUtils.lowerCase(filter.getResourceName())));
- sql.append("%'");
+ sb.append(" AND s.project_id IN (SELECT rindex.resource_id FROM resource_index rindex WHERE rindex.kee like '");
+ sb.append(StringEscapeUtils.escapeSql(StringUtils.lowerCase(filter.getResourceName())));
+ sb.append("%'");
if (!filter.getResourceQualifiers().isEmpty()) {
- sql.append(" AND rindex.qualifier IN ");
- appendInStatement(filter.getResourceQualifiers(), sql);
+ sb.append(" AND rindex.qualifier IN ");
+ appendInStatement(filter.getResourceQualifiers(), sb);
}
- sql.append(") ");
+ sb.append(") ");
}
}
List<MeasureFilterRow> process(ResultSet rs) throws SQLException {
List<MeasureFilterRow> rows = Lists.newArrayList();
- boolean sortTextValues = !filter.sort().isSortedByDatabase();
+ RowProcessor rowProcessor;
+ if (filter.sort().isOnNumericMeasure()) {
+ rowProcessor = new NumericSortRowProcessor();
+ } else if (filter.sort().isOnDate()) {
+ rowProcessor = new DateSortRowProcessor();
+ } else {
+ rowProcessor = new TextSortRowProcessor();
+ }
+
while (rs.next()) {
+ rows.add(rowProcessor.fetch(rs));
+ }
+
+ return rowProcessor.sort(rows, filter.sort().isAsc());
+ }
+
+ private static void appendInStatement(List<String> values, StringBuilder to) {
+ to.append(" ('");
+ to.append(StringUtils.join(values, "','"));
+ to.append("') ");
+ }
+
+ static abstract class RowProcessor {
+ abstract Function sortFieldFunction();
+
+ abstract Ordering sortFieldOrdering(boolean ascending);
+
+ abstract MeasureFilterRow fetch(ResultSet rs) throws SQLException;
+
+ final List<MeasureFilterRow> sort(List<MeasureFilterRow> rows, boolean ascending) {
+ Ordering<MeasureFilterRow> ordering = sortFieldOrdering(ascending).onResultOf(sortFieldFunction());
+ return ordering.immutableSortedCopy(rows);
+ }
+ }
+
+ static class TextSortRowProcessor extends RowProcessor {
+ MeasureFilterRow fetch(ResultSet rs) throws SQLException {
MeasureFilterRow row = new MeasureFilterRow(rs.getLong(1), rs.getLong(2), rs.getLong(3));
- if (sortTextValues) {
- row.setSortText(rs.getString(4));
- }
- rows.add(row);
+ row.setSortText(rs.getString(4));
+ return row;
}
- if (sortTextValues) {
- // database does not manage case-insensitive text sorting. It must be done programmatically
- Function<MeasureFilterRow, String> function = new Function<MeasureFilterRow, String>() {
- public String apply(@Nullable MeasureFilterRow row) {
- return (row != null ? StringUtils.defaultString(row.getSortText()) : "");
+
+ Function sortFieldFunction() {
+ return new Function<MeasureFilterRow, String>() {
+ public String apply(MeasureFilterRow row) {
+ return row.getSortText();
}
};
- Ordering<MeasureFilterRow> ordering = Ordering.from(String.CASE_INSENSITIVE_ORDER).onResultOf(function).nullsFirst();
- if (!filter.sort().isAsc()) {
+ }
+
+ Ordering sortFieldOrdering(boolean ascending) {
+ Ordering<String> ordering = Ordering.from(String.CASE_INSENSITIVE_ORDER);
+ if (!ascending) {
ordering = ordering.reverse();
}
- rows = ordering.sortedCopy(rows);
+ return ordering;
}
- return rows;
+
}
- private String nullSelect(Metric metric) {
- if (metric.isNumericType() && PostgreSql.ID.equals(database.getDialect().getId())) {
- return "null::integer";
+ static class NumericSortRowProcessor extends RowProcessor {
+ MeasureFilterRow fetch(ResultSet rs) throws SQLException {
+ MeasureFilterRow row = new MeasureFilterRow(rs.getLong(1), rs.getLong(2), rs.getLong(3));
+ double value = rs.getDouble(4);
+ if (!rs.wasNull()) {
+ row.setSortDouble(value);
+ }
+ return row;
+ }
+
+ Function sortFieldFunction() {
+ return new Function<MeasureFilterRow, Double>() {
+ public Double apply(MeasureFilterRow row) {
+ return row.getSortDouble();
+ }
+ };
+ }
+
+ Ordering sortFieldOrdering(boolean ascending) {
+ if (ascending) {
+ return Ordering.from(new Comparator<Double>() {
+ public int compare(@Nullable Double left, @Nullable Double right) {
+ if (left == right) {
+ return 0;
+ }
+ if (left == null) {
+ return 1;
+ }
+ if (right == null) {
+ return -1;
+ }
+
+ return Doubles.compare(left, right);
+ }
+ });
+ }
+ return Ordering.from(new Comparator<Double>() {
+ public int compare(@Nullable Double left, @Nullable Double right) {
+ if (left == right) {
+ return 0;
+ }
+ if (left == null) {
+ return 1;
+ }
+ if (right == null) {
+ return -1;
+ }
+
+ return -Doubles.compare(left, right);
+ }
+ });
}
- return "null";
}
+ static class DateSortRowProcessor extends RowProcessor {
+ MeasureFilterRow fetch(ResultSet rs) throws SQLException {
+ MeasureFilterRow row = new MeasureFilterRow(rs.getLong(1), rs.getLong(2), rs.getLong(3));
+ row.setSortDate(rs.getDate(4));
+ return row;
+ }
- private static void appendInStatement(List<String> values, StringBuilder to) {
- to.append(" ('");
- to.append(StringUtils.join(values, "','"));
- to.append("') ");
+ Function sortFieldFunction() {
+ return new Function<MeasureFilterRow, Date>() {
+ public Date apply(MeasureFilterRow row) {
+ return row.getSortDate();
+ }
+ };
+ }
+
+ Ordering sortFieldOrdering(boolean ascending) {
+ if (ascending) {
+ return Ordering.from(new Comparator<Date>() {
+ public int compare(@Nullable Date left, @Nullable Date right) {
+ if (left == right) {
+ return 0;
+ }
+ if (left == null) {
+ return 1;
+ }
+ if (right == null) {
+ return -1;
+ }
+
+ return left.compareTo(right);
+ }
+ });
+ }
+ return Ordering.from(new Comparator<Date>() {
+ public int compare(@Nullable Date left, @Nullable Date right) {
+ if (left == right) {
+ return 0;
+ }
+ if (left == null) {
+ return 1;
+ }
+ if (right == null) {
+ return -1;
+ }
+
+ return -left.compareTo(right);
+ }
+ });
+ }
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java
index 112975ff908..73b5cdb7c74 100644
--- a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterConditionTest.java
@@ -59,9 +59,9 @@ public class MeasureFilterConditionTest {
assertThat(condition.operator()).isEqualTo(MeasureFilterCondition.Operator.GREATER);
assertThat(condition.period()).isNull();
assertThat(condition.value()).isEqualTo(10.0);
- assertThat(condition.valueColumn()).isEqualTo("pm.value");
+ assertThat(condition.appendSqlColumn(new StringBuilder(), 1).toString()).isEqualTo("pmcond1.value");
assertThat(condition.toString()).isNotEmpty();
- assertThat(condition.appendSqlCondition(new StringBuilder()).toString()).isEqualTo(" pm.metric_id=123 AND pm.value>10.0");
+ assertThat(condition.appendSqlCondition(new StringBuilder(), 1).toString()).isEqualTo(" pmcond1.metric_id=123 AND pmcond1.value>10.0");
}
@Test
@@ -75,8 +75,8 @@ public class MeasureFilterConditionTest {
assertThat(condition.operator()).isEqualTo(MeasureFilterCondition.Operator.LESS_OR_EQUALS);
assertThat(condition.period()).isEqualTo(3);
assertThat(condition.value()).isEqualTo(10.0);
- assertThat(condition.valueColumn()).isEqualTo("pm.variation_value_3");
+ assertThat(condition.appendSqlColumn(new StringBuilder(), 2).toString()).isEqualTo("pmcond2.variation_value_3");
assertThat(condition.toString()).isNotEmpty();
- assertThat(condition.appendSqlCondition(new StringBuilder()).toString()).isEqualTo(" pm.metric_id=123 AND pm.variation_value_3<=10.0");
+ assertThat(condition.appendSqlCondition(new StringBuilder(), 2).toString()).isEqualTo(" pmcond2.metric_id=123 AND pmcond2.variation_value_3<=10.0");
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java
index 936b3afff77..472976e65ca 100644
--- a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterFactoryTest.java
@@ -43,7 +43,7 @@ public class MeasureFilterFactoryTest {
Map<String, Object> props = ImmutableMap.<String, Object>of("sort", "metric:ncloc");
MeasureFilter filter = factory.create(props);
- assertThat(filter.sort().column()).isEqualTo("pm.value");
+ assertThat(filter.sort().column()).isEqualTo("pmsort.value");
assertThat(filter.sort().metric().getKey()).isEqualTo("ncloc");
assertThat(filter.sort().period()).isNull();
}
@@ -54,7 +54,7 @@ public class MeasureFilterFactoryTest {
Map<String, Object> props = ImmutableMap.<String, Object>of("sort", "metric:ncloc:3");
MeasureFilter filter = factory.create(props);
- assertThat(filter.sort().column()).isEqualTo("pm.variation_value_3");
+ assertThat(filter.sort().column()).isEqualTo("pmsort.variation_value_3");
assertThat(filter.sort().metric().getKey()).isEqualTo("ncloc");
assertThat(filter.sort().period()).isEqualTo(3);
}