SOLR-13199: Fix NPE in ChildDocTransformer when parenFilter is invalid

* Return proper error message and error code
This commit is contained in:
Munendra S N 2020-03-18 10:32:28 +05:30
parent a1485ab92b
commit 2b327e5deb
4 changed files with 41 additions and 7 deletions

View File

@ -64,6 +64,9 @@ Bug Fixes
* SOLR-13264: IndexSizeTrigger aboveOp / belowOp properties not in valid properties.
(Christine Poerschke, ab)
* SOLR-13199: Return proper error when invalid parentFilter is passed in ChildDocTransformer
(Johannes Kloos, Munendra S N, David Smiley, Mikhail Khludnev)
Other Changes
---------------------
* SOLR-14197: SolrResourceLoader: marked many methods as deprecated, and in some cases rerouted exiting logic to avoid

View File

@ -34,6 +34,7 @@ import org.apache.lucene.index.SortedDocValues;
import org.apache.lucene.search.join.BitSetProducer;
import org.apache.lucene.util.BitSet;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrException;
import org.apache.solr.search.DocSet;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.search.SolrReturnFields;
@ -89,6 +90,11 @@ class ChildDocTransformer extends DocTransformer {
final int segRootId = rootDocId - segBaseId;
final BitSet segParentsBitSet = parentsFilter.getBitSet(leafReaderContext);
if (segParentsBitSet == null) {
throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
"Parent filter '" + parentsFilter + "' doesn't match any parent documents");
}
final int segPrevRootId = segRootId==0? -1: segParentsBitSet.prevSetBit(segRootId - 1); // can return -1 and that's okay
if (segPrevRootId == (segRootId - 1)) {

View File

@ -104,7 +104,11 @@ public class ChildDocTransformerFactory extends TransformerFactory {
if(buildHierarchy) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Parent filter should not be sent when the schema is nested");
}
parentsFilter = new QueryBitSetProducer(parseQuery(parentFilterStr, req, "parentFilter"));
Query query = parseQuery(parentFilterStr, req, "parentFilter");
if (query == null) {
throw new SolrException(ErrorCode.BAD_REQUEST, "Invalid Parent filter '" + parentFilterStr + "', resolves to null");
}
parentsFilter = new QueryBitSetProducer(query);
}
String childFilterStr = params.get( "childFilter" );
@ -125,11 +129,8 @@ public class ChildDocTransformerFactory extends TransformerFactory {
String childReturnFields = params.get("fl");
SolrReturnFields childSolrReturnFields;
if(childReturnFields != null) {
if (childReturnFields != null) {
childSolrReturnFields = new SolrReturnFields(childReturnFields, req);
} else if(req.getSchema().getDefaultLuceneMatchVersion().major < 8) {
// ensure backwards for versions prior to SOLR 8
childSolrReturnFields = new SolrReturnFields();
} else {
childSolrReturnFields = new SolrReturnFields(req);
}

View File

@ -22,6 +22,7 @@ import java.util.Iterator;
import org.apache.lucene.util.TestUtil;
import org.apache.solr.SolrTestCaseJ4;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.BasicResultContext;
@ -29,6 +30,8 @@ import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.hamcrest.core.StringContains.containsString;
public class TestChildDocTransformer extends SolrTestCaseJ4 {
private static String ID_FIELD = "id";
@ -92,8 +95,6 @@ public class TestChildDocTransformer extends SolrTestCaseJ4 {
"/response/result/doc[1]/doc[1]/str[@name='id']='3'" ,
"/response/result/doc[1]/doc[2]/str[@name='id']='5'"};
assertQ(req("q", "*:*", "fq", "subject:\"parentDocument\" ",
"fl", "*,[child parentFilter=\"subject:parentDocument\"]"), test1);
@ -102,6 +103,29 @@ public class TestChildDocTransformer extends SolrTestCaseJ4 {
assertQ(req("q", "*:*", "fq", "subject:\"parentDocument\" ",
"fl", "id, subject,[child parentFilter=\"subject:parentDocument\" childFilter=\"title:bar\" limit=2]"), test3);
SolrException e = expectThrows(SolrException.class, () -> {
h.query(req("q", "*:*", "fq", "subject:\"parentDocument\" ",
"fl", "id, subject,[child parentFilter=\"subject:bleh\" childFilter=\"title:bar\" limit=2]"));
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, e.code());
assertThat(e.getMessage(),
containsString("Parent filter 'QueryBitSetProducer(subject:bleh)' doesn't match any parent documents"));
e = expectThrows(SolrException.class, () -> {
h.query(req("q", "*:*", "fq", "subject:\"parentDocument\" ",
"fl", "id, subject,[child parentFilter=e childFilter=\"title:bar\" limit=2]"));
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, e.code());
assertThat(e.getMessage(),
containsString("Parent filter 'QueryBitSetProducer(text:e)' doesn't match any parent documents"));
e = expectThrows(SolrException.class, () -> {
h.query(req("q", "*:*", "fq", "subject:\"parentDocument\" ",
"fl", "id, subject,[child parentFilter=\"\"]"));
});
assertEquals(SolrException.ErrorCode.BAD_REQUEST.code, e.code());
assertThat(e.getMessage(), containsString("Invalid Parent filter '', resolves to null"));
}
private void testSubQueryXML() {