|
19 | 19 |
|
20 | 20 | package org.elasticsearch.index.query; |
21 | 21 |
|
| 22 | +import org.apache.lucene.analysis.Analyzer; |
| 23 | +import org.apache.lucene.analysis.CannedBinaryTokenStream; |
| 24 | +import org.apache.lucene.analysis.MockTokenizer; |
| 25 | +import org.apache.lucene.analysis.TokenStream; |
| 26 | +import org.apache.lucene.analysis.Tokenizer; |
22 | 27 | import org.apache.lucene.index.Term; |
23 | 28 | import org.apache.lucene.queries.ExtendedCommonTermsQuery; |
24 | 29 | import org.apache.lucene.search.BooleanClause; |
|
31 | 36 | import org.apache.lucene.search.Query; |
32 | 37 | import org.apache.lucene.search.TermQuery; |
33 | 38 | import org.elasticsearch.Version; |
| 39 | +import org.apache.lucene.util.BytesRef; |
34 | 40 | import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest; |
35 | 41 | import org.elasticsearch.common.ParsingException; |
36 | 42 | import org.elasticsearch.common.Strings; |
|
40 | 46 | import org.elasticsearch.index.mapper.MappedFieldType; |
41 | 47 | import org.elasticsearch.index.mapper.MapperService; |
42 | 48 | import org.elasticsearch.index.search.MatchQuery; |
| 49 | +import org.elasticsearch.index.search.MatchQuery.Type; |
43 | 50 | import org.elasticsearch.index.search.MatchQuery.ZeroTermsQuery; |
44 | 51 | import org.elasticsearch.search.internal.SearchContext; |
45 | 52 | import org.elasticsearch.test.AbstractQueryTestCase; |
46 | 53 | import org.hamcrest.Matcher; |
47 | 54 |
|
48 | 55 | import java.io.IOException; |
| 56 | +import java.io.Reader; |
| 57 | +import java.util.ArrayList; |
49 | 58 | import java.util.HashMap; |
50 | 59 | import java.util.List; |
51 | 60 | import java.util.Locale; |
@@ -403,4 +412,73 @@ public void testLenientPhraseQuery() throws Exception { |
403 | 412 | assertThat(query.toString(), |
404 | 413 | containsString("field:[string_no_pos] was indexed without position data; cannot run PhraseQuery")); |
405 | 414 | } |
| 415 | + |
| 416 | + public void testMaxBooleanClause() { |
| 417 | + assumeTrue("test runs only when at least a type is registered", getCurrentTypes().length > 0); |
| 418 | + MatchQuery query = new MatchQuery(createShardContext()); |
| 419 | + query.setAnalyzer(new MockGraphAnalyzer(createGiantGraph(40))); |
| 420 | + expectThrows(BooleanQuery.TooManyClauses.class, () -> query.parse(Type.PHRASE, STRING_FIELD_NAME, "")); |
| 421 | + query.setAnalyzer(new MockGraphAnalyzer(createGiantGraphMultiTerms())); |
| 422 | + expectThrows(BooleanQuery.TooManyClauses.class, () -> query.parse(Type.PHRASE, STRING_FIELD_NAME, "")); |
| 423 | + } |
| 424 | + |
| 425 | + private static class MockGraphAnalyzer extends Analyzer { |
| 426 | + final CannedBinaryTokenStream.BinaryToken[] tokens; |
| 427 | + |
| 428 | + private MockGraphAnalyzer(CannedBinaryTokenStream.BinaryToken[] tokens ) { |
| 429 | + this.tokens = tokens; |
| 430 | + } |
| 431 | + @Override |
| 432 | + protected TokenStreamComponents createComponents(String fieldName) { |
| 433 | + Tokenizer tokenizer = new MockTokenizer(MockTokenizer.SIMPLE, true); |
| 434 | + return new TokenStreamComponents(tokenizer) { |
| 435 | + @Override |
| 436 | + public TokenStream getTokenStream() { |
| 437 | + return new CannedBinaryTokenStream(tokens); |
| 438 | + } |
| 439 | + |
| 440 | + @Override |
| 441 | + protected void setReader(final Reader reader) { |
| 442 | + } |
| 443 | + }; |
| 444 | + } |
| 445 | + } |
| 446 | + |
| 447 | + /** |
| 448 | + * Creates a graph token stream with 2 side paths at each position. |
| 449 | + **/ |
| 450 | + private static CannedBinaryTokenStream.BinaryToken[] createGiantGraph(int numPos) { |
| 451 | + List<CannedBinaryTokenStream.BinaryToken> tokens = new ArrayList<>(); |
| 452 | + BytesRef term1 = new BytesRef("foo"); |
| 453 | + BytesRef term2 = new BytesRef("bar"); |
| 454 | + for (int i = 0; i < numPos;) { |
| 455 | + if (i % 2 == 0) { |
| 456 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term2, 1, 1)); |
| 457 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term1, 0, 2)); |
| 458 | + i += 2; |
| 459 | + } else { |
| 460 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term2, 1, 1)); |
| 461 | + i++; |
| 462 | + } |
| 463 | + } |
| 464 | + return tokens.toArray(new CannedBinaryTokenStream.BinaryToken[0]); |
| 465 | + } |
| 466 | + |
| 467 | + /** |
| 468 | + * Creates a graph token stream with {@link BooleanQuery#getMaxClauseCount()} |
| 469 | + * expansions at the last position. |
| 470 | + **/ |
| 471 | + private static CannedBinaryTokenStream.BinaryToken[] createGiantGraphMultiTerms() { |
| 472 | + List<CannedBinaryTokenStream.BinaryToken> tokens = new ArrayList<>(); |
| 473 | + BytesRef term1 = new BytesRef("foo"); |
| 474 | + BytesRef term2 = new BytesRef("bar"); |
| 475 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term2, 1, 1)); |
| 476 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term1, 0, 2)); |
| 477 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term2, 1, 1)); |
| 478 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term2, 1, 1)); |
| 479 | + for (int i = 0; i < BooleanQuery.getMaxClauseCount(); i++) { |
| 480 | + tokens.add(new CannedBinaryTokenStream.BinaryToken(term1, 0, 1)); |
| 481 | + } |
| 482 | + return tokens.toArray(new CannedBinaryTokenStream.BinaryToken[0]); |
| 483 | + } |
406 | 484 | } |
0 commit comments