diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index d1266f772c4..f14b91345e7 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -740,6 +740,9 @@ Bug Fixes * SOLR-3046: Fix whitespace typo in DIH response "Time taken" (hossman) +* SOLR-3261: Fix edismax to respect query operators when literal colons + are used in query string. (Juan Grande via hossman) + Other Changes ---------------------- * SOLR-2922: Upgrade commons-io and commons-lang to 2.1 and 2.6, respectively. (koji) diff --git a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParserPlugin.java b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParserPlugin.java index 8ce05c1c50f..f21636f8168 100755 --- a/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParserPlugin.java +++ b/solr/core/src/java/org/apache/solr/search/ExtendedDismaxQParserPlugin.java @@ -635,14 +635,17 @@ class ExtendedDismaxQParser extends QParser { public List splitIntoClauses(String s, boolean ignoreQuote) { ArrayList lst = new ArrayList(4); - Clause clause = new Clause(); + Clause clause; int pos=0; int end=s.length(); char ch=0; int start; - boolean disallowUserField = false; + boolean disallowUserField; outer: while (pos < end) { + clause = new Clause(); + disallowUserField = true; + ch = s.charAt(pos); while (Character.isWhitespace(ch)) { @@ -659,10 +662,10 @@ class ExtendedDismaxQParser extends QParser { clause.field = getFieldName(s, pos, end); if(clause.field != null && !userFields.isAllowed(clause.field)) { - disallowUserField = true; clause.field = null; } if (clause.field != null) { + disallowUserField = false; pos += clause.field.length(); // skip the field name pos++; // skip the ':' } @@ -758,7 +761,11 @@ class ExtendedDismaxQParser extends QParser { if (clause != null) { if(disallowUserField) { - clause.raw = clause.val; + clause.raw = s.substring(start, pos); + // escape colons, except for "match all" query + if(!"*:*".equals(clause.raw)) { + clause.raw = clause.raw.replaceAll(":", "\\\\:"); + } } else { clause.raw = s.substring(start, pos); // Add default userField boost if no explicit boost exists @@ -770,8 +777,6 @@ class ExtendedDismaxQParser extends QParser { } lst.add(clause); } - clause = new Clause(); - disallowUserField = false; } return lst; diff --git a/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java b/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java index b60d61e8c55..6c15e48f638 100755 --- a/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java +++ b/solr/core/src/test/org/apache/solr/search/TestExtendedDismaxParser.java @@ -464,5 +464,70 @@ public class TestExtendedDismaxParser extends AbstractSolrTestCase { assertTrue(e.getCause().getMessage().contains("Field aliases lead to a cycle")); } } - + + public void testOperatorsWithLiteralColons() { + assertU(adoc("id", "142", "a_s", "bogus:xxx", "text_s", "yak")); + assertU(adoc("id", "143", "a_s", "bogus:xxx")); + assertU(adoc("id", "144", "text_s", "yak")); + assertU(adoc("id", "145", "a_s", "a_s:xxx", "text_s", "yak")); + assertU(adoc("id", "146", "a_s", "a_s:xxx")); + assertU(adoc("id", "147", "a_s", "AND", "a_s", "NOT")); + assertU(commit()); + + assertQ(req("q", "bogus:xxx AND text_s:yak", + "fl", "id", + "qf", "a_s b_s", + "defType", "edismax", + "mm", "0"), + "//*[@numFound='1']", + "//str[@name='id'][.='142']"); + + assertQ(req("q", "a_s:xxx AND text_s:yak", + "fl", "id", + "qf", "a_s b_s", + "defType", "edismax", + "mm", "0", + "uf", "text_s"), + "//*[@numFound='1']", + "//str[@name='id'][.='145']"); + + assertQ(req("q", "NOT bogus:xxx +text_s:yak", + "fl", "id", + "qf", "a_s b_s", + "defType", "edismax", + "mm", "0", + "debugQuery", "true"), + "//*[@numFound='2']", + "//str[@name='id'][.='144']", + "//str[@name='id'][.='145']"); + + assertQ(req("q", "NOT a_s:xxx +text_s:yak", + "fl", "id", + "qf", "a_s b_s", + "defType", "edismax", + "mm", "0", + "uf", "text_s"), + "//*[@numFound='2']", + "//str[@name='id'][.='142']", + "//str[@name='id'][.='144']"); + + assertQ(req("q", "+bogus:xxx yak", + "fl", "id", + "qf", "a_s b_s text_s", + "defType", "edismax", + "mm", "0"), + "//*[@numFound='2']", + "//str[@name='id'][.='142']", + "//str[@name='id'][.='143']"); + + assertQ(req("q", "+a_s:xxx yak", + "fl", "id", + "qf", "a_s b_s text_s", + "defType", "edismax", + "mm", "0", + "uf", "b_s"), + "//*[@numFound='2']", + "//str[@name='id'][.='145']", + "//str[@name='id'][.='146']"); + } }