Skip to content

Commit

Permalink
Support no metric query
Browse files Browse the repository at this point in the history
  • Loading branch information
hchen04 committed Jan 14, 2020
1 parent 6de9499 commit 2cbb0e8
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import com.yahoo.elide.datastores.aggregation.query.ColumnProjection;
import com.yahoo.elide.datastores.aggregation.query.Query;

import org.apache.commons.collections.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -54,16 +52,6 @@ public QueryValidator(Query query, Set<String> allFields, EntityDictionary dicti
public void validate() {
validateHavingClause(query.getHavingFilter());
validateSorting();
validateMetricFunction();
}

/**
* Checks to make sure at least one metric is being aggregated on.
*/
private void validateMetricFunction() {
if (CollectionUtils.isEmpty(metrics)) {
throw new InvalidOperationException("Must provide at least one metric in query");
}
}

/**
Expand Down Expand Up @@ -145,6 +133,12 @@ private void validateSortingPath(Path path, Set<String> allFields) {
throw new UnsupportedOperationException(
"Currently sorting on double nested fields is not supported");
}

if (metrics.isEmpty() && pathElements.size() > 1) {
throw new UnsupportedOperationException(
"Query with no metric can't sort on nested field.");
}

Path.PathElement currentElement = pathElements.get(0);
String currentField = currentElement.getFieldName();
Class<?> currentClass = currentElement.getType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ public SQLQuery resolveTemplate(Query clientQuery,
Set<ColumnProjection> groupByDimensions = template.getGroupByDimensions();

if (!groupByDimensions.isEmpty()) {
builder.groupByClause(constructGroupByWithReference(groupByDimensions, queriedTable));
if (!clientQuery.getMetrics().isEmpty()) {
builder.groupByClause(constructGroupByWithReference(groupByDimensions, queriedTable));
}

joinPaths.addAll(extractJoinPaths(groupByDimensions, queriedTable));
}
Expand Down Expand Up @@ -200,6 +202,10 @@ private String constructProjectionWithReference(SQLQueryTemplate template, SQLAn
})
.collect(Collectors.toList());

if (metricProjections.isEmpty()) {
return "DISTINCT " + String.join(",", dimensionProjections);
}

return Stream.concat(metricProjections.stream(), dimensionProjections.stream())
.collect(Collectors.joining(","));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.yahoo.elide.core.pagination.Pagination;
import com.yahoo.elide.datastores.aggregation.QueryEngine;
import com.yahoo.elide.datastores.aggregation.metadata.MetaDataStore;
import com.yahoo.elide.datastores.aggregation.metadata.metric.MetricFunctionInvocation;
import com.yahoo.elide.datastores.aggregation.metadata.models.AnalyticView;
import com.yahoo.elide.datastores.aggregation.metadata.models.MetricFunction;
import com.yahoo.elide.datastores.aggregation.metadata.models.Table;
Expand All @@ -37,6 +38,7 @@

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -169,7 +171,22 @@ protected SQLQuery toSQL(Query query) {
timeDimension);
})
.reduce(SQLQueryTemplate::merge)
.orElseThrow(() -> new InvalidPredicateException("Metric function not found"));
.orElse(new SQLQueryTemplate() {
@Override
public List<MetricFunctionInvocation> getMetrics() {
return Collections.emptyList();
}

@Override
public Set<ColumnProjection> getNonTimeDimensions() {
return groupByDimensions;
}

@Override
public TimeDimensionProjection getTimeDimension() {
return timeDimension;
}
});

return new SQLQueryConstructor(metadataDictionary).resolveTemplate(
query,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,19 @@ public static void init() {

@Test
public void testNoMetricQuery() {
Map<String, Sorting.SortOrder> sortMap = new TreeMap<>();
sortMap.put("country.name", Sorting.SortOrder.asc);

Query query = Query.builder()
.analyticView(playerStatsTable)
.groupByDimension(toProjection(playerStatsTable.getDimension("overallRating")))
.sorting(new Sorting(sortMap))
.build();

QueryValidator validator = new QueryValidator(query, Collections.singleton("overallRating"), dictionary);

InvalidOperationException exception = assertThrows(InvalidOperationException.class, validator::validate);
assertEquals("Invalid operation: 'Must provide at least one metric in query'", exception.getMessage());
UnsupportedOperationException exception = assertThrows(UnsupportedOperationException.class, validator::validate);
assertEquals("Query with no metric can't sort on nested field.", exception.getMessage());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,60 @@ public void basicAggregationTest() throws Exception {
runQueryWithExpectedResult(graphQLRequest, expected);
}

@Test
public void noMetricQueryTest() throws Exception {
String graphQLRequest = document(
selection(
field(
"playerStatsWithView",
arguments(
argument("sort", "\"countryViewRelationshipIsoCode\"")
),
selections(
field(
"country",
selections(
field("name"),
field("isoCode")
)
),
field("countryViewRelationshipIsoCode")
)
)
)
).toQuery();

String expected = document(
selections(
field(
"playerStatsWithView",
selections(
field(
"country",
selections(
field("name", "Hong Kong"),
field("isoCode", "HKG")
)
),
field("countryViewRelationshipIsoCode", "HKG")
),
selections(
field(
"country",
selections(
field("name", "United States"),
field("isoCode", "USA")
)
),
field("countryViewRelationshipIsoCode", "USA")
)
)
)
).toResponse();

runQueryWithExpectedResult(graphQLRequest, expected);
}

@Test
public void whereFilterTest() throws Exception {
String graphQLRequest = document(
Expand Down Expand Up @@ -609,29 +663,6 @@ public void sortingOnMetricNotInQueryTest() throws Exception {
runQueryWithExpectedError(graphQLRequest, expected);
}

@Test
public void noMetricQueryTest() throws Exception {
String graphQLRequest = document(
selection(
field(
"playerStats",
selections(
field(
"country",
selections(
field("name")
)
)
)
)
)
).toQuery();

String expected = "\"Exception while fetching data (/playerStats) : Invalid operation: 'Must provide at least one metric in query'\"";

runQueryWithExpectedError(graphQLRequest, expected);
}

@Test
public void sortingMultipleLevelNesting() throws Exception {
String graphQLRequest = document(
Expand Down

0 comments on commit 2cbb0e8

Please sign in to comment.