Index: src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java =================================================================== --- src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java (revision 548835) +++ src/test/org/apache/lucene/queryParser/TestMultiFieldQueryParser.java (working copy) @@ -26,9 +26,11 @@ import org.apache.lucene.document.Field; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.search.BooleanClause; +import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.Hits; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; +import org.apache.lucene.search.BooleanClause.Occur; import org.apache.lucene.store.Directory; import org.apache.lucene.store.RAMDirectory; @@ -42,6 +44,28 @@ */ public class TestMultiFieldQueryParser extends TestCase { + public void testWithStopwords() throws Exception { + assertStopQueryEquals("one", "b:one t:one"); + assertStopQueryEquals("one stop", "b:one t:one"); + assertStopQueryEquals("one (stop)", "b:one t:one"); + assertStopQueryEquals("stop", ""); + assertStopQueryEquals("(stop)", ""); + } + + // verify parsing of query using a stoppng analyzrt + private void assertStopQueryEquals (String qtxt, String expectedRes) throws Exception { + String[] fields = {"b", "t"}; + Occur occur[] = {Occur.SHOULD, Occur.SHOULD}; + TestQueryParser.QPTestAnalyzer a = new TestQueryParser.QPTestAnalyzer(); + MultiFieldQueryParser mfqp = new MultiFieldQueryParser(fields, a); + + Query q = mfqp.parse(qtxt); + assertEquals(expectedRes, q.toString()); + + q = MultiFieldQueryParser.parse(qtxt, fields, occur, a); + assertEquals(expectedRes, q.toString()); + } + public void testSimple() throws Exception { String[] fields = {"b", "t"}; MultiFieldQueryParser mfqp = new MultiFieldQueryParser(fields, new StandardAnalyzer()); Index: src/test/org/apache/lucene/queryParser/TestQueryParser.java =================================================================== --- src/test/org/apache/lucene/queryParser/TestQueryParser.java (revision 548835) +++ src/test/org/apache/lucene/queryParser/TestQueryParser.java (working copy) @@ -365,15 +365,27 @@ } public void testQPA() throws Exception { + assertQueryEquals("term term^3.0 term", qpAnalyzer, "term term^3.0 term"); + assertQueryEquals("term stop^3.0 term", qpAnalyzer, "term term"); + assertQueryEquals("term term term", qpAnalyzer, "term term term"); assertQueryEquals("term +stop term", qpAnalyzer, "term term"); assertQueryEquals("term -stop term", qpAnalyzer, "term term"); + + assertQueryEquals("drop AND (stop) AND roll", qpAnalyzer, "+drop +roll"); + assertQueryEquals("term +(stop) term", qpAnalyzer, "term term"); + assertQueryEquals("term -(stop) term", qpAnalyzer, "term term"); + assertQueryEquals("drop AND stop AND roll", qpAnalyzer, "+drop +roll"); assertQueryEquals("term phrase term", qpAnalyzer, "term \"phrase1 phrase2\" term"); assertQueryEquals("term AND NOT phrase term", qpAnalyzer, "+term -\"phrase1 phrase2\" term"); + assertQueryEquals("stop^3", qpAnalyzer, ""); assertQueryEquals("stop", qpAnalyzer, ""); + assertQueryEquals("(stop)^3", qpAnalyzer, ""); + assertQueryEquals("(stop^3)", qpAnalyzer, ""); + assertQueryEquals("(stop)", qpAnalyzer, ""); assertTrue(getQuery("term term term", qpAnalyzer) instanceof BooleanQuery); assertTrue(getQuery("term +stop", qpAnalyzer) instanceof TermQuery); } Index: src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java =================================================================== --- src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java (revision 548835) +++ src/java/org/apache/lucene/queryParser/MultiFieldQueryParser.java (working copy) @@ -208,7 +208,10 @@ { QueryParser qp = new QueryParser(fields[i], analyzer); Query q = qp.parse(queries[i]); - bQuery.add(q, BooleanClause.Occur.SHOULD); + if (q!=null && + (!(q instanceof BooleanQuery) || ((BooleanQuery)q).getClauses().length>0)) { + bQuery.add(q, BooleanClause.Occur.SHOULD); + } } return bQuery; } @@ -251,7 +254,10 @@ for (int i = 0; i < fields.length; i++) { QueryParser qp = new QueryParser(fields[i], analyzer); Query q = qp.parse(query); - bQuery.add(q, flags[i]); + if (q!=null && + (!(q instanceof BooleanQuery) || ((BooleanQuery)q).getClauses().length>0)) { + bQuery.add(q, flags[i]); + } } return bQuery; } @@ -297,7 +303,10 @@ { QueryParser qp = new QueryParser(fields[i], analyzer); Query q = qp.parse(queries[i]); - bQuery.add(q, flags[i]); + if (q!=null && + (!(q instanceof BooleanQuery) || ((BooleanQuery)q).getClauses().length>0)) { + bQuery.add(q, flags[i]); + } } return bQuery; } Index: src/java/org/apache/lucene/queryParser/QueryParser.java =================================================================== --- src/java/org/apache/lucene/queryParser/QueryParser.java (revision 548835) +++ src/java/org/apache/lucene/queryParser/QueryParser.java (working copy) @@ -143,7 +143,8 @@ ReInit(new FastCharStream(new StringReader(query))); try { // TopLevelQuery is a Query followed by the end-of-input (EOF) - return TopLevelQuery(field); + Query res = TopLevelQuery(field); + return res!=null ? res : new BooleanQuery(); } catch (ParseException tme) { // rethrow to include the original query: @@ -614,9 +615,12 @@ protected Query getBooleanQuery(Vector clauses, boolean disableCoord) throws ParseException { + if (clauses.size()==0) { + return null; // all clause words were filtered away by the analyzer. + } BooleanQuery query = new BooleanQuery(disableCoord); for (int i = 0; i < clauses.size(); i++) { - query.add((BooleanClause)clauses.elementAt(i)); + query.add((BooleanClause)clauses.elementAt(i)); } return query; } @@ -1258,16 +1262,6 @@ finally { jj_save(0, xla); } } - final private boolean jj_3_1() { - Token xsp; - xsp = jj_scanpos; - if (jj_3R_2()) { - jj_scanpos = xsp; - if (jj_3R_3()) return true; - } - return false; - } - final private boolean jj_3R_3() { if (jj_scan_token(STAR)) return true; if (jj_scan_token(COLON)) return true; @@ -1280,6 +1274,16 @@ return false; } + final private boolean jj_3_1() { + Token xsp; + xsp = jj_scanpos; + if (jj_3R_2()) { + jj_scanpos = xsp; + if (jj_3R_3()) return true; + } + return false; + } + public QueryParserTokenManager token_source; public Token token, jj_nt; private int jj_ntk; Index: src/java/org/apache/lucene/queryParser/QueryParser.jj =================================================================== --- src/java/org/apache/lucene/queryParser/QueryParser.jj (revision 548835) +++ src/java/org/apache/lucene/queryParser/QueryParser.jj (working copy) @@ -167,7 +167,8 @@ ReInit(new FastCharStream(new StringReader(query))); try { // TopLevelQuery is a Query followed by the end-of-input (EOF) - return TopLevelQuery(field); + Query res = TopLevelQuery(field); + return res!=null ? res : new BooleanQuery(); } catch (ParseException tme) { // rethrow to include the original query: @@ -638,9 +639,12 @@ protected Query getBooleanQuery(Vector clauses, boolean disableCoord) throws ParseException { + if (clauses.size()==0) { + return null; // all clause words were filtered away by the analyzer. + } BooleanQuery query = new BooleanQuery(disableCoord); for (int i = 0; i < clauses.size(); i++) { - query.add((BooleanClause)clauses.elementAt(i)); + query.add((BooleanClause)clauses.elementAt(i)); } return query; }