SOLR-13728: fail partial updates to child docs when not supported.

(cherry picked from commit c8203e4787)
This commit is contained in:
David Smiley 2019-09-06 05:16:55 -04:00
parent 625c3c9477
commit 3a20ebc3a6
4 changed files with 54 additions and 0 deletions

View File

@ -93,6 +93,9 @@ Improvements
* SOLR-13720: BlockJoinParentQParser.getCachedFilter()made public for accessing from QParser plugins
(Stanislav Livotov via Mikhail Khludnev)
* SOLR-13728: If a partial update (aka atomic update) is attempted on a document that has child docs, then ensure
the schema supports it (_root_ stored/docValues) by throwing an exception. (David Smiley)
Bug Fixes
----------------------

View File

@ -1974,6 +1974,17 @@ public class IndexSchema {
return nestPathType instanceof NestPathField;
}
/**
* Does this schema supports partial updates (aka atomic updates) and child docs as well.
*/
public boolean supportsPartialUpdatesOfChildDocs() {
if (savesChildDocRelations() == false) {
return false;
}
SchemaField rootField = getField(IndexSchema.ROOT_FIELD_NAME);
return rootField.stored() || rootField.hasDocValues();
}
public PayloadDecoder getPayloadDecoder(String field) {
FieldType ft = getFieldType(field);
if (ft == null)

View File

@ -23,6 +23,8 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import com.google.common.annotations.VisibleForTesting;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.CharsRefBuilder;
import org.apache.solr.client.solrj.SolrRequest;
@ -693,6 +695,13 @@ public class DistributedUpdateProcessor extends UpdateRequestProcessor {
// create a new doc by default if an old one wasn't found
mergedDoc = docMerger.merge(sdoc, new SolrInputDocument());
} else {
// Safety check: don't allow an update to an existing doc that has children, unless we actually support this.
if (req.getSchema().isUsableForChildDocs() // however, next line we see it doesn't support child docs
&& req.getSchema().supportsPartialUpdatesOfChildDocs() == false
&& req.getSearcher().count(new TermQuery(new Term(IndexSchema.ROOT_FIELD_NAME, idBytes))) > 1) {
throw new SolrException(ErrorCode.BAD_REQUEST, "This schema does not support partial updates to nested docs. See ref guide.");
}
String oldRootDocRootFieldVal = (String) oldRootDocWithChildren.getFieldValue(IndexSchema.ROOT_FIELD_NAME);
if(req.getSchema().savesChildDocRelations() && oldRootDocRootFieldVal != null &&
!idString.equals(oldRootDocRootFieldVal)) {

View File

@ -18,6 +18,7 @@ package org.apache.solr.update.processor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -1179,6 +1180,36 @@ public class AtomicUpdatesTest extends SolrTestCaseJ4 {
"/response/docs/[0]/single_i_dvn==5");
}
/**
* Test what happens if we try to update the parent of a doc with children.
* This fails because _root_ is not stored which is currently required for doing this.
*/
@Test
public void testUpdateNestedDocUnsupported() throws Exception {
assertU(adoc(sdoc(
"id", "1",
"children", Arrays.asList(sdoc(
"id", "100",
"cat", "childCat1")
)
)));
assertU(commit());
// update the parent doc to have a category
try {
assertU(adoc(sdoc(
"id", "1",
"cat", Collections.singletonMap("add", Arrays.asList("parentCat"))
)));
fail("expected a failure");
} catch (Exception e) {
assertEquals("org.apache.solr.common.SolrException: " +
"This schema does not support partial updates to nested docs. See ref guide.", e.toString());
}
}
@Test
public void testInvalidOperation() {
SolrInputDocument doc;