Index: src/test/org/apache/lucene/search/TestBooleanQuery.java =================================================================== --- src/test/org/apache/lucene/search/TestBooleanQuery.java (revision 751897) +++ src/test/org/apache/lucene/search/TestBooleanQuery.java (working copy) @@ -50,5 +50,44 @@ // okay } } - + + public void testMaxClauseCounts() { + BooleanQuery.setMaxClauseCount(2); + BooleanQuery bq1 = new BooleanQuery(); + // existing queries do not have their clause + // count affected by calling the static method. + BooleanQuery.setMaxClauseCount(1); + BooleanQuery bq2 = new BooleanQuery(); + BooleanQuery bq3 = new BooleanQuery(); + bq3.setQueryClauseCount(2); + + bq1.add(new TermQuery(new Term("field", "value1")), BooleanClause.Occur.SHOULD); + bq1.add(new TermQuery(new Term("field", "value2")), BooleanClause.Occur.SHOULD); + try { + bq1.add(new TermQuery(new Term("field", "value3")), BooleanClause.Occur.SHOULD); + fail(); + } + catch (BooleanQuery.TooManyClauses e) { + // expected + } + + bq2.add(new TermQuery(new Term("field", "value1")), BooleanClause.Occur.SHOULD); + try { + bq2.add(new TermQuery(new Term("field", "value2")), BooleanClause.Occur.SHOULD); + fail(); + } + catch (BooleanQuery.TooManyClauses e) { + // expected + } + + bq3.add(new TermQuery(new Term("field", "value1")), BooleanClause.Occur.SHOULD); + bq3.add(new TermQuery(new Term("field", "value2")), BooleanClause.Occur.SHOULD); + try { + bq3.add(new TermQuery(new Term("field", "value3")), BooleanClause.Occur.SHOULD); + fail(); + } + catch (BooleanQuery.TooManyClauses e) { + // expected + } + } } Index: src/test/org/apache/lucene/search/TestPrefixQuery.java =================================================================== --- src/test/org/apache/lucene/search/TestPrefixQuery.java (revision 751897) +++ src/test/org/apache/lucene/search/TestPrefixQuery.java (working copy) @@ -17,33 +17,43 @@ * limitations under the License. */ -import org.apache.lucene.util.LuceneTestCase; -import org.apache.lucene.store.RAMDirectory; -import org.apache.lucene.index.IndexWriter; -import org.apache.lucene.index.Term; import org.apache.lucene.analysis.WhitespaceAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; +import org.apache.lucene.index.IndexWriter; +import org.apache.lucene.index.Term; +import org.apache.lucene.store.Directory; +import org.apache.lucene.store.RAMDirectory; +import org.apache.lucene.util.LuceneTestCase; +import java.io.IOException; + /** * Tests {@link PrefixQuery} class. * */ public class TestPrefixQuery extends LuceneTestCase { - public void testPrefixQuery() throws Exception { - RAMDirectory directory = new RAMDirectory(); + private Directory directory; - String[] categories = new String[] {"/Computers", - "/Computers/Mac", - "/Computers/Windows"}; + public void setUp() throws Exception + { + super.setUp(); + directory = new RAMDirectory(); + + String[] categories = new String[] { "/Computers", + "/Computers/Mac", + "/Computers/Windows" }; IndexWriter writer = new IndexWriter(directory, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); - for (int i = 0; i < categories.length; i++) { + for (int i = 0; i < categories.length; i++) + { Document doc = new Document(); doc.add(new Field("category", categories[i], Field.Store.YES, Field.Index.NOT_ANALYZED)); writer.addDocument(doc); } writer.close(); + } + public void testPrefixQuery() throws Exception { PrefixQuery query = new PrefixQuery(new Term("category", "/Computers")); IndexSearcher searcher = new IndexSearcher(directory); ScoreDoc[] hits = searcher.search(query, null, 1000).scoreDocs; @@ -53,4 +63,16 @@ hits = searcher.search(query, null, 1000).scoreDocs; assertEquals("One in /Computers/Mac", 1, hits.length); } + + public void testNonDefaultMaxClauseCount() throws Exception { + PrefixQuery query = new PrefixQuery(new Term("category", "/Computers")); + query.setMaxQueryClauseCount(1); + IndexSearcher searcher = new IndexSearcher(directory); + try { + ScoreDoc[] hits = searcher.search(query, null, 1000).scoreDocs; + fail(); + } catch (BooleanQuery.TooManyClauses e) { + // expected + } + } } Index: src/java/org/apache/lucene/search/MultiTermQuery.java =================================================================== --- src/java/org/apache/lucene/search/MultiTermQuery.java (revision 751897) +++ src/java/org/apache/lucene/search/MultiTermQuery.java (working copy) @@ -17,9 +17,6 @@ * limitations under the License. */ -import java.io.IOException; -import java.util.BitSet; - import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.index.TermDocs; @@ -27,6 +24,9 @@ import org.apache.lucene.util.OpenBitSet; import org.apache.lucene.util.ToStringUtils; +import java.io.IOException; +import java.util.BitSet; + /** * A {@link Query} that matches documents containing a subset of terms provided * by a {@link FilteredTermEnum} enumeration. @@ -45,6 +45,7 @@ public abstract class MultiTermQuery extends Query { protected Term term; protected boolean constantScoreRewrite = false; + private int maxQueryClauseCount = BooleanQuery.getMaxClauseCount(); /** Constructs a query for terms matching term. */ public MultiTermQuery(Term term) { @@ -71,10 +72,29 @@ return new MultiTermFilter(this); } + /** + * Get the maximum clause query count for this query. + * The default is BooleanQuery.getMaxClauseCount() unless + * changed + * @return maximum clause query count + * @see #setMaxQueryClauseCount(int) + */ + public int getMaxQueryClauseCount() { return maxQueryClauseCount; } + + /** + * Set a new maximum clause query count for this query. + * @param clauseCount new maximum clause query count while rewriting the query + * @see #rewrite + */ + public void setMaxQueryClauseCount(final int clauseCount) { + maxQueryClauseCount = clauseCount; + } + public Query rewrite(IndexReader reader) throws IOException { if (!constantScoreRewrite) { FilteredTermEnum enumerator = getEnum(reader); BooleanQuery query = new BooleanQuery(true); + query.setQueryClauseCount(maxQueryClauseCount); try { do { Term t = enumerator.term(); Index: src/java/org/apache/lucene/search/BooleanQuery.java =================================================================== --- src/java/org/apache/lucene/search/BooleanQuery.java (revision 751897) +++ src/java/org/apache/lucene/search/BooleanQuery.java (working copy) @@ -32,23 +32,27 @@ private static int maxClauseCount = 1024; + private int queryClauseCount = maxClauseCount; /** Thrown when an attempt is made to add more than {@link - * #getMaxClauseCount()} clauses. This typically happens if + * #getQueryClauseCount()} clauses. This typically happens if * a PrefixQuery, FuzzyQuery, WildcardQuery, or RangeQuery * is expanded to many terms during search. */ - public static class TooManyClauses extends RuntimeException { + public class TooManyClauses extends RuntimeException { public TooManyClauses() {} public String getMessage() { - return "maxClauseCount is set to " + maxClauseCount; + return "queryClauseCount is set to " + queryClauseCount; } } /** Return the maximum number of clauses permitted, 1024 by default. * Attempts to add more than the permitted number of clauses cause {@link - * TooManyClauses} to be thrown. + * TooManyClauses} to be thrown. This will be the default for all BooleanQuery + * objects created. * @see #setMaxClauseCount(int) + * @see #getQueryClauseCount + * @see #setQueryClauseCount(int) */ public static int getMaxClauseCount() { return maxClauseCount; } @@ -90,6 +94,21 @@ this.disableCoord = disableCoord; } + /** Get the maximum clause count for this BooleanQuery + * + * @return maximum clause count + */ + public int getQueryClauseCount() { return queryClauseCount; } + + /** Set the maximum clause count for this BooleanQuery. The + * default will be used if this is not called. + * @param clauseCount new maximum clause count + * @see #setMaxClauseCount(int) + */ + public void setQueryClauseCount(final int clauseCount) { + this.queryClauseCount = clauseCount; + } + /** Returns true iff {@link Similarity#coord(int,int)} is disabled in * scoring for this query instance. * @see #BooleanQuery(boolean) @@ -159,7 +178,7 @@ * @see #getMaxClauseCount() */ public void add(BooleanClause clause) { - if (clauses.size() >= maxClauseCount) + if (clauses.size() >= queryClauseCount) throw new TooManyClauses(); clauses.add(clause);