summaryrefslogtreecommitdiffstats
path: root/container-search
diff options
context:
space:
mode:
authorTor Egge <Tor.Egge@broadpark.no>2018-09-05 11:06:57 +0200
committerGitHub <noreply@github.com>2018-09-05 11:06:57 +0200
commit6a30c43ab7407904e1f5b36457a4a319f44a8aaf (patch)
treef98f2b2679f285c335e7dbd68c73eeee79c590ca /container-search
parent773cdb1ef16386fb7d8d023080cbba811a1073fe (diff)
parentea78663a3544923aed4251f04ad05564b659b3db (diff)
Merge pull request #6793 from vespa-engine/geirst/extend-grouping-validator-to-handle-attribute-map-syntax
Geirst/extend grouping validator to handle attribute map syntax
Diffstat (limited to 'container-search')
-rw-r--r--container-search/src/main/java/com/yahoo/search/grouping/GroupingValidator.java18
-rw-r--r--container-search/src/test/java/com/yahoo/search/grouping/GroupingValidatorTestCase.java91
2 files changed, 87 insertions, 22 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/grouping/GroupingValidator.java b/container-search/src/main/java/com/yahoo/search/grouping/GroupingValidator.java
index d96f490909e..790b5c4e601 100644
--- a/container-search/src/main/java/com/yahoo/search/grouping/GroupingValidator.java
+++ b/container-search/src/main/java/com/yahoo/search/grouping/GroupingValidator.java
@@ -75,8 +75,22 @@ public class GroupingValidator extends Searcher {
public void visitExpression(GroupingExpression exp) {
if (exp instanceof AttributeValue) {
String name = ((AttributeValue)exp).getAttributeName();
- if (!attributeNames.contains(name)) {
- throw new UnavailableAttributeException(clusterName, name);
+ int leftBracePos = name.indexOf('{');
+ if (leftBracePos == -1) {
+ if (!attributeNames.contains(name)) {
+ throw new UnavailableAttributeException(clusterName, name);
+ }
+ } else {
+ String baseName = name.substring(0, leftBracePos);
+ String keyName = baseName + ".key";
+ if (!attributeNames.contains(keyName)) {
+ throw new UnavailableAttributeException(clusterName, keyName);
+ }
+ int rightBracePos = name.lastIndexOf('}');
+ String valueName = baseName + ".value" + name.substring(rightBracePos + 1);
+ if (!attributeNames.contains(valueName)) {
+ throw new UnavailableAttributeException(clusterName, valueName);
+ }
}
}
}
diff --git a/container-search/src/test/java/com/yahoo/search/grouping/GroupingValidatorTestCase.java b/container-search/src/test/java/com/yahoo/search/grouping/GroupingValidatorTestCase.java
index 82c05c1d995..055ea5929db 100644
--- a/container-search/src/test/java/com/yahoo/search/grouping/GroupingValidatorTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/grouping/GroupingValidatorTestCase.java
@@ -7,50 +7,101 @@ import com.yahoo.search.Query;
import com.yahoo.search.config.ClusterConfig;
import com.yahoo.search.grouping.request.GroupingOperation;
import com.yahoo.search.searchchain.Execution;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
import java.util.Arrays;
import java.util.Collection;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
-
/**
* @author Simon Thoresen Hult
*/
public class GroupingValidatorTestCase {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
@Test
public void requireThatAvailableAttributesDoNotThrow() {
- Query query = new Query();
- GroupingRequest req = GroupingRequest.newInstance(query);
- req.setRootOperation(GroupingOperation.fromString("all(group(foo) each(output(max(bar))))"));
- validateGrouping("myCluster", Arrays.asList("foo", "bar"), query);
+ validateGrouping("myCluster", Arrays.asList("foo", "bar"),
+ "all(group(foo) each(output(max(bar))))");;
}
@Test
public void requireThatUnavailableAttributesThrow() {
- Query query = new Query();
- GroupingRequest req = GroupingRequest.newInstance(query);
- req.setRootOperation(GroupingOperation.fromString("all(group(foo) each(output(max(bar))))"));
- try {
- validateGrouping("myCluster", Arrays.asList("foo"), query);
- fail("Validator should throw exception because attribute 'bar' is unavailable.");
- } catch (UnavailableAttributeException e) {
- assertEquals("myCluster", e.getClusterName());
- assertEquals("bar", e.getAttributeName());
- }
+ thrown.expect(UnavailableAttributeException.class);
+ thrown.expectMessage(createMessage("myCluster", "bar"));
+ validateGrouping("myCluster", Arrays.asList("foo"),
+ "all(group(foo) each(output(max(bar))))");
}
@Test
public void requireThatEnableFlagPreventsThrow() {
- Query query = new Query();
- GroupingRequest req = GroupingRequest.newInstance(query);
- req.setRootOperation(GroupingOperation.fromString("all(group(foo) each(output(max(bar))))"));
+ Query query = createQuery("all(group(foo) each(output(max(bar))))");
query.properties().set(GroupingValidator.PARAM_ENABLED, "false");
validateGrouping("myCluster", Arrays.asList("foo"), query);
}
+ @Test
+ public void available_primitive_map_attribute_does_not_throw() {
+ validateGrouping("myCluster", Arrays.asList("map.key", "map.value"),
+ "all(group(map{\"foo\"}) each(output(count())))");
+ }
+
+ @Test
+ public void unavailable_primitive_map_key_attribute_throws() {
+ thrown.expect(UnavailableAttributeException.class);
+ thrown.expectMessage(createMessage("myCluster", "map.key"));
+ validateGrouping("myCluster", Arrays.asList("null"),
+ "all(group(map{\"foo\"}) each(output(count())))");
+ }
+
+ @Test
+ public void unavailable_primitive_map_value_attribute_throws() {
+ thrown.expect(UnavailableAttributeException.class);
+ thrown.expectMessage(createMessage("myCluster", "map.value"));
+ validateGrouping("myCluster", Arrays.asList("map.key"),
+ "all(group(map{\"foo\"}) each(output(count())))");
+ }
+
+ @Test
+ public void available_struct_map_attribute_does_not_throw() {
+ validateGrouping("myCluster", Arrays.asList("map.key", "map.value.name"),
+ "all(group(map{\"foo\"}.name) each(output(count())))");
+ }
+
+ @Test
+ public void unavailable_struct_map_key_attribute_throws() {
+ thrown.expect(UnavailableAttributeException.class);
+ thrown.expectMessage(createMessage("myCluster", "map.key"));
+ validateGrouping("myCluster", Arrays.asList("null"),
+ "all(group(map{\"foo\"}.name) each(output(count())))");
+ }
+
+ @Test
+ public void unavailable_struct_map_value_attribute_throws() {
+ thrown.expect(UnavailableAttributeException.class);
+ thrown.expectMessage(createMessage("myCluster", "map.value.name"));
+ validateGrouping("myCluster", Arrays.asList("map.key"),
+ "all(group(map{\"foo\"}.name) each(output(count())))");
+ }
+
+ private static String createMessage(String clusterName, String attributeName) {
+ return "Grouping request references attribute '" + attributeName + "' which is not available in cluster '" + clusterName + "'.";
+ }
+
+ private static Query createQuery(String groupingExpression) {
+ Query query = new Query();
+ GroupingRequest req = GroupingRequest.newInstance(query);
+ req.setRootOperation(GroupingOperation.fromString(groupingExpression));
+ return query;
+ }
+
+ private static void validateGrouping(String clusterName, Collection<String> attributeNames, String groupingExpression) {
+ validateGrouping(clusterName, attributeNames, createQuery(groupingExpression));
+ }
+
private static void validateGrouping(String clusterName, Collection<String> attributeNames, Query query) {
QrSearchersConfig.Builder qrsConfig = new QrSearchersConfig.Builder().searchcluster(
new QrSearchersConfig.Searchcluster.Builder()