summaryrefslogtreecommitdiffstats
path: root/container-search
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@verizonmedia.com>2019-05-20 13:53:37 +0200
committerJon Bratseth <bratseth@verizonmedia.com>2019-05-20 13:53:37 +0200
commit5d86a48ada45c73fc28b733dd8ed0b3ee50f9663 (patch)
treef8efbd97e23ecf165375f18a40b5a3f07ea0a84f /container-search
parente3e9c7536295537e2a9c9c430e6a0f1cda76baca (diff)
Test searching for backslash
Diffstat (limited to 'container-search')
-rw-r--r--container-search/src/main/java/com/yahoo/search/yql/YqlParser.java76
-rw-r--r--container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java2
-rw-r--r--container-search/src/test/java/com/yahoo/search/yql/YqlParserTestCase.java34
3 files changed, 52 insertions, 60 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 4061af72fd6..23dcaba0b3b 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
@@ -877,80 +877,65 @@ public class YqlParser implements Parser {
return ast.getArgument(0);
}
- @NonNull
private static String fetchFieldRead(OperatorNode<ExpressionOperator> ast) {
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();
+ return fetchFieldRead(ast.getArgument(0)) + '.' + ast.getArgument(1);
default:
throw newUnexpectedArgumentException(ast.getOperator(),
- ExpressionOperator.READ_FIELD, ExpressionOperator.PROPREF);
+ ExpressionOperator.READ_FIELD, ExpressionOperator.PROPREF);
}
}
- @NonNull
private IntItem buildGreaterThanOrEquals(OperatorNode<ExpressionOperator> ast) {
- IntItem number;
if (isIndexOnLeftHandSide(ast)) {
- number = new IntItem("[" + fetchConditionWord(ast) + ";]", fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
+ IntItem number = new IntItem("[" + fetchConditionWord(ast) + ";]", fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
} else {
- number = new IntItem("[;" + fetchConditionWord(ast) + "]", fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
+ IntItem number = new IntItem("[;" + fetchConditionWord(ast) + "]", fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
}
- return number;
}
- @NonNull
private IntItem buildLessThanOrEquals(OperatorNode<ExpressionOperator> ast) {
- IntItem number;
if (isIndexOnLeftHandSide(ast)) {
- number = new IntItem("[;" + fetchConditionWord(ast) + "]", fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
+ IntItem number = new IntItem("[;" + fetchConditionWord(ast) + "]", fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
} else {
- number = new IntItem("[" + fetchConditionWord(ast) + ";]", fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
+ IntItem number = new IntItem("[" + fetchConditionWord(ast) + ";]", fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
}
- return number;
}
- @NonNull
private IntItem buildGreaterThan(OperatorNode<ExpressionOperator> ast) {
- IntItem number;
if (isIndexOnLeftHandSide(ast)) {
- number = new IntItem(">" + fetchConditionWord(ast), fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
+ IntItem number = new IntItem(">" + fetchConditionWord(ast), fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
} else {
- number = new IntItem("<" + fetchConditionWord(ast), fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
+ IntItem number = new IntItem("<" + fetchConditionWord(ast), fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
}
- return number;
}
- @NonNull
private IntItem buildLessThan(OperatorNode<ExpressionOperator> ast) {
- IntItem number;
if (isIndexOnLeftHandSide(ast)) {
- number = new IntItem("<" + fetchConditionWord(ast), fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
+ IntItem number = new IntItem("<" + fetchConditionWord(ast), fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(1, OperatorNode.class), number);
} else {
- number = new IntItem(">" + fetchConditionWord(ast), fetchConditionIndex(ast));
- number = leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
+ IntItem number = new IntItem(">" + fetchConditionWord(ast), fetchConditionIndex(ast));
+ return leafStyleSettings(ast.getArgument(0, OperatorNode.class), number);
}
- return number;
}
- @NonNull
private TermItem buildEquals(OperatorNode<ExpressionOperator> ast) {
String value = fetchConditionWord(ast);
TermItem item;
- if (value.equals("true")) {
+ if (value.equals("true"))
item = new BoolItem(true, fetchConditionIndex(ast));
- } else if (value.equals("false"))
+ else if (value.equals("false"))
item = new BoolItem(false, fetchConditionIndex(ast));
else
item = new IntItem(value, fetchConditionIndex(ast));
@@ -961,7 +946,6 @@ public class YqlParser implements Parser {
return leafStyleSettings(ast.getArgument(0, OperatorNode.class), item);
}
- @NonNull
private String fetchConditionIndex(OperatorNode<ExpressionOperator> ast) {
OperatorNode<ExpressionOperator> lhs = ast.getArgument(0);
OperatorNode<ExpressionOperator> rhs = ast.getArgument(1);
@@ -986,7 +970,6 @@ public class YqlParser implements Parser {
return negative + currentAst.getArgument(0).toString();
}
- @NonNull
private static String fetchConditionWord(OperatorNode<ExpressionOperator> ast) {
OperatorNode<ExpressionOperator> lhs = ast.getArgument(0);
OperatorNode<ExpressionOperator> rhs = ast.getArgument(1);
@@ -1007,7 +990,6 @@ public class YqlParser implements Parser {
return node.getOperator() == ExpressionOperator.READ_FIELD || node.getOperator() == ExpressionOperator.PROPREF;
}
- @NonNull
private CompositeItem buildAnd(OperatorNode<ExpressionOperator> ast) {
AndItem andItem = new AndItem();
NotItem notItem = new NotItem();
@@ -1026,12 +1008,10 @@ public class YqlParser implements Parser {
return notItem;
}
- @NonNull
private CompositeItem buildOr(OperatorNode<ExpressionOperator> spec) {
return convertVarArgs(spec, 0, new OrItem());
}
- @NonNull
private CompositeItem buildWeakAnd(OperatorNode<ExpressionOperator> spec) {
WeakAndItem weakAnd = new WeakAndItem();
Integer targetNumHits = getAnnotation(spec, TARGET_NUM_HITS,
@@ -1047,12 +1027,10 @@ public class YqlParser implements Parser {
return convertVarArgs(spec, 1, weakAnd);
}
- @NonNull
private CompositeItem buildRank(OperatorNode<ExpressionOperator> spec) {
return convertVarArgs(spec, 1, new RankItem());
}
- @NonNull
private CompositeItem convertVarArgs(OperatorNode<ExpressionOperator> ast, int argIdx, @NonNull CompositeItem out) {
Iterable<OperatorNode<ExpressionOperator>> args = ast.getArgument(argIdx);
for (OperatorNode<ExpressionOperator> arg : args) {
@@ -1076,7 +1054,6 @@ public class YqlParser implements Parser {
}
}
- @NonNull
private Item buildTermSearch(OperatorNode<ExpressionOperator> ast) {
assertHasOperator(ast, ExpressionOperator.CONTAINS);
String field = getIndex(ast.<OperatorNode<ExpressionOperator>>getArgument(0));
@@ -1086,7 +1063,6 @@ public class YqlParser implements Parser {
return instantiateLeafItem(field, ast.<OperatorNode<ExpressionOperator>> getArgument(1));
}
- @NonNull
private Item buildRegExpSearch(OperatorNode<ExpressionOperator> ast) {
assertHasOperator(ast, ExpressionOperator.MATCHES);
String field = getIndex(ast.<OperatorNode<ExpressionOperator>>getArgument(0));
@@ -1099,8 +1075,6 @@ public class YqlParser implements Parser {
return leafStyleSettings(ast1, regExp);
}
-
- @NonNull
private Item buildRange(OperatorNode<ExpressionOperator> spec) {
assertHasOperator(spec, ExpressionOperator.CALL);
assertHasFunctionName(spec, RANGE);
@@ -1127,7 +1101,6 @@ public class YqlParser implements Parser {
}
}
- @NonNull
private IntItem instantiateRangeItem(
List<OperatorNode<ExpressionOperator>> args,
OperatorNode<ExpressionOperator> spec) {
@@ -1177,7 +1150,6 @@ public class YqlParser implements Parser {
return boundValue;
}
- @NonNull
private Item instantiateLeafItem(String field, OperatorNode<ExpressionOperator> ast) {
switch (ast.getOperator()) {
case LITERAL:
@@ -1191,7 +1163,6 @@ public class YqlParser implements Parser {
}
}
- @NonNull
private Item instantiateCompositeLeaf(String field, OperatorNode<ExpressionOperator> ast) {
List<String> names = ast.getArgument(0);
Preconditions.checkArgument(names.size() == 1, "Expected 1 name, got %s.", names.size());
@@ -1237,7 +1208,6 @@ public class YqlParser implements Parser {
return leafStyleSettings(ast, new WordAlternativesItem(field, isFromQuery, origin, terms));
}
- @NonNull
private Item instantiateEquivItem(String field, OperatorNode<ExpressionOperator> ast) {
List<OperatorNode<ExpressionOperator>> args = ast.getArgument(1);
Preconditions.checkArgument(args.size() >= 2, "Expected 2 or more arguments, got %s.", args.size());
@@ -1261,12 +1231,10 @@ public class YqlParser implements Parser {
return leafStyleSettings(ast, equiv);
}
- @NonNull
private Item instantiateWordItem(String field, OperatorNode<ExpressionOperator> ast, Class<?> parent) {
return instantiateWordItem(field, ast, parent, SegmentWhen.POSSIBLY);
}
- @NonNull
private Item instantiateWordItem(String field,
OperatorNode<ExpressionOperator> ast, Class<?> parent,
SegmentWhen segmentPolicy) {
@@ -1352,7 +1320,6 @@ public class YqlParser implements Parser {
return fromQuery && ! indexFactsSession.getIndex(indexNameExpander.expand(field)).isAttribute();
}
- @NonNull
private TaggableItem segment(String field, OperatorNode<ExpressionOperator> ast, String wordData,
boolean fromQuery, Class<?> parent, Language language) {
String toSegment = wordData;
@@ -1395,7 +1362,6 @@ public class YqlParser implements Parser {
wordStyleSettings(ast, wordItem);
}
- @NonNull
private <T extends TaggableItem> T leafStyleSettings(OperatorNode<?> ast, @NonNull T out) {
{
Map<?, ?> connectivity = getAnnotation(ast, CONNECTIVITY, Map.class, null, "connectivity settings");
@@ -1632,7 +1598,7 @@ public class YqlParser implements Parser {
indexNameExpander = newExpander;
return old;
}
- @NonNull
+
private String getIndex(OperatorNode<ExpressionOperator> operatorNode) {
String index = fetchFieldRead(operatorNode);
String expanded = indexNameExpander.expand(index);
diff --git a/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java b/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java
index e89c8aeb409..ef0efd41e19 100644
--- a/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java
+++ b/container-search/src/test/java/com/yahoo/search/yql/MinimalQueryInserterTestCase.java
@@ -49,7 +49,7 @@ public class MinimalQueryInserterTestCase {
}
@After
- public void tearDown() throws Exception {
+ public void tearDown() {
searchChain = null;
context = null;
execution = null;
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 531167bb342..18fad47de37 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
@@ -2,8 +2,10 @@
package com.yahoo.search.yql;
import com.yahoo.component.Version;
+import com.yahoo.component.chain.Chain;
import com.yahoo.container.QrSearchersConfig;
import com.yahoo.language.Language;
+import com.yahoo.language.simple.SimpleLinguistics;
import com.yahoo.prelude.IndexFacts;
import com.yahoo.prelude.IndexModel;
import com.yahoo.prelude.query.AndItem;
@@ -25,6 +27,7 @@ import com.yahoo.prelude.query.WordAlternativesItem;
import com.yahoo.prelude.query.WordItem;
import com.yahoo.prelude.querytransform.QueryRewrite;
import com.yahoo.search.Query;
+import com.yahoo.search.Searcher;
import com.yahoo.search.config.IndexInfoConfig;
import com.yahoo.search.config.IndexInfoConfig.Indexinfo;
import com.yahoo.search.config.IndexInfoConfig.Indexinfo.Alias;
@@ -38,6 +41,7 @@ import com.yahoo.search.query.Sorting.UcaSorter;
import com.yahoo.search.query.parser.Parsable;
import com.yahoo.search.query.parser.ParserEnvironment;
+import com.yahoo.search.searchchain.Execution;
import org.junit.Test;
import java.util.ArrayList;
@@ -906,6 +910,30 @@ public class YqlParserTestCase {
assertEquals("foo:\"forest WORD_ALTERNATIVES foo:[ tree(0.7) trees(1.0) ]\"", root.toString());
}
+ /** Verifies that we can search for a backslash */
+ @Test
+ public void testBackslash() {
+ {
+ String queryString = "select * from testtype where title contains \"\\\\\";"; // Java escaping * YQL escaping
+
+ QueryTree query = parse(queryString);
+
+ assertEquals("title:\\", query.toString());
+ }
+
+ {
+ Query query = new Query("search?yql=select%20*%20from%20testtype%20where%20title%20contains%20%22%5C%5C%22;");
+
+ // Cause parsing :-\
+ Chain<Searcher> searchChain = new Chain<>(new MinimalQueryInserter());
+ Execution.Context context = Execution.Context.createContextStub(null, null, new SimpleLinguistics());
+ Execution execution = new Execution(searchChain, context);
+ execution.search(query);
+
+ assertEquals("title:\\", query.getModel().getQueryTree().toString());
+ }
+ }
+
private void checkWordAlternativesContent(WordAlternativesItem alternatives) {
boolean seenTree = false;
boolean seenForest = false;
@@ -981,10 +1009,8 @@ public class YqlParserTestCase {
private static String toString(List<VespaGroupingStep> steps) {
List<String> actual = new ArrayList<>(steps.size());
- for (VespaGroupingStep step : steps) {
- actual.add(step.continuations().toString() +
- step.getOperation());
- }
+ for (VespaGroupingStep step : steps)
+ actual.add(step.continuations().toString() + step.getOperation());
return actual.toString();
}
}