blob: 311bf0da70a200811241118d60fb10d04d6194f9 [file] [log] [blame]
Index: solr/core/src/java/org/apache/solr/search/join/BlockJoinChildQParser.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/join/BlockJoinChildQParser.java (revision 1713172)
+++ solr/core/src/java/org/apache/solr/search/join/BlockJoinChildQParser.java (working copy)
@@ -18,6 +18,7 @@
package org.apache.solr.search.join;
import org.apache.lucene.search.Query;
+import org.apache.lucene.search.join.BitSetProducer;
import org.apache.lucene.search.join.ToChildBlockJoinQuery;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
@@ -29,8 +30,8 @@
}
@Override
- protected Query createQuery(Query parentListQuery, Query query, String scoreMode) {
- return new ToChildBlockJoinQuery(query, getFilter(parentListQuery).filter);
+ protected Query createQuery(BitSetProducer parentFilter, Query query, String scoreMode) {
+ return new ToChildBlockJoinQuery(query, parentFilter);
}
@Override
Index: solr/core/src/java/org/apache/solr/search/join/BlockJoinParentQParser.java
===================================================================
--- solr/core/src/java/org/apache/solr/search/join/BlockJoinParentQParser.java (revision 1713172)
+++ solr/core/src/java/org/apache/solr/search/join/BlockJoinParentQParser.java (working copy)
@@ -18,11 +18,19 @@
package org.apache.solr.search.join;
import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+import org.apache.lucene.index.CheckIndex;
+import org.apache.lucene.index.DirectoryReader;
+import org.apache.lucene.index.IndexReaderContext;
+import org.apache.lucene.index.LeafReader;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DocIdSet;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.join.BitSetProducer;
+import org.apache.lucene.search.join.CheckJoinIndex;
import org.apache.lucene.search.join.QueryBitSetProducer;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.lucene.search.join.ToParentBlockJoinQuery;
@@ -29,6 +37,8 @@
import org.apache.lucene.util.BitDocIdSet;
import org.apache.lucene.util.BitSet;
import org.apache.lucene.util.Bits;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.params.SolrParams;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.BitsFilteredDocIdSet;
@@ -57,25 +67,35 @@
String scoreMode = localParams.get("score", ScoreMode.None.name());
QParser parentParser = subQuery(filter, null);
Query parentQ = parentParser.getQuery();
-
- String queryText = localParams.get(QueryParsing.V);
- // there is no child query, return parent filter from cache
- if (queryText == null || queryText.length()==0) {
- SolrConstantScoreQuery wrapped = new SolrConstantScoreQuery(getFilter(parentQ));
- wrapped.setCache(false);
- return wrapped;
+
+ try{
+ String queryText = localParams.get(QueryParsing.V);
+ // there is no child query, return parent filter from cache
+ if (queryText == null || queryText.length()==0) {
+ SolrConstantScoreQuery wrapped = new SolrConstantScoreQuery(getFilter(parentQ,false));
+ wrapped.setCache(false);
+ return wrapped;
+ }
+ QParser childrenParser = subQuery(queryText, null);
+ Query childrenQuery = childrenParser.getQuery();
+ // checking parent filter is necessary, but only for the first level of nesting
+ final BitDocIdSetFilterWrapper parentFilterWrapper = getFilter(parentQ, this.recurseCount==0);
+
+ return createQuery(parentFilterWrapper.filter , childrenQuery, scoreMode);
+ }catch(IOException ioe){ // very rare when checking searches for parent
+ throw new SolrException(ErrorCode.SERVER_ERROR, ioe);
}
- QParser childrenParser = subQuery(queryText, null);
- Query childrenQuery = childrenParser.getQuery();
- return createQuery(parentQ, childrenQuery, scoreMode);
+ catch(IllegalStateException ise){ // check index exceptions
+ throw new SolrException(ErrorCode.BAD_REQUEST, ise);
+ }
}
- protected Query createQuery(Query parentList, Query query, String scoreMode) throws SyntaxError {
- return new ToParentBlockJoinQuery(query, getFilter(parentList).filter,
+ protected Query createQuery(BitSetProducer parentFilter, Query query, String scoreMode) throws SyntaxError {
+ return new ToParentBlockJoinQuery(query, parentFilter,
ScoreModeParser.parse(scoreMode));
}
- BitDocIdSetFilterWrapper getFilter(Query parentList) {
+ BitDocIdSetFilterWrapper getFilter(Query parentList, boolean checkIndex) throws IOException {
SolrCache parentCache = req.getSearcher().getCache(CACHE_NAME);
// lazily retrieve from solr cache
Filter filter = null;
@@ -82,7 +102,7 @@
if (parentCache != null) {
filter = (Filter) parentCache.get(parentList);
}
- BitDocIdSetFilterWrapper result;
+ final BitDocIdSetFilterWrapper result;
if (filter instanceof BitDocIdSetFilterWrapper) {
result = (BitDocIdSetFilterWrapper) filter;
} else {
@@ -91,6 +111,10 @@
parentCache.put(parentList, result);
}
}
+ // only when necessary
+ if(checkIndex){
+ result.checkIndex(req.getSearcher().getIndexReader());
+ }
return result;
}
@@ -102,11 +126,19 @@
static class BitDocIdSetFilterWrapper extends Filter {
final BitSetProducer filter;
+ private final Map<Object,Boolean> checkedTopReaders = Collections.synchronizedMap(new WeakHashMap<>());
BitDocIdSetFilterWrapper(BitSetProducer filter) {
this.filter = filter;
}
+ public void checkIndex(DirectoryReader directoryReader) throws IOException {
+ if(checkedTopReaders.get(directoryReader)!=Boolean.TRUE){
+ CheckJoinIndex.check(directoryReader, filter);
+ checkedTopReaders.put(directoryReader,Boolean.TRUE);
+ }
+ }
+
@Override
public DocIdSet getDocIdSet(LeafReaderContext context, Bits acceptDocs) throws IOException {
BitSet set = filter.getBitSet(context);
Index: solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java
===================================================================
--- solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java (revision 1713172)
+++ solr/core/src/test/org/apache/solr/search/join/BJQParserTest.java (working copy)
@@ -17,10 +17,23 @@
package org.apache.solr.search.join;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.queryparser.xml.builders.RangeQueryBuilder;
+import org.apache.lucene.search.IndexSearcher;
+import org.apache.lucene.search.Sort;
+import org.apache.lucene.search.SortField;
+import org.apache.lucene.search.TermRangeQuery;
+import org.apache.lucene.search.TopFieldDocs;
+import org.apache.lucene.search.SortField.Type;
+import org.apache.lucene.search.join.CheckJoinIndex;
import org.apache.lucene.search.join.ScoreMode;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.common.params.MapSolrParams;
+import org.apache.solr.common.params.MultiMapSolrParams;
import org.apache.solr.common.util.NamedList;
+import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.search.SolrCache;
import org.apache.solr.util.BaseTestHarness;
import org.junit.BeforeClass;
@@ -30,6 +43,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
@@ -139,6 +153,31 @@
assertQ(req("q", childb), sixParents);
}
+ @Test
+ public void testBrokenParentFilter() throws IOException, Exception {
+ final SolrQueryRequest req = req();
+ final List<LeafReaderContext> segments = req.getSearcher().getLeafReader().leaves();
+ final LeafReaderContext aSegment = segments.get(random().nextInt(segments.size()));
+ final IndexSearcher segmentSearcher = new IndexSearcher(aSegment, null);
+ final TopFieldDocs parentsFromSegment = segmentSearcher.search(
+ TermRangeQuery.newStringRange("parent_s", null, null, true, true)
+ , sixParents.length, new Sort( new SortField(null, Type.DOC, true)));
+
+ final StringBuilder noParentsClasuse = new StringBuilder();
+ for(int p=0;p<parentsFromSegment.totalHits;p++){
+ final String parent = segmentSearcher.doc(
+ parentsFromSegment.scoreDocs[p].doc).get("parent_s");
+ noParentsClasuse.append(" -parent_s:"+parent);
+ if(p==0 && !rarely()){// most times I wish to test absebse of last parent in a segment
+ break;
+ }
+ }
+ req.setParams(new MapSolrParams(new HashMap<String,String>(){{
+ put("q","{!parent which=\"parent_s:[* TO *]"+noParentsClasuse.toString()+"\"}child_s:l");
+ }}));
+ assertQEx("expecting an exeption from "+CheckJoinIndex.class.getSimpleName(),"segment", req, ErrorCode.BAD_REQUEST);
+ }
+
private static final String sixParents[] = new String[] {
"//*[@numFound='6']", "//doc/arr[@name=\"parent_s\"]/str='a'",
"//doc/arr[@name=\"parent_s\"]/str='b'",