summaryrefslogtreecommitdiff
path: root/src/mongo/db/update
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
commit4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch)
tree1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/db/update
parentaa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff)
parent8f0827553e09872941945a093b647a4211a9db7f (diff)
Update upstream source from tag 'upstream/6.0.0'master
Update to upstream version '6.0.0' with Debian dir 5604a80ec1c96ca76f25f40d78e6ef855abec322
Diffstat (limited to 'src/mongo/db/update')
-rw-r--r--src/mongo/db/update/addtoset_node.cpp5
-rw-r--r--src/mongo/db/update/addtoset_node_test.cpp17
-rw-r--r--src/mongo/db/update/document_diff_calculator_test.cpp11
-rw-r--r--src/mongo/db/update/document_diff_serialization.cpp4
-rw-r--r--src/mongo/db/update/object_replace_executor.cpp17
-rw-r--r--src/mongo/db/update/object_replace_executor.h9
-rw-r--r--src/mongo/db/update/pipeline_executor.cpp4
-rw-r--r--src/mongo/db/update/pipeline_executor.h7
-rw-r--r--src/mongo/db/update/pipeline_executor_test.cpp40
-rw-r--r--src/mongo/db/update/storage_validation.cpp33
-rw-r--r--src/mongo/db/update/update_driver.cpp9
-rw-r--r--src/mongo/db/update/update_driver.h9
-rw-r--r--src/mongo/db/update/update_driver_test.cpp9
-rw-r--r--src/mongo/db/update/update_executor.h4
14 files changed, 37 insertions, 141 deletions
diff --git a/src/mongo/db/update/addtoset_node.cpp b/src/mongo/db/update/addtoset_node.cpp
index 824f6943c8e..f7b821815d1 100644
--- a/src/mongo/db/update/addtoset_node.cpp
+++ b/src/mongo/db/update/addtoset_node.cpp
@@ -85,10 +85,7 @@ Status AddToSetNode::init(BSONElement modExpr,
str::stream() << "Found unexpected fields after $each in $addToSet: "
<< modExpr.Obj());
}
-
- // We call 'ArrayVerifyIndexes' to uassert in the event that 'firstElement' is a
- // BSONArray with invalid indexes.
- _elements = firstElement.ArrayVerifyIndexes();
+ _elements = firstElement.Array();
}
}
diff --git a/src/mongo/db/update/addtoset_node_test.cpp b/src/mongo/db/update/addtoset_node_test.cpp
index f590c7140dc..d2b7f90be65 100644
--- a/src/mongo/db/update/addtoset_node_test.cpp
+++ b/src/mongo/db/update/addtoset_node_test.cpp
@@ -99,23 +99,6 @@ TEST(AddToSetNodeTest, InitSucceedsWithArray) {
ASSERT_OK(node.init(update["$addToSet"]["a"], expCtx));
}
-TEST(AddToSetNodeTest, InitFailsWhenArgumentIsInvalidBSONArray) {
- // Create our invalid array by creating a BSONObj with non contiguous array indexes that is then
- // passed to the BSONArray ctor.
- BSONObj updateArrAsObj = BSON("0"
- << "foo"
- << "2"
- << "bar");
- BSONArray updateArr(updateArrAsObj);
-
- auto update = BSON("$addToSet" << BSON("fieldName" << BSON("$each" << updateArr)));
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- AddToSetNode node;
-
- ASSERT_THROWS(node.init(update["$addToSet"]["fieldName"], expCtx),
- ExceptionFor<ErrorCodes::BadValue>);
-}
-
TEST(AddToSetNodeTest, InitSucceedsWithScaler) {
auto update = fromjson("{$addToSet: {a: 1}}");
boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
diff --git a/src/mongo/db/update/document_diff_calculator_test.cpp b/src/mongo/db/update/document_diff_calculator_test.cpp
index 5c83ac027c8..55a05051021 100644
--- a/src/mongo/db/update/document_diff_calculator_test.cpp
+++ b/src/mongo/db/update/document_diff_calculator_test.cpp
@@ -32,7 +32,6 @@
#include <functional>
#include "mongo/bson/bson_depth.h"
-#include "mongo/bson/bson_validate.h"
#include "mongo/bson/json.h"
#include "mongo/db/update/document_diff_calculator.h"
#include "mongo/unittest/unittest.h"
@@ -296,7 +295,7 @@ TEST(DocumentDiffCalculatorTest, DeeplyNestObjectGenerateDiff) {
preBob.append("largeField", largeValue);
buildDeepObj(&preBob, "subObj", 0, maxDepth, functionToApply);
auto preObj = preBob.done();
- ASSERT(validateBSON(preObj).isOK());
+ ASSERT(preObj.valid());
BSONObjBuilder postBob;
postBob.append("largeField", largeValue);
@@ -313,7 +312,7 @@ TEST(DocumentDiffCalculatorTest, DeeplyNestObjectGenerateDiff) {
// Deleting the deepest field should give the post object.
diffOutput = doc_diff::computeDiff(preObj, postBob2.done(), 0, nullptr);
ASSERT(diffOutput);
- ASSERT_OK(validateBSON(diffOutput->diff));
+ ASSERT(diffOutput->diff.valid());
BSONObjBuilder expectedOutputBuilder;
buildDeepObj(&expectedOutputBuilder,
@@ -342,17 +341,17 @@ TEST(DocumentDiffCalculatorTest, DeepestObjectSubDiff) {
value = 1;
buildDeepObj(&bob1, "subObj", 0, BSONDepth::getMaxDepthForUserStorage(), functionToApply);
auto preObj = bob1.done();
- ASSERT_OK(validateBSON(preObj));
+ ASSERT(preObj.valid());
BSONObjBuilder postBob;
value = 2;
buildDeepObj(&postBob, "subObj", 0, BSONDepth::getMaxDepthForUserStorage(), functionToApply);
auto postObj = postBob.done();
- ASSERT_OK(validateBSON(postObj));
+ ASSERT(postObj.valid());
auto diffOutput = doc_diff::computeDiff(preObj, postObj, 0, nullptr);
ASSERT(diffOutput);
- ASSERT_OK(validateBSON(diffOutput->diff));
+ ASSERT(diffOutput->diff.valid());
BSONObjBuilder expectedOutputBuilder;
buildDeepObj(&expectedOutputBuilder,
diff --git a/src/mongo/db/update/document_diff_serialization.cpp b/src/mongo/db/update/document_diff_serialization.cpp
index db3d4520e49..0f5533e1d06 100644
--- a/src/mongo/db/update/document_diff_serialization.cpp
+++ b/src/mongo/db/update/document_diff_serialization.cpp
@@ -80,9 +80,7 @@ Node* DocumentSubDiffNode::addChild(StringData fieldName, std::unique_ptr<Node>
sizeTracker.addEntry(fieldName.size(), nodePtr);
auto result = children.insert({fieldName.toString(), std::move(node)});
- uassert(7693400,
- str::stream() << "Document already has a field named '" << fieldName << "'",
- result.second);
+ invariant(result.second);
StringData storedFieldName = result.first->first;
switch (nodePtr->type()) {
case (NodeType::kArray):
diff --git a/src/mongo/db/update/object_replace_executor.cpp b/src/mongo/db/update/object_replace_executor.cpp
index 205b270a8ca..e2d9262e001 100644
--- a/src/mongo/db/update/object_replace_executor.cpp
+++ b/src/mongo/db/update/object_replace_executor.cpp
@@ -45,24 +45,19 @@ namespace {
constexpr StringData kIdFieldName = "_id"_sd;
} // namespace
-ObjectReplaceExecutor::ObjectReplaceExecutor(BSONObj replacement, bool bypassEmptyTsReplacement)
- : _replacementDoc(replacement.getOwned()),
- _containsId(false),
- _bypassEmptyTsReplacement(bypassEmptyTsReplacement) {
- // Check for the existence of the "_id" field, and if approrpriate replace all zero-valued
- // timestamps with the current time.
+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 : _replacementDoc) {
+
// Do not change the _id field.
if (elem.fieldNameStringData() == kIdFieldName) {
_containsId = true;
continue;
}
- // For updates that originated from the oplog, we're required to apply the update
- // exactly as it was recorded (even if it contains zero-valued timestamps). Therefore,
- // we should only replace zero-valued timestamps with the current time when
- // '_bypassEmptyTsReplacement' is false.
- if (!_bypassEmptyTsReplacement && elem.type() == BSONType::bsonTimestamp) {
+ if (elem.type() == BSONType::bsonTimestamp) {
auto timestampView = DataView(const_cast<char*>(elem.value()));
// We don't need to do an endian-safe read here, because 0 is 0 either way.
diff --git a/src/mongo/db/update/object_replace_executor.h b/src/mongo/db/update/object_replace_executor.h
index 3f4c787e588..f9c70bde919 100644
--- a/src/mongo/db/update/object_replace_executor.h
+++ b/src/mongo/db/update/object_replace_executor.h
@@ -65,11 +65,10 @@ public:
bool allowTopLevelDollarPrefixedFields = false);
/**
- * Initializes the node with the document to replace with. If 'bypassEmptyTsReplacement' is
- * false, any zero-valued timestamps (except for the _id) will be replaced with the current
- * time.
+ * Initializes the node with the document to replace with. Any zero-valued timestamps (except
+ * for the _id) are updated to the current time.
*/
- explicit ObjectReplaceExecutor(BSONObj replacement, bool bypassEmptyTsReplacement = false);
+ explicit ObjectReplaceExecutor(BSONObj replacement);
/**
* Replaces the document that 'applyParams.element' belongs to with 'val'. If 'val' does not
@@ -96,8 +95,6 @@ private:
// True if '_replacementDoc' contains an _id.
bool _containsId;
-
- bool _bypassEmptyTsReplacement = false;
};
} // namespace mongo
diff --git a/src/mongo/db/update/pipeline_executor.cpp b/src/mongo/db/update/pipeline_executor.cpp
index 7d99b3aecb3..710803d6b04 100644
--- a/src/mongo/db/update/pipeline_executor.cpp
+++ b/src/mongo/db/update/pipeline_executor.cpp
@@ -87,10 +87,6 @@ PipelineExecutor::PipelineExecutor(const boost::intrusive_ptr<ExpressionContext>
invariant(stageConstraints.requiredPosition ==
StageConstraints::PositionRequirement::kNone);
invariant(!stageConstraints.isIndependentOfAnyCollection);
-
- if (stageConstraints.checkExistenceForDiffInsertOperations) {
- _checkExistenceForDiffInsertOperations = true;
- }
}
_pipeline->addInitialSource(DocumentSourceQueue::create(expCtx));
diff --git a/src/mongo/db/update/pipeline_executor.h b/src/mongo/db/update/pipeline_executor.h
index 7569005de7d..e0b16b851c2 100644
--- a/src/mongo/db/update/pipeline_executor.h
+++ b/src/mongo/db/update/pipeline_executor.h
@@ -64,14 +64,7 @@ public:
Value serialize() const final;
- bool getCheckExistenceForDiffInsertOperations() const override final {
- return _checkExistenceForDiffInsertOperations;
- }
-
private:
- // Sets to true if the pipeline contains '$_internalApplyOplogUpdate'.
- bool _checkExistenceForDiffInsertOperations = false;
-
boost::intrusive_ptr<ExpressionContext> _expCtx;
std::unique_ptr<Pipeline, PipelineDeleter> _pipeline;
};
diff --git a/src/mongo/db/update/pipeline_executor_test.cpp b/src/mongo/db/update/pipeline_executor_test.cpp
index d237dd4f78e..c650e06749d 100644
--- a/src/mongo/db/update/pipeline_executor_test.cpp
+++ b/src/mongo/db/update/pipeline_executor_test.cpp
@@ -719,45 +719,5 @@ TEST_F(PipelineExecutorV2ModeTest, TestIndexesAffectedWithArraysAfterIndexPath)
}
}
-/**
- * Verifies the fix for SERVER-76934 in the case where the original document has a duplicate field.
- */
-TEST_F(PipelineExecutorV2ModeTest, TestIndexesAffectedWithArraysAfterIndexPath1) {
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- BSONObj preImage(
- fromjson("{f1: {paddingField: 'largeValueString'}, k: {c: 1, c: 2, paddingField: "
- "'largeValueString'}}"));
-
- auto doc = mutablebson::Document(preImage);
- const std::vector<BSONObj> pipeline{
- fromjson("{$replaceWith: {$literal: {f1: {paddingField: 'largeValueString'}, k: {c: 4, "
- "paddingField: 'largeValueString'}} }}")};
- PipelineExecutor exec(expCtx, pipeline);
- ASSERT_THROWS_CODE_AND_WHAT(exec.applyUpdate(getApplyParams(doc.root())),
- AssertionException,
- 7693400,
- "Document already has a field named 'c'");
-}
-
-/**
- * Verifies the fix for SERVER-76934 in the case where the pipeline tries to add a duplicate field.
- */
-TEST_F(PipelineExecutorV2ModeTest, TestIndexesAffectedWithArraysAfterIndexPath2) {
- boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest());
- BSONObj preImage(
- fromjson("{f1: {paddingField: 'largeValueString'}, k: {c: 1, paddingField: "
- "'largeValueString'}}"));
-
- auto doc = mutablebson::Document(preImage);
- const std::vector<BSONObj> pipeline{
- fromjson("{$replaceWith: {$literal: {f1: {paddingField: 'largeValueString'}, k: {c: 4, c: "
- "5, paddingField: 'largeValueString'}} }}")};
- PipelineExecutor exec(expCtx, pipeline);
- ASSERT_THROWS_CODE_AND_WHAT(exec.applyUpdate(getApplyParams(doc.root())),
- AssertionException,
- 7693400,
- "Document already has a field named 'c'");
-}
-
} // namespace
} // namespace mongo
diff --git a/src/mongo/db/update/storage_validation.cpp b/src/mongo/db/update/storage_validation.cpp
index 69967c14aef..d94c645a588 100644
--- a/src/mongo/db/update/storage_validation.cpp
+++ b/src/mongo/db/update/storage_validation.cpp
@@ -160,30 +160,19 @@ void scanDocument(const mutablebson::Document& doc,
auto currElem = doc.root().leftChild();
while (currElem.ok()) {
if (currElem.getFieldName() == idFieldName && shouldValidate) {
- if (currElem.getType() == BSONType::Object) {
- // We need to recursively validate the _id field while ensuring we disallow
- // top-level $-prefix fields in the _id object.
- scanDocument(currElem,
- true /* deep */,
- 0 /* recursionLevel - forces _id fields to be treated as top-level. */,
- false /* Top-level _id fields cannot be $-prefixed. */,
- shouldValidate,
- containsDotsAndDollarsField);
- } else {
- uassertStatusOK(storageValidIdField(currElem.getValue()));
- }
- } else {
- // Validate this child element.
- const auto deep = true;
- const uint32_t recursionLevel = 1;
- scanDocument(currElem,
- deep,
- recursionLevel,
- allowTopLevelDollarPrefixes,
- shouldValidate,
- containsDotsAndDollarsField);
+ uassertStatusOK(storageValidIdField(currElem.getValue()));
}
+ // Validate this child element.
+ const auto deep = true;
+ const uint32_t recursionLevel = 1;
+ scanDocument(currElem,
+ deep,
+ recursionLevel,
+ allowTopLevelDollarPrefixes,
+ shouldValidate,
+ containsDotsAndDollarsField);
+
currElem = currElem.rightSibling();
}
}
diff --git a/src/mongo/db/update/update_driver.cpp b/src/mongo/db/update/update_driver.cpp
index 9839487da9d..5ce9dc8aa84 100644
--- a/src/mongo/db/update/update_driver.cpp
+++ b/src/mongo/db/update/update_driver.cpp
@@ -159,14 +159,7 @@ void UpdateDriver::parse(
"multi update is not supported for replacement-style update",
!multi);
- // For updates that originated from the oplog, we're required to apply the update
- // exactly as it was recorded (even if it contains zero-valued timestamps). Therefore,
- // we should only replace zero-valued timestamps with the current time when both
- // '_bypassEmptyTsReplacement' and '_fromOplogApplication' are false.
- const bool bypassEmptyTsReplacement = _bypassEmptyTsReplacement || _fromOplogApplication;
-
- _updateExecutor = std::make_unique<ObjectReplaceExecutor>(updateMod.getUpdateReplacement(),
- bypassEmptyTsReplacement);
+ _updateExecutor = std::make_unique<ObjectReplaceExecutor>(updateMod.getUpdateReplacement());
// Register the fact that this driver will only do full object replacements.
_updateType = UpdateType::kReplacement;
diff --git a/src/mongo/db/update/update_driver.h b/src/mongo/db/update/update_driver.h
index 9949f43787c..94d1f73c8d4 100644
--- a/src/mongo/db/update/update_driver.h
+++ b/src/mongo/db/update/update_driver.h
@@ -195,13 +195,6 @@ public:
_containsDotsAndDollarsField = containsDotsAndDollarsField;
}
- bool bypassEmptyTsReplacement() const {
- return _bypassEmptyTsReplacement;
- }
- void setBypassEmptyTsReplacement(bool bypassEmptyTsReplacement) {
- _bypassEmptyTsReplacement = bypassEmptyTsReplacement;
- }
-
/**
* Serialize the update expression to Value. Output of this method is expected to, when parsed,
* produce a logically equivalent update expression.
@@ -245,8 +238,6 @@ private:
// True if this update comes from an oplog application.
bool _fromOplogApplication = false;
- bool _bypassEmptyTsReplacement = false;
-
// True if this update is guaranteed not to contain dots or dollars fields and should skip the
// check.
bool _skipDotsDollarsCheck = false;
diff --git a/src/mongo/db/update/update_driver_test.cpp b/src/mongo/db/update/update_driver_test.cpp
index 86f6ae492bf..2d03e4b7886 100644
--- a/src/mongo/db/update/update_driver_test.cpp
+++ b/src/mongo/db/update/update_driver_test.cpp
@@ -46,6 +46,15 @@
#include "mongo/db/update_index_data.h"
#include "mongo/unittest/unittest.h"
+#define ASSERT_DOES_NOT_THROW(EXPRESSION) \
+ try { \
+ EXPRESSION; \
+ } catch (const AssertionException& e) { \
+ ::mongo::str::stream err; \
+ err << "Threw an exception incorrectly: " << e.toString(); \
+ ::mongo::unittest::TestAssertionFailure(__FILE__, __LINE__, err).stream(); \
+ }
+
namespace mongo {
namespace {
diff --git a/src/mongo/db/update/update_executor.h b/src/mongo/db/update/update_executor.h
index a5f964e76ac..539f044432b 100644
--- a/src/mongo/db/update/update_executor.h
+++ b/src/mongo/db/update/update_executor.h
@@ -136,10 +136,6 @@ public:
virtual void setCollator(const CollatorInterface* collator){};
- virtual bool getCheckExistenceForDiffInsertOperations() const {
- return false;
- }
-
/**
* Applies the update to 'applyParams.element'. Returns an ApplyResult specifying whether the
* operation was a no-op and whether indexes are affected.