LUCENE-5450: fix getField() NPE issues with span queries that have empty clauses

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1569503 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Robert Muir 2014-02-18 19:41:06 +00:00
parent e04cf308ea
commit 2991d657e4
6 changed files with 148 additions and 6 deletions

View File

@ -65,6 +65,14 @@ Optimizations
on Windows if NIOFSDirectory is used, mmapped files are still locked.
(Michael Poindexter, Robert Muir, Uwe Schindler)
======================= Lucene 4.8.0 =======================
Bug fixes
* LUCENE-5450: Fix getField() NPE issues with SpanOr/SpanNear when they have an
empty list of clauses. This can happen for example, when a wildcard matches
no terms. (Tim Allison via Robert Muir)
======================= Lucene 4.7.0 =======================
New Features

View File

@ -64,9 +64,9 @@ public class SpanNearQuery extends SpanQuery implements Cloneable {
this.clauses = new ArrayList<SpanQuery>(clauses.length);
for (int i = 0; i < clauses.length; i++) {
SpanQuery clause = clauses[i];
if (i == 0) { // check field
if (field == null) { // check field
field = clause.getField();
} else if (!clause.getField().equals(field)) {
} else if (clause.getField() != null && !clause.getField().equals(field)) {
throw new IllegalArgumentException("Clauses must have same field.");
}
this.clauses.add(clause);

View File

@ -62,7 +62,7 @@ public class SpanNotQuery extends SpanQuery implements Cloneable {
this.pre = (pre >=0) ? pre : 0;
this.post = (post >= 0) ? post : 0;
if (!include.getField().equals(exclude.getField()))
if (include.getField() != null && exclude.getField() != null && !include.getField().equals(exclude.getField()))
throw new IllegalArgumentException("Clauses must have same field.");
}

View File

@ -54,7 +54,7 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
public final void addClause(SpanQuery clause) {
if (field == null) {
field = clause.getField();
} else if (!clause.getField().equals(field)) {
} else if (clause.getField() != null && !clause.getField().equals(field)) {
throw new IllegalArgumentException("Clauses must have same field.");
}
this.clauses.add(clause);
@ -132,7 +132,6 @@ public class SpanOrQuery extends SpanQuery implements Cloneable {
final SpanOrQuery that = (SpanOrQuery) o;
if (!clauses.equals(that.clauses)) return false;
if (!clauses.isEmpty() && !field.equals(that.field)) return false;
return getBoost() == that.getBoost();
}

View File

@ -34,7 +34,11 @@ public abstract class SpanQuery extends Query {
* to search for spans. */
public abstract Spans getSpans(AtomicReaderContext context, Bits acceptDocs, Map<Term,TermContext> termContexts) throws IOException;
/** Returns the name of the field matched by this query.*/
/**
* Returns the name of the field matched by this query.
* <p>
* Note that this may return null if the query matches no terms.
*/
public abstract String getField();
@Override

View File

@ -24,6 +24,8 @@ import org.apache.lucene.index.RandomIndexWriter;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.RegexpQuery;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase;
@ -95,4 +97,133 @@ public class TestSpanMultiTermQueryWrapper extends LuceneTestCase {
SpanPositionRangeQuery sprq = new SpanPositionRangeQuery(sfq, 0, 100);
assertEquals(1, searcher.search(sprq, 10).totalHits);
}
public void testNoSuchMultiTermsInNear() throws Exception {
//test to make sure non existent multiterms aren't throwing null pointer exceptions
FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<FuzzyQuery>(fuzzyNoSuch);
SpanQuery term = new SpanTermQuery(new Term("field", "brown"));
SpanQuery near = new SpanNearQuery(new SpanQuery[]{term, spanNoSuch}, 1, true);
assertEquals(0, searcher.search(near, 10).totalHits);
//flip order
near = new SpanNearQuery(new SpanQuery[]{spanNoSuch, term}, 1, true);
assertEquals(0, searcher.search(near, 10).totalHits);
WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<WildcardQuery>(wcNoSuch);
near = new SpanNearQuery(new SpanQuery[]{term, spanWCNoSuch}, 1, true);
assertEquals(0, searcher.search(near, 10).totalHits);
RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<RegexpQuery>(rgxNoSuch);
near = new SpanNearQuery(new SpanQuery[]{term, spanRgxNoSuch}, 1, true);
assertEquals(0, searcher.search(near, 10).totalHits);
PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<PrefixQuery>(prfxNoSuch);
near = new SpanNearQuery(new SpanQuery[]{term, spanPrfxNoSuch}, 1, true);
assertEquals(0, searcher.search(near, 10).totalHits);
//test single noSuch
near = new SpanNearQuery(new SpanQuery[]{spanPrfxNoSuch}, 1, true);
assertEquals(0, searcher.search(near, 10).totalHits);
//test double noSuch
near = new SpanNearQuery(new SpanQuery[]{spanPrfxNoSuch, spanPrfxNoSuch}, 1, true);
assertEquals(0, searcher.search(near, 10).totalHits);
}
public void testNoSuchMultiTermsInNotNear() throws Exception {
//test to make sure non existent multiterms aren't throwing non-matching field exceptions
FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<FuzzyQuery>(fuzzyNoSuch);
SpanQuery term = new SpanTermQuery(new Term("field", "brown"));
SpanNotQuery notNear = new SpanNotQuery(term, spanNoSuch, 0,0);
assertEquals(1, searcher.search(notNear, 10).totalHits);
//flip
notNear = new SpanNotQuery(spanNoSuch, term, 0,0);
assertEquals(0, searcher.search(notNear, 10).totalHits);
//both noSuch
notNear = new SpanNotQuery(spanNoSuch, spanNoSuch, 0,0);
assertEquals(0, searcher.search(notNear, 10).totalHits);
WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<WildcardQuery>(wcNoSuch);
notNear = new SpanNotQuery(term, spanWCNoSuch, 0,0);
assertEquals(1, searcher.search(notNear, 10).totalHits);
RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<RegexpQuery>(rgxNoSuch);
notNear = new SpanNotQuery(term, spanRgxNoSuch, 1, 1);
assertEquals(1, searcher.search(notNear, 10).totalHits);
PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<PrefixQuery>(prfxNoSuch);
notNear = new SpanNotQuery(term, spanPrfxNoSuch, 1, 1);
assertEquals(1, searcher.search(notNear, 10).totalHits);
}
public void testNoSuchMultiTermsInOr() throws Exception {
//test to make sure non existent multiterms aren't throwing null pointer exceptions
FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<FuzzyQuery>(fuzzyNoSuch);
SpanQuery term = new SpanTermQuery(new Term("field", "brown"));
SpanOrQuery near = new SpanOrQuery(new SpanQuery[]{term, spanNoSuch});
assertEquals(1, searcher.search(near, 10).totalHits);
//flip
near = new SpanOrQuery(new SpanQuery[]{spanNoSuch, term});
assertEquals(1, searcher.search(near, 10).totalHits);
WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<WildcardQuery>(wcNoSuch);
near = new SpanOrQuery(new SpanQuery[]{term, spanWCNoSuch});
assertEquals(1, searcher.search(near, 10).totalHits);
RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<RegexpQuery>(rgxNoSuch);
near = new SpanOrQuery(new SpanQuery[]{term, spanRgxNoSuch});
assertEquals(1, searcher.search(near, 10).totalHits);
PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<PrefixQuery>(prfxNoSuch);
near = new SpanOrQuery(new SpanQuery[]{term, spanPrfxNoSuch});
assertEquals(1, searcher.search(near, 10).totalHits);
near = new SpanOrQuery(new SpanQuery[]{spanPrfxNoSuch});
assertEquals(0, searcher.search(near, 10).totalHits);
near = new SpanOrQuery(new SpanQuery[]{spanPrfxNoSuch, spanPrfxNoSuch});
assertEquals(0, searcher.search(near, 10).totalHits);
}
public void testNoSuchMultiTermsInSpanFirst() throws Exception {
//this hasn't been a problem
FuzzyQuery fuzzyNoSuch = new FuzzyQuery(new Term("field", "noSuch"), 1, 0, 1, false);
SpanQuery spanNoSuch = new SpanMultiTermQueryWrapper<FuzzyQuery>(fuzzyNoSuch);
SpanQuery spanFirst = new SpanFirstQuery(spanNoSuch, 10);
assertEquals(0, searcher.search(spanFirst, 10).totalHits);
WildcardQuery wcNoSuch = new WildcardQuery(new Term("field", "noSuch*"));
SpanQuery spanWCNoSuch = new SpanMultiTermQueryWrapper<WildcardQuery>(wcNoSuch);
spanFirst = new SpanFirstQuery(spanWCNoSuch, 10);
assertEquals(0, searcher.search(spanFirst, 10).totalHits);
RegexpQuery rgxNoSuch = new RegexpQuery(new Term("field", "noSuch"));
SpanQuery spanRgxNoSuch = new SpanMultiTermQueryWrapper<RegexpQuery>(rgxNoSuch);
spanFirst = new SpanFirstQuery(spanRgxNoSuch, 10);
assertEquals(0, searcher.search(spanFirst, 10).totalHits);
PrefixQuery prfxNoSuch = new PrefixQuery(new Term("field", "noSuch"));
SpanQuery spanPrfxNoSuch = new SpanMultiTermQueryWrapper<PrefixQuery>(prfxNoSuch);
spanFirst = new SpanFirstQuery(spanPrfxNoSuch, 10);
assertEquals(0, searcher.search(spanFirst, 10).totalHits);
}
}