LUCENE-10407: Set bpos flag to true when containing filter is exhausted (#648)

ContainedByIntervalIterator and OverlappingIntervalIterator set their 'is the filter
interval exhausted' flag to `false` once it has returned NO_MORE_POSITIONS on
a document, so that subsequent calls to `startPosition()` will also return
NO_MORE_POSITIONS. ContainingIntervalIterator omits to do this, and so it can
incorrectly report matches, for example when used in a disjunction.  This commit
fixes that omission.
This commit is contained in:
Alan Woodward 2022-02-04 16:44:57 +00:00 committed by GitHub
parent 9ebee5a058
commit 6b64f4b556
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 5 deletions

View File

@ -223,6 +223,9 @@ Bug Fixes
* LUCENE-10402: Prefix intervals should declare their automaton as binary, otherwise prefixes * LUCENE-10402: Prefix intervals should declare their automaton as binary, otherwise prefixes
containing multibyte characters will not correctly match. (Alan Woodward) containing multibyte characters will not correctly match. (Alan Woodward)
* LUCENE-10407: Containing intervals could sometimes yield incorrect matches when wrapped
in a disjunction. (Alan Woodward, Dawid Weiss)
Other Other
--------------------- ---------------------

View File

@ -51,8 +51,10 @@ class ContainingIntervalsSource extends ConjunctionIntervalsSource {
} }
while (a.nextInterval() != IntervalIterator.NO_MORE_INTERVALS) { while (a.nextInterval() != IntervalIterator.NO_MORE_INTERVALS) {
while (b.start() < a.start() && b.end() < a.end()) { while (b.start() < a.start() && b.end() < a.end()) {
if (b.nextInterval() == IntervalIterator.NO_MORE_INTERVALS) if (b.nextInterval() == IntervalIterator.NO_MORE_INTERVALS) {
bpos = false;
return IntervalIterator.NO_MORE_INTERVALS; return IntervalIterator.NO_MORE_INTERVALS;
}
} }
if (a.start() <= b.start() && a.end() >= b.end()) { if (a.start() <= b.start() && a.end() >= b.end()) {
return a.start(); return a.start();

View File

@ -17,6 +17,11 @@
package org.apache.lucene.queries.intervals; package org.apache.lucene.queries.intervals;
import static org.apache.lucene.queries.intervals.Intervals.containing;
import static org.apache.lucene.queries.intervals.Intervals.extend;
import static org.apache.lucene.queries.intervals.Intervals.or;
import static org.apache.lucene.queries.intervals.Intervals.term;
import java.io.IOException; import java.io.IOException;
import org.apache.lucene.document.Document; import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field; import org.apache.lucene.document.Field;
@ -50,9 +55,9 @@ public class TestIntervalQuery extends LuceneTestCase {
random(), random(),
directory, directory,
newIndexWriterConfig(new MockAnalyzer(random())).setMergePolicy(newLogMergePolicy())); newIndexWriterConfig(new MockAnalyzer(random())).setMergePolicy(newLogMergePolicy()));
for (int i = 0; i < docFields.length; i++) { for (String docField : docFields) {
Document doc = new Document(); Document doc = new Document();
doc.add(newTextField(field, docFields[i], Field.Store.YES)); doc.add(newTextField(field, docField, Field.Store.YES));
writer.addDocument(doc); writer.addDocument(doc);
} }
reader = writer.getReader(); reader = writer.getReader();
@ -67,7 +72,7 @@ public class TestIntervalQuery extends LuceneTestCase {
super.tearDown(); super.tearDown();
} }
private String[] docFields = { private final String[] docFields = {
"w1 w2 w3 w4 w5", "w1 w2 w3 w4 w5",
"w1 w3 w2 w3", "w1 w3 w2 w3",
"w1 xx w2 w4 yy w3", "w1 xx w2 w4 yy w3",
@ -168,7 +173,7 @@ public class TestIntervalQuery extends LuceneTestCase {
assertTrue(explain.toString().contains(field)); assertTrue(explain.toString().contains(field));
} }
public void testNullConstructorArgs() throws IOException { public void testNullConstructorArgs() {
expectThrows(NullPointerException.class, () -> new IntervalQuery(null, Intervals.term("z"))); expectThrows(NullPointerException.class, () -> new IntervalQuery(null, Intervals.term("z")));
expectThrows(NullPointerException.class, () -> new IntervalQuery("field", null)); expectThrows(NullPointerException.class, () -> new IntervalQuery("field", null));
} }
@ -423,4 +428,11 @@ public class TestIntervalQuery extends LuceneTestCase {
Query q = new IntervalQuery(field, Intervals.prefix(new BytesRef(""))); Query q = new IntervalQuery(field, Intervals.prefix(new BytesRef("")));
checkHits(q, new int[] {11}); checkHits(q, new int[] {11});
} }
public void testExtendDisjunctions() throws IOException {
Query q =
new IntervalQuery(
field, or(term("XXX"), containing(extend(term("message"), 0, 10), term("intend"))));
checkHits(q, new int[] {});
}
} }