summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorJames Wahlin <james@mongodb.com>2019-04-11 15:13:50 -0400
committerJames Wahlin <james@mongodb.com>2019-04-29 16:04:49 -0400
commit71e13919c25fbf839d2a65b8c7842f9466e3876a (patch)
tree2be3105b3c00849fcbed552ce892b3eaa40f3c71 /src/mongo/db
parent59a22d074e7d690b8db0eda76747ff3985907c98 (diff)
downloadmongo-71e13919c25fbf839d2a65b8c7842f9466e3876a.tar.gz
SERVER-40585 UpdateNode should not derive from UpdateExecutor
Diffstat (limited to 'src/mongo/db')
-rw-r--r--src/mongo/db/update/SConscript4
-rw-r--r--src/mongo/db/update/object_replace_executor.cpp (renamed from src/mongo/db/update/object_replace_node.cpp)13
-rw-r--r--src/mongo/db/update/object_replace_executor.h (renamed from src/mongo/db/update/object_replace_node.h)23
-rw-r--r--src/mongo/db/update/object_replace_executor_test.cpp (renamed from src/mongo/db/update/object_replace_node_test.cpp)76
-rw-r--r--src/mongo/db/update/pipeline_executor.cpp4
-rw-r--r--src/mongo/db/update/pipeline_executor.h8
-rw-r--r--src/mongo/db/update/update_driver.cpp16
-rw-r--r--src/mongo/db/update/update_driver.h26
-rw-r--r--src/mongo/db/update/update_executor.h17
-rw-r--r--src/mongo/db/update/update_node.h25
-rw-r--r--src/mongo/db/update/update_node_test_fixture.h2
-rw-r--r--src/mongo/db/update/update_node_visitor.h4
-rw-r--r--src/mongo/db/update/update_tree_executor.h69
13 files changed, 177 insertions, 110 deletions
diff --git a/src/mongo/db/update/SConscript b/src/mongo/db/update/SConscript
index 819a9c6e834..29a37605244 100644
--- a/src/mongo/db/update/SConscript
+++ b/src/mongo/db/update/SConscript
@@ -75,7 +75,7 @@ env.Library(
'current_date_node.cpp',
'modifier_node.cpp',
'modifier_table.cpp',
- 'object_replace_node.cpp',
+ 'object_replace_executor.cpp',
'pipeline_executor.cpp',
'pop_node.cpp',
'pull_node.cpp',
@@ -107,7 +107,7 @@ env.CppUnitTest(
'bit_node_test.cpp',
'compare_node_test.cpp',
'current_date_node_test.cpp',
- 'object_replace_node_test.cpp',
+ 'object_replace_executor_test.cpp',
'pipeline_executor_test.cpp',
'pop_node_test.cpp',
'pull_node_test.cpp',
diff --git a/src/mongo/db/update/object_replace_node.cpp b/src/mongo/db/update/object_replace_executor.cpp
index 42f89906181..8a65cd1b0ca 100644
--- a/src/mongo/db/update/object_replace_node.cpp
+++ b/src/mongo/db/update/object_replace_executor.cpp
@@ -29,7 +29,7 @@
#include "mongo/platform/basic.h"
-#include "mongo/db/update/object_replace_node.h"
+#include "mongo/db/update/object_replace_executor.h"
#include "mongo/base/data_view.h"
#include "mongo/db/bson/dotted_path_support.h"
@@ -44,10 +44,11 @@ namespace {
constexpr StringData kIdFieldName = "_id"_sd;
} // namespace
-ObjectReplaceNode::ObjectReplaceNode(BSONObj value) : val(value.getOwned()), _containsId(false) {
+ObjectReplaceExecutor::ObjectReplaceExecutor(BSONObj replacement)
+ : _replacementDoc(replacement.getOwned()), _containsId(false) {
// Replace all zero-valued timestamps with the current time and check for the existence of _id.
- for (auto&& elem : val) {
+ for (auto&& elem : _replacementDoc) {
// Do not change the _id field.
if (elem.fieldNameStringData() == kIdFieldName) {
@@ -69,7 +70,7 @@ ObjectReplaceNode::ObjectReplaceNode(BSONObj value) : val(value.getOwned()), _co
}
}
-UpdateExecutor::ApplyResult ObjectReplaceNode::applyReplacementUpdate(
+UpdateExecutor::ApplyResult ObjectReplaceExecutor::applyReplacementUpdate(
ApplyParams applyParams, const BSONObj& replacementDoc, bool replacementDocContainsIdField) {
auto originalDoc = applyParams.element.getDocument().getObject();
@@ -153,8 +154,8 @@ UpdateExecutor::ApplyResult ObjectReplaceNode::applyReplacementUpdate(
return ApplyResult();
}
-UpdateExecutor::ApplyResult ObjectReplaceNode::applyUpdate(ApplyParams applyParams) const {
- return applyReplacementUpdate(applyParams, val, _containsId);
+UpdateExecutor::ApplyResult ObjectReplaceExecutor::applyUpdate(ApplyParams applyParams) const {
+ return applyReplacementUpdate(applyParams, _replacementDoc, _containsId);
}
} // namespace mongo
diff --git a/src/mongo/db/update/object_replace_node.h b/src/mongo/db/update/object_replace_executor.h
index c2c570f9093..f141f169d6f 100644
--- a/src/mongo/db/update/object_replace_node.h
+++ b/src/mongo/db/update/object_replace_executor.h
@@ -42,7 +42,7 @@ namespace mongo {
/**
* An UpdateExecutor representing a replacement-style update.
*/
-class ObjectReplaceNode : public UpdateExecutor {
+class ObjectReplaceExecutor : public UpdateExecutor {
public:
// Applies a replacement style update to 'applyParams.element'. If
@@ -56,9 +56,7 @@ public:
* Initializes the node with the document to replace with. Any zero-valued timestamps (except
* for the _id) are updated to the current time.
*/
- explicit ObjectReplaceNode(BSONObj value);
-
- void setCollator(const CollatorInterface* collator) final {}
+ explicit ObjectReplaceExecutor(BSONObj replacement);
/**
* Replaces the document that 'applyParams.element' belongs to with 'val'. If 'val' does not
@@ -68,19 +66,22 @@ public:
*/
ApplyResult applyUpdate(ApplyParams applyParams) const final;
- BSONObj serialize() const {
- return val;
+ Value serialize() const final {
+ return Value(_replacementDoc);
}
- void acceptVisitor(UpdateNodeVisitor* visitor) final {
- visitor->visit(this);
+ const BSONObj& getReplacement() const {
+ return _replacementDoc;
}
- // Object to replace with.
- BSONObj val;
+ void setReplacement(BSONObj doc) {
+ _replacementDoc = std::move(doc);
+ }
private:
- // True if val contains an _id.
+ BSONObj _replacementDoc;
+
+ // True if '_replacementDoc' contains an _id.
bool _containsId;
};
diff --git a/src/mongo/db/update/object_replace_node_test.cpp b/src/mongo/db/update/object_replace_executor_test.cpp
index 0a0e241cf0c..cef054fd289 100644
--- a/src/mongo/db/update/object_replace_node_test.cpp
+++ b/src/mongo/db/update/object_replace_executor_test.cpp
@@ -29,7 +29,7 @@
#include "mongo/platform/basic.h"
-#include "mongo/db/update/object_replace_node.h"
+#include "mongo/db/update/object_replace_executor.h"
#include "mongo/bson/mutable/algorithm.h"
#include "mongo/bson/mutable/mutable_bson_test_utils.h"
@@ -41,13 +41,13 @@
namespace mongo {
namespace {
-using ObjectReplaceNodeTest = UpdateNodeTest;
+using ObjectReplaceExecutorTest = UpdateNodeTest;
using mongo::mutablebson::Element;
using mongo::mutablebson::countChildren;
-TEST_F(ObjectReplaceNodeTest, Noop) {
+TEST_F(ObjectReplaceExecutorTest, Noop) {
auto obj = fromjson("{a: 1, b: 2}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{a: 1, b: 2}"));
auto result = node.applyUpdate(getApplyParams(doc.root()));
@@ -58,9 +58,9 @@ TEST_F(ObjectReplaceNodeTest, Noop) {
ASSERT_EQUALS(fromjson("{}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, ShouldNotCreateIdIfNoIdExistsAndNoneIsSpecified) {
+TEST_F(ObjectReplaceExecutorTest, ShouldNotCreateIdIfNoIdExistsAndNoneIsSpecified) {
auto obj = fromjson("{a: 1, b: 2}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{c: 1, d: 2}"));
auto result = node.applyUpdate(getApplyParams(doc.root()));
@@ -71,9 +71,9 @@ TEST_F(ObjectReplaceNodeTest, ShouldNotCreateIdIfNoIdExistsAndNoneIsSpecified) {
ASSERT_EQUALS(fromjson("{a: 1, b: 2}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, ShouldPreserveIdOfExistingDocumentIfIdNotSpecified) {
+TEST_F(ObjectReplaceExecutorTest, ShouldPreserveIdOfExistingDocumentIfIdNotSpecified) {
auto obj = fromjson("{a: 1, b: 2}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0, c: 1, d: 2}"));
auto result = node.applyUpdate(getApplyParams(doc.root()));
@@ -84,9 +84,9 @@ TEST_F(ObjectReplaceNodeTest, ShouldPreserveIdOfExistingDocumentIfIdNotSpecified
ASSERT_EQUALS(fromjson("{_id: 0, a: 1, b: 2}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, ShouldSucceedWhenImmutableIdIsNotModified) {
+TEST_F(ObjectReplaceExecutorTest, ShouldSucceedWhenImmutableIdIsNotModified) {
auto obj = fromjson("{_id: 0, a: 1, b: 2}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0, c: 1, d: 2}"));
addImmutablePath("_id");
@@ -98,9 +98,9 @@ TEST_F(ObjectReplaceNodeTest, ShouldSucceedWhenImmutableIdIsNotModified) {
ASSERT_EQUALS(fromjson("{_id: 0, a: 1, b: 2}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, IdTimestampNotModified) {
+TEST_F(ObjectReplaceExecutorTest, IdTimestampNotModified) {
auto obj = fromjson("{_id: Timestamp(0,0)}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{}"));
auto result = node.applyUpdate(getApplyParams(doc.root()));
@@ -111,9 +111,9 @@ TEST_F(ObjectReplaceNodeTest, IdTimestampNotModified) {
ASSERT_EQUALS(fromjson("{_id: Timestamp(0,0)}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, NonIdTimestampsModified) {
+TEST_F(ObjectReplaceExecutorTest, NonIdTimestampsModified) {
auto obj = fromjson("{a: Timestamp(0,0), b: Timestamp(0,0)}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{}"));
auto result = node.applyUpdate(getApplyParams(doc.root()));
@@ -138,9 +138,9 @@ TEST_F(ObjectReplaceNodeTest, NonIdTimestampsModified) {
ASSERT_EQUALS(doc, getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, ComplexDoc) {
+TEST_F(ObjectReplaceExecutorTest, ComplexDoc) {
auto obj = fromjson("{a: 1, b: [0, 1, 2], c: {d: 1}}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{a: 1, b: [0, 2, 2], e: []}"));
auto result = node.applyUpdate(getApplyParams(doc.root()));
@@ -151,9 +151,9 @@ TEST_F(ObjectReplaceNodeTest, ComplexDoc) {
ASSERT_EQUALS(fromjson("{a: 1, b: [0, 1, 2], c: {d: 1}}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, CannotRemoveImmutablePath) {
+TEST_F(ObjectReplaceExecutorTest, CannotRemoveImmutablePath) {
auto obj = fromjson("{_id: 0, c: 1}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0, a: {b: 1}}"));
addImmutablePath("a.b");
@@ -164,9 +164,9 @@ TEST_F(ObjectReplaceNodeTest, CannotRemoveImmutablePath) {
"field was found to have been removed --{ _id: 0, a: { b: 1 } }");
}
-TEST_F(ObjectReplaceNodeTest, IdFieldIsNotRemoved) {
+TEST_F(ObjectReplaceExecutorTest, IdFieldIsNotRemoved) {
auto obj = fromjson("{a: 1}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0, b: 1}"));
addImmutablePath("_id");
@@ -178,9 +178,9 @@ TEST_F(ObjectReplaceNodeTest, IdFieldIsNotRemoved) {
ASSERT_EQUALS(fromjson("{_id: 0, a: 1}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, CannotReplaceImmutablePathWithArrayField) {
+TEST_F(ObjectReplaceExecutorTest, CannotReplaceImmutablePathWithArrayField) {
auto obj = fromjson("{_id: 0, a: [{b: 1}]}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0, a: {b: 1}}"));
addImmutablePath("a.b");
@@ -191,9 +191,9 @@ TEST_F(ObjectReplaceNodeTest, CannotReplaceImmutablePathWithArrayField) {
"'a.b' was found to be an array or array descendant.");
}
-TEST_F(ObjectReplaceNodeTest, CannotMakeImmutablePathArrayDescendant) {
+TEST_F(ObjectReplaceExecutorTest, CannotMakeImmutablePathArrayDescendant) {
auto obj = fromjson("{_id: 0, a: [1]}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0, a: {'0': 1}}"));
addImmutablePath("a.0");
@@ -204,9 +204,9 @@ TEST_F(ObjectReplaceNodeTest, CannotMakeImmutablePathArrayDescendant) {
"'a.0' was found to be an array or array descendant.");
}
-TEST_F(ObjectReplaceNodeTest, CannotModifyImmutablePath) {
+TEST_F(ObjectReplaceExecutorTest, CannotModifyImmutablePath) {
auto obj = fromjson("{_id: 0, a: {b: 2}}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0, a: {b: 1}}"));
addImmutablePath("a.b");
@@ -217,9 +217,9 @@ TEST_F(ObjectReplaceNodeTest, CannotModifyImmutablePath) {
"to have been altered to b: 2");
}
-TEST_F(ObjectReplaceNodeTest, CannotModifyImmutableId) {
+TEST_F(ObjectReplaceExecutorTest, CannotModifyImmutableId) {
auto obj = fromjson("{_id: 1}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{_id: 0}"));
addImmutablePath("_id");
@@ -230,9 +230,9 @@ TEST_F(ObjectReplaceNodeTest, CannotModifyImmutableId) {
"to have been altered to _id: 1");
}
-TEST_F(ObjectReplaceNodeTest, CanAddImmutableField) {
+TEST_F(ObjectReplaceExecutorTest, CanAddImmutableField) {
auto obj = fromjson("{a: {b: 1}}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{c: 1}"));
addImmutablePath("a.b");
@@ -244,9 +244,9 @@ TEST_F(ObjectReplaceNodeTest, CanAddImmutableField) {
ASSERT_EQUALS(fromjson("{a: {b: 1}}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, CanAddImmutableId) {
+TEST_F(ObjectReplaceExecutorTest, CanAddImmutableId) {
auto obj = fromjson("{_id: 0}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{c: 1}"));
addImmutablePath("_id");
@@ -258,9 +258,9 @@ TEST_F(ObjectReplaceNodeTest, CanAddImmutableId) {
ASSERT_EQUALS(fromjson("{_id: 0}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, CannotCreateDollarPrefixedNameWhenValidateForStorageIsTrue) {
+TEST_F(ObjectReplaceExecutorTest, CannotCreateDollarPrefixedNameWhenValidateForStorageIsTrue) {
auto obj = fromjson("{a: {b: 1, $bad: 1}}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{}"));
ASSERT_THROWS_CODE_AND_WHAT(
@@ -270,9 +270,9 @@ TEST_F(ObjectReplaceNodeTest, CannotCreateDollarPrefixedNameWhenValidateForStora
"The dollar ($) prefixed field '$bad' in 'a.$bad' is not valid for storage.");
}
-TEST_F(ObjectReplaceNodeTest, CanCreateDollarPrefixedNameWhenValidateForStorageIsFalse) {
+TEST_F(ObjectReplaceExecutorTest, CanCreateDollarPrefixedNameWhenValidateForStorageIsFalse) {
auto obj = fromjson("{a: {b: 1, $bad: 1}}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{}"));
setValidateForStorage(false);
@@ -284,9 +284,9 @@ TEST_F(ObjectReplaceNodeTest, CanCreateDollarPrefixedNameWhenValidateForStorageI
ASSERT_EQUALS(fromjson("{a: {b: 1, $bad: 1}}"), getLogDoc());
}
-TEST_F(ObjectReplaceNodeTest, NoLogBuilder) {
+TEST_F(ObjectReplaceExecutorTest, NoLogBuilder) {
auto obj = fromjson("{a: 1}");
- ObjectReplaceNode node(obj);
+ ObjectReplaceExecutor node(obj);
mutablebson::Document doc(fromjson("{b: 1}"));
setLogBuilderToNull();
diff --git a/src/mongo/db/update/pipeline_executor.cpp b/src/mongo/db/update/pipeline_executor.cpp
index d3360ffb2c4..f2e66da44b9 100644
--- a/src/mongo/db/update/pipeline_executor.cpp
+++ b/src/mongo/db/update/pipeline_executor.cpp
@@ -34,7 +34,7 @@
#include "mongo/db/bson/dotted_path_support.h"
#include "mongo/db/pipeline/document_source_mock.h"
#include "mongo/db/pipeline/lite_parsed_pipeline.h"
-#include "mongo/db/update/object_replace_node.h"
+#include "mongo/db/update/object_replace_executor.h"
#include "mongo/db/update/storage_validation.h"
namespace mongo {
@@ -80,7 +80,7 @@ UpdateExecutor::ApplyResult PipelineExecutor::applyUpdate(ApplyParams applyParam
auto transformedDoc = _pipeline->getNext()->toBson();
auto transformedDocHasIdField = transformedDoc.hasField(kIdFieldName);
- return ObjectReplaceNode::applyReplacementUpdate(
+ return ObjectReplaceExecutor::applyReplacementUpdate(
applyParams, transformedDoc, transformedDocHasIdField);
}
diff --git a/src/mongo/db/update/pipeline_executor.h b/src/mongo/db/update/pipeline_executor.h
index fb1c5d7a562..0fba04ad24b 100644
--- a/src/mongo/db/update/pipeline_executor.h
+++ b/src/mongo/db/update/pipeline_executor.h
@@ -61,7 +61,7 @@ public:
*/
ApplyResult applyUpdate(ApplyParams applyParams) const final;
- Value serialize() const {
+ Value serialize() const final {
std::vector<Value> valueArray;
for (const auto& stage : _pipeline->getSources()) {
// TODO SERVER-40539: Consider subclassing DocumentSourceQueue with a class that is
@@ -77,12 +77,6 @@ public:
return Value(valueArray);
}
- void acceptVisitor(UpdateNodeVisitor* visitor) final {
- visitor->visit(this);
- }
-
- void setCollator(const CollatorInterface* collator) final {}
-
private:
boost::intrusive_ptr<ExpressionContext> _expCtx;
std::unique_ptr<Pipeline, PipelineDeleter> _pipeline;
diff --git a/src/mongo/db/update/update_driver.cpp b/src/mongo/db/update/update_driver.cpp
index a897f5739cd..d66dcc8dab9 100644
--- a/src/mongo/db/update/update_driver.cpp
+++ b/src/mongo/db/update/update_driver.cpp
@@ -41,7 +41,7 @@
#include "mongo/db/server_options.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/db/update/modifier_table.h"
-#include "mongo/db/update/object_replace_node.h"
+#include "mongo/db/update/object_replace_executor.h"
#include "mongo/db/update/path_support.h"
#include "mongo/db/update/storage_validation.h"
#include "mongo/util/embedded_builder.h"
@@ -165,9 +165,11 @@ void UpdateDriver::parse(
// Check if the update expression is a full object replacement.
if (isDocReplacement(updateMod)) {
- uassert(ErrorCodes::FailedToParse, "multi update only works with $ operators", !multi);
+ uassert(ErrorCodes::FailedToParse,
+ "multi update is not supported for replacement-style update",
+ !multi);
- _updateExecutor = stdx::make_unique<ObjectReplaceNode>(updateMod.getUpdateClassic());
+ _updateExecutor = stdx::make_unique<ObjectReplaceExecutor>(updateMod.getUpdateClassic());
// Register the fact that this driver will only do full object replacements.
_updateType = UpdateType::kReplacement;
@@ -192,7 +194,7 @@ void UpdateDriver::parse(
auto root = stdx::make_unique<UpdateObjectNode>();
_positional = parseUpdateExpression(updateExpr, root.get(), _expCtx, arrayFilters);
- _updateExecutor = std::move(root);
+ _updateExecutor = stdx::make_unique<UpdateTreeExecutor>(std::move(root));
}
Status UpdateDriver::populateDocumentWithQueryFields(OperationContext* opCtx,
@@ -261,7 +263,7 @@ Status UpdateDriver::update(StringData matchedField,
_logDoc.reset();
LogBuilder logBuilder(_logDoc.root());
- UpdateNode::ApplyParams applyParams(doc->root(), immutablePaths);
+ UpdateExecutor::ApplyParams applyParams(doc->root(), immutablePaths);
applyParams.matchedField = matchedField;
applyParams.insert = isInsert;
applyParams.fromOplogApplication = _fromOplogApplication;
@@ -305,11 +307,11 @@ Status UpdateDriver::update(StringData matchedField,
}
void UpdateDriver::setCollator(const CollatorInterface* collator) {
+ _expCtx->setCollator(collator);
+
if (_updateExecutor) {
_updateExecutor->setCollator(collator);
}
-
- _expCtx->setCollator(collator);
}
bool UpdateDriver::isDocReplacement(const write_ops::UpdateModification& updateMod) {
diff --git a/src/mongo/db/update/update_driver.h b/src/mongo/db/update/update_driver.h
index 4f400ce640c..24c0cd72edc 100644
--- a/src/mongo/db/update/update_driver.h
+++ b/src/mongo/db/update/update_driver.h
@@ -42,10 +42,11 @@
#include "mongo/db/pipeline/value.h"
#include "mongo/db/query/canonical_query.h"
#include "mongo/db/update/modifier_table.h"
-#include "mongo/db/update/object_replace_node.h"
+#include "mongo/db/update/object_replace_executor.h"
#include "mongo/db/update/pipeline_executor.h"
#include "mongo/db/update/update_node_visitor.h"
#include "mongo/db/update/update_object_node.h"
+#include "mongo/db/update/update_tree_executor.h"
#include "mongo/db/update_index_data.h"
namespace mongo {
@@ -127,7 +128,17 @@ public:
* implementing methods that operate on the nodes of the tree.
*/
void visitRoot(UpdateNodeVisitor* visitor) {
- _updateExecutor->acceptVisitor(visitor);
+ if (_updateType == UpdateType::kOperator) {
+ UpdateTreeExecutor* exec = static_cast<UpdateTreeExecutor*>(_updateExecutor.get());
+ invariant(exec);
+ return exec->getUpdateTree()->acceptVisitor(visitor);
+ }
+
+ MONGO_UNREACHABLE;
+ }
+
+ UpdateExecutor* getUpdateExecutor() {
+ return _updateExecutor.get();
}
//
@@ -178,16 +189,7 @@ public:
* produce a logically equivalent update expression.
*/
Value serialize() const {
- switch (_updateType) {
- case UpdateType::kReplacement:
- return Value(static_cast<ObjectReplaceNode*>(_updateExecutor.get())->serialize());
- case UpdateType::kPipeline:
- return static_cast<PipelineExecutor*>(_updateExecutor.get())->serialize();
- case UpdateType::kOperator:
- return Value(static_cast<UpdateObjectNode*>(_updateExecutor.get())->serialize());
- default:
- MONGO_UNREACHABLE;
- }
+ return _updateExecutor->serialize();
}
/**
diff --git a/src/mongo/db/update/update_executor.h b/src/mongo/db/update/update_executor.h
index 0a3baf8779f..f7548b5b155 100644
--- a/src/mongo/db/update/update_executor.h
+++ b/src/mongo/db/update/update_executor.h
@@ -31,6 +31,7 @@
#include "mongo/bson/mutable/element.h"
#include "mongo/db/field_ref_set.h"
+#include "mongo/db/pipeline/value.h"
#include "mongo/db/update/log_builder.h"
#include "mongo/db/update/update_node_visitor.h"
#include "mongo/db/update_index_data.h"
@@ -102,27 +103,15 @@ public:
UpdateExecutor() = default;
virtual ~UpdateExecutor() = default;
- /**
- * Set the collation. This is a noop if the UpdateExecutor subclass does not require a collator.
- * If setCollator() is called, it is required that the current collator is the simple collator
- * (nullptr). The collator must outlive the modifier interface. This is used to override the
- * collation after obtaining a collection lock if the update did not specify a collation and the
- * collection has a non-simple default collation.
- */
- virtual void setCollator(const CollatorInterface* collator) = 0;
+ virtual Value serialize() const = 0;
+ virtual void setCollator(const CollatorInterface* collator){};
/**
* Applies the update to 'applyParams.element'. Returns an ApplyResult specifying whether the
* operation was a no-op and whether indexes are affected.
*/
virtual ApplyResult applyUpdate(ApplyParams applyParams) const = 0;
-
- /**
- * This allows an arbitrary class to implement logic which gets dispatched to at runtime
- * depending on the type of the UpdateExecutor.
- */
- virtual void acceptVisitor(UpdateNodeVisitor* visitor) = 0;
};
} // namespace mongo
diff --git a/src/mongo/db/update/update_node.h b/src/mongo/db/update/update_node.h
index 9b3bee195ae..cca2bea0105 100644
--- a/src/mongo/db/update/update_node.h
+++ b/src/mongo/db/update/update_node.h
@@ -49,6 +49,9 @@ namespace mongo {
class CollatorInterface;
class FieldRef;
+using ApplyParams = UpdateExecutor::ApplyParams;
+using ApplyResult = UpdateExecutor::ApplyResult;
+
/**
* Update modifier expressions are stored as a prefix tree of UpdateNodes, where two modifiers that
* share a field path prefix share a path prefix in the tree. The prefix tree is used to enforce
@@ -64,7 +67,7 @@ class FieldRef;
* b / \ c
* SetNode: _val = 5 IncNode: _val = 1
*/
-class UpdateNode : public UpdateExecutor {
+class UpdateNode {
public:
enum class Context { kAll, kInsertOnly };
enum class Type { Object, Array, Leaf, Replacement };
@@ -87,11 +90,6 @@ public:
virtual std::unique_ptr<UpdateNode> clone() const = 0;
- ApplyResult applyUpdate(ApplyParams applyParams) const final {
- UpdateNodeApplyParams updateNodeApplyParams;
- return apply(applyParams, updateNodeApplyParams);
- }
-
virtual ApplyResult apply(ApplyParams applyParams,
UpdateNodeApplyParams updateNodeApplyParams) const = 0;
@@ -120,6 +118,21 @@ public:
std::map<std::string, std::vector<std::pair<std::string, BSONObj>>>*
operatorOrientedUpdates) const = 0;
+ /**
+ * Set the collation. This is a noop if the UpdateExecutor subclass does not require a collator.
+ * If setCollator() is called, it is required that the current collator is the simple collator
+ * (nullptr). The collator must outlive the modifier interface. This is used to override the
+ * collation after obtaining a collection lock if the update did not specify a collation and the
+ * collection has a non-simple default collation.
+ */
+ virtual void setCollator(const CollatorInterface* collator) = 0;
+
+ /**
+ * This allows an arbitrary class to implement logic which gets dispatched to at runtime
+ * depending on the type of the UpdateExecutor.
+ */
+ virtual void acceptVisitor(UpdateNodeVisitor* visitor) = 0;
+
public:
const Context context;
const Type type;
diff --git a/src/mongo/db/update/update_node_test_fixture.h b/src/mongo/db/update/update_node_test_fixture.h
index 2f3506ea487..73953167ffc 100644
--- a/src/mongo/db/update/update_node_test_fixture.h
+++ b/src/mongo/db/update/update_node_test_fixture.h
@@ -45,7 +45,7 @@ protected:
void setUp() override {
resetApplyParams();
- // Set up the logical clock needed by CurrentDateNode and ObjectReplaceNode.
+ // Set up the logical clock needed by CurrentDateNode and ObjectReplaceExecutor.
auto service = mongo::getGlobalServiceContext();
auto logicalClock = mongo::stdx::make_unique<mongo::LogicalClock>(service);
mongo::LogicalClock::set(service, std::move(logicalClock));
diff --git a/src/mongo/db/update/update_node_visitor.h b/src/mongo/db/update/update_node_visitor.h
index 55ede3a0e64..39abf1f181a 100644
--- a/src/mongo/db/update/update_node_visitor.h
+++ b/src/mongo/db/update/update_node_visitor.h
@@ -39,8 +39,6 @@ class BitNode;
class CompareNode;
class ConflictPlaceholderNode;
class CurrentDateNode;
-class ObjectReplaceNode;
-class PipelineExecutor;
class PopNode;
class PullAllNode;
class PullNode;
@@ -72,8 +70,6 @@ public:
virtual void visit(CompareNode*) = 0;
virtual void visit(ConflictPlaceholderNode*) = 0;
virtual void visit(CurrentDateNode*) = 0;
- virtual void visit(ObjectReplaceNode*) = 0;
- virtual void visit(PipelineExecutor*) = 0;
virtual void visit(PopNode*) = 0;
virtual void visit(PullAllNode*) = 0;
virtual void visit(PullNode*) = 0;
diff --git a/src/mongo/db/update/update_tree_executor.h b/src/mongo/db/update/update_tree_executor.h
new file mode 100644
index 00000000000..e10bccc50c1
--- /dev/null
+++ b/src/mongo/db/update/update_tree_executor.h
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 2019-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+#include "mongo/db/update/update_executor.h"
+
+#include "mongo/db/update/update_node.h"
+#include "mongo/db/update/update_object_node.h"
+
+namespace mongo {
+
+class UpdateTreeExecutor : public UpdateExecutor {
+public:
+ explicit UpdateTreeExecutor(std::unique_ptr<UpdateObjectNode> node)
+ : _updateTree(std::move(node)) {}
+
+ ApplyResult applyUpdate(ApplyParams applyParams) const final {
+ UpdateNode::UpdateNodeApplyParams updateNodeApplyParams;
+ return _updateTree->apply(applyParams, updateNodeApplyParams);
+ }
+
+ UpdateNode* getUpdateTree() {
+ return static_cast<UpdateNode*>(_updateTree.get());
+ }
+
+ /**
+ * Gather all update operators in the subtree rooted from '_updateTree' into a BSONObj in the
+ * format of the update command's update parameter.
+ */
+ Value serialize() const final {
+ return Value(_updateTree->serialize());
+ }
+
+ void setCollator(const CollatorInterface* collator) final {
+ _updateTree->setCollator(collator);
+ }
+
+private:
+ std::unique_ptr<UpdateObjectNode> _updateTree;
+};
+
+} // namespace mongo