diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2018-06-03 13:59:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-03 13:59:26 +0200 |
commit | b42b350a9892d2ca4fd2d2c3ef022e4e8565a8f4 (patch) | |
tree | 89c962e41535ea2de52bb370ff7c6846616f6397 | |
parent | a98edada487056d6d155e7ab419734809acd20ef (diff) | |
parent | e30aeab40c5a7e0f6265f41a812d07175227b90b (diff) |
Merge pull request #6063 from vespa-engine/balder/allow-dot-nested-fieldnames-in-yql
Allow nested fieldnames using '.' in yql.
-rw-r--r-- | container-search/src/main/java/com/yahoo/search/yql/YqlParser.java | 44 | ||||
-rw-r--r-- | container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java | 13 |
2 files changed, 39 insertions, 18 deletions
diff --git a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java index 38a87f3b7bc..0b9f79537d0 100644 --- a/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java +++ b/container-search/src/main/java/com/yahoo/search/yql/YqlParser.java @@ -915,8 +915,16 @@ public class YqlParser implements Parser { @NonNull private static String fetchFieldRead(OperatorNode<ExpressionOperator> ast) { - assertHasOperator(ast, ExpressionOperator.READ_FIELD); - return ast.getArgument(1); + switch (ast.getOperator()) { + case READ_FIELD: + return ast.getArgument(1); + case PROPREF: + return new StringBuilder(fetchFieldRead(ast.getArgument(0))) + .append('.').append(ast.getArgument(1).toString()).toString(); + default: + throw newUnexpectedArgumentException(ast.getOperator(), + ExpressionOperator.READ_FIELD, ExpressionOperator.PROPREF); + } } @NonNull @@ -986,14 +994,12 @@ public class YqlParser implements Parser { OperatorNode<ExpressionOperator> lhs = ast.getArgument(0); OperatorNode<ExpressionOperator> rhs = ast.getArgument(1); if (lhs.getOperator() == ExpressionOperator.LITERAL || lhs.getOperator() == ExpressionOperator.NEGATE) { - assertHasOperator(rhs, ExpressionOperator.READ_FIELD); return getIndex(rhs); } if (rhs.getOperator() == ExpressionOperator.LITERAL || rhs.getOperator() == ExpressionOperator.NEGATE) { - assertHasOperator(lhs, ExpressionOperator.READ_FIELD); return getIndex(lhs); } - throw new IllegalArgumentException("Expected LITERAL and READ_FIELD, got " + lhs.getOperator() + + throw new IllegalArgumentException("Expected LITERAL and READ_FIELD/PROPREF, got " + lhs.getOperator() + " and " + rhs.getOperator() + "."); } @@ -1009,28 +1015,24 @@ public class YqlParser implements Parser { } @NonNull - private static String fetchConditionWord( - OperatorNode<ExpressionOperator> ast) { + private static String fetchConditionWord(OperatorNode<ExpressionOperator> ast) { OperatorNode<ExpressionOperator> lhs = ast.getArgument(0); OperatorNode<ExpressionOperator> rhs = ast.getArgument(1); - if (lhs.getOperator() == ExpressionOperator.LITERAL - || lhs.getOperator() == ExpressionOperator.NEGATE) { - assertHasOperator(rhs, ExpressionOperator.READ_FIELD); + if (lhs.getOperator() == ExpressionOperator.LITERAL || lhs.getOperator() == ExpressionOperator.NEGATE) { + assertFieldName(rhs); return getNumberAsString(lhs); } - if (rhs.getOperator() == ExpressionOperator.LITERAL - || rhs.getOperator() == ExpressionOperator.NEGATE) { - assertHasOperator(lhs, ExpressionOperator.READ_FIELD); + if (rhs.getOperator() == ExpressionOperator.LITERAL || rhs.getOperator() == ExpressionOperator.NEGATE) { + assertFieldName(lhs); return getNumberAsString(rhs); } - throw new IllegalArgumentException( - "Expected LITERAL/NEGATE and READ_FIELD, got " + throw new IllegalArgumentException("Expected LITERAL/NEGATE and READ_FIELD/PROPREF, got " + lhs.getOperator() + " and " + rhs.getOperator() + "."); } - private static boolean isIndexOnLeftHandSide( - OperatorNode<ExpressionOperator> ast) { - return ast.getArgument(0, OperatorNode.class).getOperator() == ExpressionOperator.READ_FIELD; + private static boolean isIndexOnLeftHandSide(OperatorNode<ExpressionOperator> ast) { + OperatorNode node = ast.getArgument(0, OperatorNode.class); + return node.getOperator() == ExpressionOperator.READ_FIELD || node.getOperator() == ExpressionOperator.PROPREF; } @NonNull @@ -1558,6 +1560,12 @@ public class YqlParser implements Parser { expectedFunctionName, names.get(0)); } + private static void assertFieldName(OperatorNode<?> ast) { + Preconditions.checkArgument(ast.getOperator() == ExpressionOperator.READ_FIELD || + ast.getOperator() == ExpressionOperator.PROPREF, + "Expected operator READ_FIELD or PRPPREF, got %s.", ast.getOperator()); + } + private static void addItems(OperatorNode<ExpressionOperator> ast, WeightedSetItem out) { switch (ast.getOperator()) { case MAP: diff --git a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java index ac1969701ca..8bbe43ee3d4 100644 --- a/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java @@ -118,6 +118,17 @@ public class YqlParserTestCase { } @Test + public void testDottedFieldNames() { + assertParse("select foo from bar where my.nested.title contains \"madonna\";", + "my.nested.title:madonna"); + } + @Test + public void testDottedNestedFieldNames() { + assertParse("select foo from bar where my.title contains \"madonna\";", + "my.title:madonna"); + } + + @Test public void testOr() { assertParse("select foo from bar where title contains \"madonna\" or title contains \"saint\";", "OR title:madonna title:saint"); @@ -266,6 +277,8 @@ public class YqlParserTestCase { "baz:{f1:a f2:b}"); assertParse("select foo from bar where baz contains sameElement(f1 contains \"a\", f2 = 10);", "baz:{f1:a f2:10}"); + assertParse("select foo from bar where baz contains sameElement(key contains \"a\", value.f2 = 10);", + "baz:{key:a value.f2:10}"); } @Test |