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
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
---------------------

View File

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

View File

@ -17,6 +17,11 @@
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 org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
@ -50,9 +55,9 @@ public class TestIntervalQuery extends LuceneTestCase {
random(),
directory,
newIndexWriterConfig(new MockAnalyzer(random())).setMergePolicy(newLogMergePolicy()));
for (int i = 0; i < docFields.length; i++) {
for (String docField : docFields) {
Document doc = new Document();
doc.add(newTextField(field, docFields[i], Field.Store.YES));
doc.add(newTextField(field, docField, Field.Store.YES));
writer.addDocument(doc);
}
reader = writer.getReader();
@ -67,7 +72,7 @@ public class TestIntervalQuery extends LuceneTestCase {
super.tearDown();
}
private String[] docFields = {
private final String[] docFields = {
"w1 w2 w3 w4 w5",
"w1 w3 w2 w3",
"w1 xx w2 w4 yy w3",
@ -168,7 +173,7 @@ public class TestIntervalQuery extends LuceneTestCase {
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("field", null));
}
@ -423,4 +428,11 @@ public class TestIntervalQuery extends LuceneTestCase {
Query q = new IntervalQuery(field, Intervals.prefix(new BytesRef("")));
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[] {});
}
}