mirror of https://github.com/apache/lucene.git
LUCENE-7755: Join queries should not reference IndexReaders.
This commit is contained in:
parent
edcdc3052b
commit
edafcbad14
|
@ -93,6 +93,13 @@ Other
|
||||||
* LUCENE-7743: Never call new String(String).
|
* LUCENE-7743: Never call new String(String).
|
||||||
(Daniel Jelinski via Adrien Grand)
|
(Daniel Jelinski via Adrien Grand)
|
||||||
|
|
||||||
|
======================= Lucene 6.5.1 =======================
|
||||||
|
|
||||||
|
Bug Fixes
|
||||||
|
|
||||||
|
* LUCENE-7755: Fixed join queries to not reference IndexReaders, as it could
|
||||||
|
cause leaks if they are cached. (Adrien Grand)
|
||||||
|
|
||||||
======================= Lucene 6.5.0 =======================
|
======================= Lucene 6.5.0 =======================
|
||||||
|
|
||||||
API Changes
|
API Changes
|
||||||
|
|
|
@ -47,6 +47,14 @@ public abstract class IndexReaderContext {
|
||||||
this.isTopLevel = parent==null;
|
this.isTopLevel = parent==null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Expert: Return an {@link Object} that uniquely identifies this context.
|
||||||
|
* The returned object does neither reference this {@link IndexReaderContext}
|
||||||
|
* nor the wrapped {@link IndexReader}.
|
||||||
|
* @lucene.experimental */
|
||||||
|
public Object id() {
|
||||||
|
return identity;
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the {@link IndexReader}, this context represents. */
|
/** Returns the {@link IndexReader}, this context represents. */
|
||||||
public abstract IndexReader reader();
|
public abstract IndexReader reader();
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.DocValues;
|
import org.apache.lucene.index.DocValues;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReaderContext;
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.MultiDocValues;
|
import org.apache.lucene.index.MultiDocValues;
|
||||||
import org.apache.lucene.index.SortedDocValues;
|
import org.apache.lucene.index.SortedDocValues;
|
||||||
|
@ -48,19 +48,23 @@ final class GlobalOrdinalsQuery extends Query {
|
||||||
|
|
||||||
// just for hashcode and equals:
|
// just for hashcode and equals:
|
||||||
private final Query fromQuery;
|
private final Query fromQuery;
|
||||||
private final IndexReader indexReader;
|
// id of the context rather than the context itself in order not to hold references to index readers
|
||||||
|
private final Object indexReaderContextId;
|
||||||
|
|
||||||
GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReader indexReader) {
|
GlobalOrdinalsQuery(LongBitSet foundOrds, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, IndexReaderContext context) {
|
||||||
this.foundOrds = foundOrds;
|
this.foundOrds = foundOrds;
|
||||||
this.joinField = joinField;
|
this.joinField = joinField;
|
||||||
this.globalOrds = globalOrds;
|
this.globalOrds = globalOrds;
|
||||||
this.toQuery = toQuery;
|
this.toQuery = toQuery;
|
||||||
this.fromQuery = fromQuery;
|
this.fromQuery = fromQuery;
|
||||||
this.indexReader = indexReader;
|
this.indexReaderContextId = context.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
|
public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
|
||||||
|
if (searcher.getTopReaderContext().id() != indexReaderContextId) {
|
||||||
|
throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
|
||||||
|
}
|
||||||
return new W(this, toQuery.createWeight(searcher, false, 1f), boost);
|
return new W(this, toQuery.createWeight(searcher, false, 1f), boost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,7 +78,7 @@ final class GlobalOrdinalsQuery extends Query {
|
||||||
return fromQuery.equals(other.fromQuery) &&
|
return fromQuery.equals(other.fromQuery) &&
|
||||||
joinField.equals(other.joinField) &&
|
joinField.equals(other.joinField) &&
|
||||||
toQuery.equals(other.toQuery) &&
|
toQuery.equals(other.toQuery) &&
|
||||||
indexReader.equals(other.indexReader);
|
indexReaderContextId.equals(other.indexReaderContextId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -83,7 +87,7 @@ final class GlobalOrdinalsQuery extends Query {
|
||||||
result = 31 * result + joinField.hashCode();
|
result = 31 * result + joinField.hashCode();
|
||||||
result = 31 * result + toQuery.hashCode();
|
result = 31 * result + toQuery.hashCode();
|
||||||
result = 31 * result + fromQuery.hashCode();
|
result = 31 * result + fromQuery.hashCode();
|
||||||
result = 31 * result + indexReader.hashCode();
|
result = 31 * result + indexReaderContextId.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import java.io.IOException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.index.DocValues;
|
import org.apache.lucene.index.DocValues;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReaderContext;
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.MultiDocValues;
|
import org.apache.lucene.index.MultiDocValues;
|
||||||
import org.apache.lucene.index.SortedDocValues;
|
import org.apache.lucene.index.SortedDocValues;
|
||||||
|
@ -48,9 +48,10 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
|
||||||
private final Query fromQuery;
|
private final Query fromQuery;
|
||||||
private final int min;
|
private final int min;
|
||||||
private final int max;
|
private final int max;
|
||||||
private final IndexReader indexReader;
|
// id of the context rather than the context itself in order not to hold references to index readers
|
||||||
|
private final Object indexReaderContextId;
|
||||||
|
|
||||||
GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReader indexReader) {
|
GlobalOrdinalsWithScoreQuery(GlobalOrdinalsWithScoreCollector collector, String joinField, MultiDocValues.OrdinalMap globalOrds, Query toQuery, Query fromQuery, int min, int max, IndexReaderContext context) {
|
||||||
this.collector = collector;
|
this.collector = collector;
|
||||||
this.joinField = joinField;
|
this.joinField = joinField;
|
||||||
this.globalOrds = globalOrds;
|
this.globalOrds = globalOrds;
|
||||||
|
@ -58,11 +59,14 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
|
||||||
this.fromQuery = fromQuery;
|
this.fromQuery = fromQuery;
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
this.indexReader = indexReader;
|
this.indexReaderContextId = context.id();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
|
public Weight createWeight(IndexSearcher searcher, boolean needsScores, float boost) throws IOException {
|
||||||
|
if (searcher.getTopReaderContext().id() != indexReaderContextId) {
|
||||||
|
throw new IllegalStateException("Creating the weight against a different index reader than this query has been built for.");
|
||||||
|
}
|
||||||
return new W(this, toQuery.createWeight(searcher, false, 1f));
|
return new W(this, toQuery.createWeight(searcher, false, 1f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +82,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
|
||||||
joinField.equals(other.joinField) &&
|
joinField.equals(other.joinField) &&
|
||||||
fromQuery.equals(other.fromQuery) &&
|
fromQuery.equals(other.fromQuery) &&
|
||||||
toQuery.equals(other.toQuery) &&
|
toQuery.equals(other.toQuery) &&
|
||||||
indexReader.equals(other.indexReader);
|
indexReaderContextId.equals(other.indexReaderContextId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,7 +93,7 @@ final class GlobalOrdinalsWithScoreQuery extends Query {
|
||||||
result = 31 * result + fromQuery.hashCode();
|
result = 31 * result + fromQuery.hashCode();
|
||||||
result = 31 * result + min;
|
result = 31 * result + min;
|
||||||
result = 31 * result + max;
|
result = 31 * result + max;
|
||||||
result = 31 * result + indexReader.hashCode();
|
result = 31 * result + indexReaderContextId.hashCode();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,6 @@ import org.apache.lucene.document.LongPoint;
|
||||||
import org.apache.lucene.index.BinaryDocValues;
|
import org.apache.lucene.index.BinaryDocValues;
|
||||||
import org.apache.lucene.index.DocValues;
|
import org.apache.lucene.index.DocValues;
|
||||||
import org.apache.lucene.index.DocValuesType;
|
import org.apache.lucene.index.DocValuesType;
|
||||||
import org.apache.lucene.index.IndexReader;
|
|
||||||
import org.apache.lucene.index.LeafReader;
|
import org.apache.lucene.index.LeafReader;
|
||||||
import org.apache.lucene.index.LeafReaderContext;
|
import org.apache.lucene.index.LeafReaderContext;
|
||||||
import org.apache.lucene.index.MultiDocValues;
|
import org.apache.lucene.index.MultiDocValues;
|
||||||
|
@ -467,8 +466,7 @@ public final class JoinUtil {
|
||||||
MultiDocValues.OrdinalMap ordinalMap,
|
MultiDocValues.OrdinalMap ordinalMap,
|
||||||
int min,
|
int min,
|
||||||
int max) throws IOException {
|
int max) throws IOException {
|
||||||
IndexReader indexReader = searcher.getIndexReader();
|
int numSegments = searcher.getIndexReader().leaves().size();
|
||||||
int numSegments = indexReader.leaves().size();
|
|
||||||
final long valueCount;
|
final long valueCount;
|
||||||
if (numSegments == 0) {
|
if (numSegments == 0) {
|
||||||
return new MatchNoDocsQuery("JoinUtil.createJoinQuery with no segments");
|
return new MatchNoDocsQuery("JoinUtil.createJoinQuery with no segments");
|
||||||
|
@ -509,7 +507,7 @@ public final class JoinUtil {
|
||||||
if (min <= 0 && max == Integer.MAX_VALUE) {
|
if (min <= 0 && max == Integer.MAX_VALUE) {
|
||||||
GlobalOrdinalsCollector globalOrdinalsCollector = new GlobalOrdinalsCollector(joinField, ordinalMap, valueCount);
|
GlobalOrdinalsCollector globalOrdinalsCollector = new GlobalOrdinalsCollector(joinField, ordinalMap, valueCount);
|
||||||
searcher.search(rewrittenFromQuery, globalOrdinalsCollector);
|
searcher.search(rewrittenFromQuery, globalOrdinalsCollector);
|
||||||
return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, indexReader);
|
return new GlobalOrdinalsQuery(globalOrdinalsCollector.getCollectorOrdinals(), joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, searcher.getTopReaderContext());
|
||||||
} else {
|
} else {
|
||||||
globalOrdinalsWithScoreCollector = new GlobalOrdinalsWithScoreCollector.NoScore(joinField, ordinalMap, valueCount, min, max);
|
globalOrdinalsWithScoreCollector = new GlobalOrdinalsWithScoreCollector.NoScore(joinField, ordinalMap, valueCount, min, max);
|
||||||
break;
|
break;
|
||||||
|
@ -518,7 +516,7 @@ public final class JoinUtil {
|
||||||
throw new IllegalArgumentException(String.format(Locale.ROOT, "Score mode %s isn't supported.", scoreMode));
|
throw new IllegalArgumentException(String.format(Locale.ROOT, "Score mode %s isn't supported.", scoreMode));
|
||||||
}
|
}
|
||||||
searcher.search(rewrittenFromQuery, globalOrdinalsWithScoreCollector);
|
searcher.search(rewrittenFromQuery, globalOrdinalsWithScoreCollector);
|
||||||
return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, indexReader);
|
return new GlobalOrdinalsWithScoreQuery(globalOrdinalsWithScoreCollector, joinField, ordinalMap, rewrittenToQuery, rewrittenFromQuery, min, max, searcher.getTopReaderContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue