diff --git a/src/java/org/apache/lucene/queryParser/QueryParser.java b/src/java/org/apache/lucene/queryParser/QueryParser.java
index 121dc7dd87c..a34e1cf8ac9 100644
--- a/src/java/org/apache/lucene/queryParser/QueryParser.java
+++ b/src/java/org/apache/lucene/queryParser/QueryParser.java
@@ -429,6 +429,25 @@ public class QueryParser implements QueryParserConstants {
return new String(caDest, 0, j);
}
+ /**
+ * Returns a String where those characters that QueryParser
+ * expects to be escaped are escaped, i.e. preceded by a \
.
+ */
+ public static String escape(String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ // NOTE: keep this in sync with _ESCAPED_CHAR below!
+ if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
+ || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
+ || c == '*' || c == '?') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
public static void main(String[] args) throws Exception {
QueryParser qp = new QueryParser("field",
new org.apache.lucene.analysis.SimpleAnalyzer());
diff --git a/src/java/org/apache/lucene/queryParser/QueryParser.jj b/src/java/org/apache/lucene/queryParser/QueryParser.jj
index 85ec5511338..44a2cf9b389 100644
--- a/src/java/org/apache/lucene/queryParser/QueryParser.jj
+++ b/src/java/org/apache/lucene/queryParser/QueryParser.jj
@@ -452,6 +452,25 @@ public class QueryParser {
return new String(caDest, 0, j);
}
+ /**
+ * Returns a String where those characters that QueryParser
+ * expects to be escaped are escaped, i.e. preceded by a \
.
+ */
+ public static String escape(String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < s.length(); i++) {
+ char c = s.charAt(i);
+ // NOTE: keep this in sync with _ESCAPED_CHAR below!
+ if (c == '\\' || c == '+' || c == '-' || c == '!' || c == '(' || c == ')' || c == ':'
+ || c == '^' || c == '[' || c == ']' || c == '\"' || c == '{' || c == '}' || c == '~'
+ || c == '*' || c == '?') {
+ sb.append('\\');
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
public static void main(String[] args) throws Exception {
QueryParser qp = new QueryParser("field",
new org.apache.lucene.analysis.SimpleAnalyzer());
@@ -468,6 +487,7 @@ PARSER_END(QueryParser)
<*> TOKEN : {
<#_NUM_CHAR: ["0"-"9"] >
+// NOTE: keep this in sync with escape(String) above!
| <#_ESCAPED_CHAR: "\\" [ "\\", "+", "-", "!", "(", ")", ":", "^",
"[", "]", "\"", "{", "}", "~", "*", "?" ] >
| <#_TERM_START_CHAR: ( ~[ " ", "\t", "\n", "\r", "+", "-", "!", "(", ")", ":", "^",
diff --git a/src/java/org/apache/lucene/search/TermQuery.java b/src/java/org/apache/lucene/search/TermQuery.java
index 6ff9b2994a7..fa99867d84a 100644
--- a/src/java/org/apache/lucene/search/TermQuery.java
+++ b/src/java/org/apache/lucene/search/TermQuery.java
@@ -20,6 +20,7 @@ import java.io.IOException;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.TermDocs;
import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.queryParser.QueryParser;
/** A Query that matches documents containing a term.
This may be combined with other terms with a {@link BooleanQuery}.
@@ -142,10 +143,10 @@ public class TermQuery extends Query {
public String toString(String field) {
StringBuffer buffer = new StringBuffer();
if (!term.field().equals(field)) {
- buffer.append(term.field());
+ buffer.append(QueryParser.escape(term.field()));
buffer.append(":");
}
- buffer.append(term.text());
+ buffer.append(QueryParser.escape(term.text()));
if (getBoost() != 1.0f) {
buffer.append("^");
buffer.append(Float.toString(getBoost()));
diff --git a/src/test/org/apache/lucene/queryParser/TestQueryParser.java b/src/test/org/apache/lucene/queryParser/TestQueryParser.java
index c3519bb7ef7..ec0a763033e 100644
--- a/src/test/org/apache/lucene/queryParser/TestQueryParser.java
+++ b/src/test/org/apache/lucene/queryParser/TestQueryParser.java
@@ -317,7 +317,7 @@ public class TestQueryParser extends TestCase {
public void testEscaped() throws Exception {
Analyzer a = new WhitespaceAnalyzer();
- /* assertQueryEquals("\\[brackets", a, "\\[brackets");
+ assertQueryEquals("\\[brackets", a, "\\[brackets");
assertQueryEquals("\\[brackets", null, "brackets");
assertQueryEquals("\\\\", a, "\\\\");
assertQueryEquals("\\+blah", a, "\\+blah");
@@ -337,29 +337,33 @@ public class TestQueryParser extends TestCase {
assertQueryEquals("\\~blah", a, "\\~blah");
assertQueryEquals("\\*blah", a, "\\*blah");
assertQueryEquals("\\?blah", a, "\\?blah");
- assertQueryEquals("foo \\&& bar", a, "foo \\&& bar");
- assertQueryEquals("foo \\|| bar", a, "foo \\|| bar");
- assertQueryEquals("foo \\AND bar", a, "foo \\AND bar"); */
+
+ // TODO: what about these?
+ //assertQueryEquals("foo \\&\\& bar", a, "foo \\&\\& bar");
+ //assertQueryEquals("foo \\|| bar", a, "foo \\|| bar");
+ //assertQueryEquals("foo \\AND bar", a, "foo \\AND bar");
- assertQueryEquals("a\\-b:c",a,"a-b:c");
- assertQueryEquals("a\\+b:c",a,"a+b:c");
- assertQueryEquals("a\\:b:c",a,"a:b:c");
- assertQueryEquals("a\\\\b:c",a,"a\\b:c");
+ assertQueryEquals("a\\-b:c",a,"a\\-b:c");
+ assertQueryEquals("a\\+b:c",a,"a\\+b:c");
+ assertQueryEquals("a\\:b:c",a,"a\\:b:c");
+ assertQueryEquals("a\\\\b:c",a,"a\\\\b:c");
- assertQueryEquals("a:b\\-c",a,"a:b-c");
- assertQueryEquals("a:b\\+c",a,"a:b+c");
- assertQueryEquals("a:b\\:c",a,"a:b:c");
- assertQueryEquals("a:b\\\\c",a,"a:b\\c");
+ assertQueryEquals("a:b\\-c",a,"a:b\\-c");
+ assertQueryEquals("a:b\\+c",a,"a:b\\+c");
+ assertQueryEquals("a:b\\:c",a,"a:b\\:c");
+ assertQueryEquals("a:b\\\\c",a,"a:b\\\\c");
assertQueryEquals("a:b\\-c*",a,"a:b-c*");
assertQueryEquals("a:b\\+c*",a,"a:b+c*");
assertQueryEquals("a:b\\:c*",a,"a:b:c*");
+
assertQueryEquals("a:b\\\\c*",a,"a:b\\c*");
assertQueryEquals("a:b\\-?c",a,"a:b-?c");
assertQueryEquals("a:b\\+?c",a,"a:b+?c");
assertQueryEquals("a:b\\:?c",a,"a:b:?c");
- assertQueryEquals("a:b\\\\?c",a,"a:b\\?c");
+
+ assertQueryEquals("a:b\\\\?c",a,"a:b\\\\\\?c");
assertQueryEquals("a:b\\-c~",a,"a:b-c~");
assertQueryEquals("a:b\\+c~",a,"a:b+c~");