diff --git a/changelog/unreleased/SOLR-6973-signature-partial-update.yml b/changelog/unreleased/SOLR-6973-signature-partial-update.yml new file mode 100644 index 000000000000..36cb04a0f974 --- /dev/null +++ b/changelog/unreleased/SOLR-6973-signature-partial-update.yml @@ -0,0 +1,7 @@ +title: SignatureUpdateProcessorFactory no longer adds an empty signature to (or deletes duplicates for) a partial update that contains none of the signature fields. +type: fixed +authors: + - name: Nick Shanin +links: + - name: SOLR-6973 + url: https://issues.apache.org/jira/browse/SOLR-6973 diff --git a/solr/core/src/java/org/apache/solr/update/processor/SignatureUpdateProcessorFactory.java b/solr/core/src/java/org/apache/solr/update/processor/SignatureUpdateProcessorFactory.java index fd99601357db..e895bfb5d215 100644 --- a/solr/core/src/java/org/apache/solr/update/processor/SignatureUpdateProcessorFactory.java +++ b/solr/core/src/java/org/apache/solr/update/processor/SignatureUpdateProcessorFactory.java @@ -162,6 +162,22 @@ public void processAdd(AddUpdateCommand cmd) throws IOException { currDocSigFields = sigFields; } + if (isPartialUpdate) { + for (String field : currDocSigFields) { + if (doc.getField(field) != null) { + throw new SolrException( + ErrorCode.SERVER_ERROR, + "Can't use SignatureUpdateProcessor with partial update request " + + "containing signature field: " + + field); + } + } + // none of the signature fields are in the partial update, so there is nothing to sign; + // an empty signature would overwrite or delete unrelated documents + if (next != null) next.processAdd(cmd); + return; + } + Signature sig = req.getCore().getResourceLoader().newInstance(signatureClass, Signature.class); sig.init(params); @@ -169,13 +185,6 @@ public void processAdd(AddUpdateCommand cmd) throws IOException { for (String field : currDocSigFields) { SolrInputField f = doc.getField(field); if (f != null) { - if (isPartialUpdate) { - throw new SolrException( - ErrorCode.SERVER_ERROR, - "Can't use SignatureUpdateProcessor with partial update request " - + "containing signature field: " - + field); - } sig.add(field); Object o = f.getValue(); if (o instanceof Collection) { diff --git a/solr/core/src/test/org/apache/solr/update/processor/SignatureUpdateProcessorFactoryTest.java b/solr/core/src/test/org/apache/solr/update/processor/SignatureUpdateProcessorFactoryTest.java index 05487931e063..1056f7527174 100644 --- a/solr/core/src/test/org/apache/solr/update/processor/SignatureUpdateProcessorFactoryTest.java +++ b/solr/core/src/test/org/apache/solr/update/processor/SignatureUpdateProcessorFactoryTest.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import org.apache.lucene.util.Constants; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.request.JavaBinRequestWriter; @@ -34,6 +35,7 @@ import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrQueryRequestBase; import org.apache.solr.response.SolrQueryResponse; +import org.apache.solr.update.AddUpdateCommand; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -200,6 +202,39 @@ public void run() { checkNumDocs(1); } + @Test + public void testPartialUpdateWithoutSignatureFieldsIsPassedThrough() throws Exception { + SignatureUpdateProcessorFactory factory = new SignatureUpdateProcessorFactory(); + NamedList args = new NamedList<>(); + args.add("signatureField", "signatureField"); + args.add("overwriteDupes", true); + args.add("fields", "v_t,t_field"); + args.add("signatureClass", "org.apache.solr.update.processor.Lookup3Signature"); + factory.init(args); + + AtomicReference seen = new AtomicReference<>(); + try (SolrQueryRequest r = req()) { + UpdateRequestProcessor proc = + factory.getInstance( + r, + new SolrQueryResponse(), + new UpdateRequestProcessor(null) { + @Override + public void processAdd(AddUpdateCommand cmd) { + seen.set(cmd); + } + }); + AddUpdateCommand cmd = new AddUpdateCommand(r); + cmd.solrDoc = new SolrInputDocument(); + cmd.solrDoc.addField("id", "1a"); + cmd.solrDoc.addField("name", Map.of("set", "changed")); + proc.processAdd(cmd); + } + assertNotNull(seen.get()); + assertNull(seen.get().solrDoc.getField("signatureField")); + assertNull(seen.get().updateTerm); + } + /** a non-indexed signatureField is fine as long as overwriteDupes==false */ @Test public void testNonIndexedSignatureField() throws Exception {