diff options
Diffstat (limited to 'src/mongo/db/update/pipeline_executor.cpp')
-rw-r--r-- | src/mongo/db/update/pipeline_executor.cpp | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/src/mongo/db/update/pipeline_executor.cpp b/src/mongo/db/update/pipeline_executor.cpp index 2dd47908309..d12cfd7f292 100644 --- a/src/mongo/db/update/pipeline_executor.cpp +++ b/src/mongo/db/update/pipeline_executor.cpp @@ -31,11 +31,14 @@ #include "mongo/db/update/pipeline_executor.h" +#include "mongo/bson/mutable/document.h" #include "mongo/db/bson/dotted_path_support.h" #include "mongo/db/pipeline/document_source_queue.h" #include "mongo/db/pipeline/lite_parsed_pipeline.h" +#include "mongo/db/update/document_diff_calculator.h" #include "mongo/db/update/object_replace_executor.h" #include "mongo/db/update/storage_validation.h" +#include "mongo/db/update/update_oplog_entry_serialization.h" namespace mongo { @@ -86,13 +89,39 @@ PipelineExecutor::PipelineExecutor(const boost::intrusive_ptr<ExpressionContext> } UpdateExecutor::ApplyResult PipelineExecutor::applyUpdate(ApplyParams applyParams) const { + const auto originalDoc = applyParams.element.getDocument().getObject(); + DocumentSourceQueue* queueStage = static_cast<DocumentSourceQueue*>(_pipeline->peekFront()); - queueStage->emplace_back(Document{applyParams.element.getDocument().getObject()}); - auto transformedDoc = _pipeline->getNext()->toBson(); - auto transformedDocHasIdField = transformedDoc.hasField(kIdFieldName); + queueStage->emplace_back(Document{originalDoc}); + + const auto transformedDoc = _pipeline->getNext()->toBson(); + const auto transformedDocHasIdField = transformedDoc.hasField(kIdFieldName); - return ObjectReplaceExecutor::applyReplacementUpdate( + // Replace the pre-image document in applyParams with the post image we got from running the + // post image. + auto ret = ObjectReplaceExecutor::applyReplacementUpdate( applyParams, transformedDoc, transformedDocHasIdField); + // The oplog entry should not have been populated yet. + invariant(ret.oplogEntry.isEmpty()); + + if (applyParams.logMode != ApplyParams::LogMode::kDoNotGenerateOplogEntry && !ret.noop) { + if (applyParams.logMode == ApplyParams::LogMode::kGenerateOplogEntry) { + // We're allowed to generate $v: 2 log entries. + const auto diff = doc_diff::computeDiff(originalDoc, transformedDoc); + if (diff) { + ret.oplogEntry = update_oplog_entry::makeDeltaOplogEntry(*diff); + return ret; + } + } + + // Either we can't use diffing or diffing failed so fall back to full replacement. Set the + // replacement to the value set by the object replace executor, in case it changed _id or + // anything like that. + ret.oplogEntry = update_oplog_entry::makeReplacementOplogEntry( + applyParams.element.getDocument().getObject()); + } + + return ret; } Value PipelineExecutor::serialize() const { |