diff options
author | Ian Boros <ian.boros@mongodb.com> | 2020-08-13 14:08:58 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-08-27 03:08:04 +0000 |
commit | 3a32dd0a25105ba547712190ff503a46e91f392e (patch) | |
tree | 3bf333229d495a35ffde62aa0ace0e312a720352 /src/mongo | |
parent | 6791200c0513187dc193895af70cc170db9afc78 (diff) | |
download | mongo-3a32dd0a25105ba547712190ff503a46e91f392e.tar.gz |
SERVER-50217 change auth op observer to handle $v:1 and $v:2 updates
This commit also removes an implicit constructor for write_ops::UpdateModification.
Diffstat (limited to 'src/mongo')
38 files changed, 267 insertions, 143 deletions
diff --git a/src/mongo/db/auth/authz_manager_external_state_mock.cpp b/src/mongo/db/auth/authz_manager_external_state_mock.cpp index 57aee1183ea..00d479756a6 100644 --- a/src/mongo/db/auth/authz_manager_external_state_mock.cpp +++ b/src/mongo/db/auth/authz_manager_external_state_mock.cpp @@ -197,7 +197,8 @@ Status AuthzManagerExternalStateMock::updateOne(OperationContext* opCtx, new ExpressionContext(opCtx, std::unique_ptr<CollatorInterface>(nullptr), collectionName)); UpdateDriver driver(std::move(expCtx)); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - driver.parse(updatePattern, arrayFilters); + driver.parse(write_ops::UpdateModification::parseFromClassicUpdate(updatePattern), + arrayFilters); BSONObjCollection::iterator iter; Status status = _findOneIter(opCtx, collectionName, query, &iter); diff --git a/src/mongo/db/auth/role_graph_update.cpp b/src/mongo/db/auth/role_graph_update.cpp index f8945340274..85bf11e8de3 100644 --- a/src/mongo/db/auth/role_graph_update.cpp +++ b/src/mongo/db/auth/role_graph_update.cpp @@ -208,7 +208,7 @@ Status handleOplogUpdate(OperationContext* opCtx, // Oplog updates do not have array filters. std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - driver.parse(updatePattern, arrayFilters); + driver.parse(write_ops::UpdateModification::parseFromOplogEntry(updatePattern), arrayFilters); mutablebson::Document roleDocument; status = RoleGraph::getBSONForRole(roleGraph, roleToUpdate, roleDocument.root()); diff --git a/src/mongo/db/commands/oplog_application_checks.cpp b/src/mongo/db/commands/oplog_application_checks.cpp index 3cb9dafb0ac..3b7f96fc224 100644 --- a/src/mongo/db/commands/oplog_application_checks.cpp +++ b/src/mongo/db/commands/oplog_application_checks.cpp @@ -119,7 +119,8 @@ Status OplogApplicationChecks::checkOperationAuthorization(OperationContext* opC const bool upsert = b || alwaysUpsert; - return authSession->checkAuthForUpdate(opCtx, ns, o, o2, upsert); + return authSession->checkAuthForUpdate( + opCtx, ns, o2, write_ops::UpdateModification::parseFromOplogEntry(o), upsert); } else if (opType == "d"_sd) { return authSession->checkAuthForDelete(opCtx, ns, o); diff --git a/src/mongo/db/commands/rwc_defaults_commands.cpp b/src/mongo/db/commands/rwc_defaults_commands.cpp index 071227a941a..90f817f29c5 100644 --- a/src/mongo/db/commands/rwc_defaults_commands.cpp +++ b/src/mongo/db/commands/rwc_defaults_commands.cpp @@ -59,7 +59,7 @@ void updatePersistedDefaultRWConcernDocument(OperationContext* opCtx, const RWCo write_ops::UpdateOpEntry entry; entry.setQ(BSON("_id" << ReadWriteConcernDefaults::kPersistedDocumentId)); // Note the _id is propagated from the query into the upserted document. - entry.setU(rw.toBSON()); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(rw.toBSON())); entry.setUpsert(true); return entry; }()}); diff --git a/src/mongo/db/commands/user_management_commands.cpp b/src/mongo/db/commands/user_management_commands.cpp index 15b40b7ddc6..5694a2368cb 100644 --- a/src/mongo/db/commands/user_management_commands.cpp +++ b/src/mongo/db/commands/user_management_commands.cpp @@ -274,7 +274,8 @@ Status updateAuthzDocuments(OperationContext* opCtx, updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(updatePattern); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate( + updatePattern)); entry.setMulti(multi); entry.setUpsert(upsert); return entry; diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp index bf19f4bd8bf..36b034e0b05 100644 --- a/src/mongo/db/dbhelpers.cpp +++ b/src/mongo/db/dbhelpers.cpp @@ -245,7 +245,7 @@ void Helpers::upsert(OperationContext* opCtx, request.setNamespaceString(requestNs); request.setQuery(filter); - request.setUpdateModification(updateMod); + request.setUpdateModification(write_ops::UpdateModification::parseFromClassicUpdate(updateMod)); request.setUpsert(); request.setFromMigration(fromMigrate); request.setYieldPolicy(PlanYieldPolicy::YieldPolicy::NO_YIELD); @@ -260,7 +260,7 @@ void Helpers::putSingleton(OperationContext* opCtx, const char* ns, BSONObj obj) auto request = UpdateRequest(); request.setNamespaceString(requestNs); - request.setUpdateModification(obj); + request.setUpdateModification(write_ops::UpdateModification::parseFromClassicUpdate(obj)); request.setUpsert(); update(opCtx, context.db(), request); diff --git a/src/mongo/db/exec/upsert_stage.cpp b/src/mongo/db/exec/upsert_stage.cpp index 831946beed0..a0fd31ca201 100644 --- a/src/mongo/db/exec/upsert_stage.cpp +++ b/src/mongo/db/exec/upsert_stage.cpp @@ -247,7 +247,7 @@ void UpsertStage::_generateNewDocumentFromSuppliedDoc(const FieldRefSet& immutab UpdateDriver replacementDriver(nullptr); // Create a new replacement-style update from the supplied document. - replacementDriver.parse({suppliedDoc}, {}); + replacementDriver.parse(write_ops::UpdateModification::parseFromClassicUpdate(suppliedDoc), {}); replacementDriver.setLogOp(false); // We do not validate for storage, as we will validate the full document before inserting. diff --git a/src/mongo/db/ops/write_ops_parsers.cpp b/src/mongo/db/ops/write_ops_parsers.cpp index 5e0faf1ae8e..1d70e93019a 100644 --- a/src/mongo/db/ops/write_ops_parsers.cpp +++ b/src/mongo/db/ops/write_ops_parsers.cpp @@ -236,7 +236,7 @@ write_ops::UpdateModification write_ops::UpdateModification::parseFromOplogEntry // Treat it as a "classic" update which can either be a full replacement or a // modifier-style update. Which variant it is will be determined when the update driver is // constructed. - return UpdateModification(oField); + return UpdateModification(oField, ClassicTag{}); } // The $v field must be present, but have some unsupported value. @@ -262,7 +262,7 @@ write_ops::UpdateModification::UpdateModification(BSONElement update) { _update = PipelineUpdate{uassertStatusOK(AggregationRequest::parsePipelineFromBSON(update))}; } -write_ops::UpdateModification::UpdateModification(const BSONObj& update) { +write_ops::UpdateModification::UpdateModification(const BSONObj& update, ClassicTag) { // Do a sanity check that the $v field is either not provided or has value of 1. const auto versionElem = update["$v"]; uassert(4772602, @@ -284,7 +284,7 @@ write_ops::UpdateModification write_ops::UpdateModification::parseFromBSON(BSONE write_ops::UpdateModification write_ops::UpdateModification::parseLegacyOpUpdateFromBSON( const BSONObj& obj) { - return UpdateModification(obj); + return UpdateModification(obj, ClassicTag{}); } int write_ops::UpdateModification::objsize() const { diff --git a/src/mongo/db/ops/write_ops_parsers.h b/src/mongo/db/ops/write_ops_parsers.h index 0464a3349df..937b5853912 100644 --- a/src/mongo/db/ops/write_ops_parsers.h +++ b/src/mongo/db/ops/write_ops_parsers.h @@ -60,20 +60,27 @@ public: enum class Type { kClassic, kPipeline, kDelta }; /** - * Used to indicate that a diff is being passed to the constructor. + * Used to indicate that a certain type of update is being passed to the constructor. */ struct DiffTag {}; + struct ClassicTag {}; // Given the 'o' field of an update oplog entry, will return an UpdateModification that can be // applied. static UpdateModification parseFromOplogEntry(const BSONObj& oField); + static UpdateModification parseFromClassicUpdate(const BSONObj& modifiers) { + return UpdateModification(modifiers, ClassicTag{}); + } + static UpdateModification parseFromV2Delta(const doc_diff::Diff& diff) { + return UpdateModification(diff, DiffTag{}); + } UpdateModification() = default; UpdateModification(BSONElement update); UpdateModification(std::vector<BSONObj> pipeline); UpdateModification(doc_diff::Diff, DiffTag); // This constructor exists only to provide a fast-path for constructing classic-style updates. - UpdateModification(const BSONObj& update); + UpdateModification(const BSONObj& update, ClassicTag); /** * These methods support IDL parsing of the "u" field from the update command and OP_UPDATE. diff --git a/src/mongo/db/ops/write_ops_retryability_test.cpp b/src/mongo/db/ops/write_ops_retryability_test.cpp index 4d70242b31f..276eaf1040c 100644 --- a/src/mongo/db/ops/write_ops_retryability_test.cpp +++ b/src/mongo/db/ops/write_ops_retryability_test.cpp @@ -176,7 +176,8 @@ protected: const NamespaceString kNs("test.user"); TEST_F(FindAndModifyRetryability, BasicUpsertReturnNew) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setUpsert(true); request.setShouldReturnNew(true); @@ -199,7 +200,8 @@ TEST_F(FindAndModifyRetryability, BasicUpsertReturnNew) { } TEST_F(FindAndModifyRetryability, BasicUpsertReturnOld) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setUpsert(true); request.setShouldReturnNew(false); @@ -219,7 +221,8 @@ TEST_F(FindAndModifyRetryability, BasicUpsertReturnOld) { } TEST_F(FindAndModifyRetryability, NestedUpsert) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setUpsert(true); request.setShouldReturnNew(true); @@ -241,7 +244,8 @@ TEST_F(FindAndModifyRetryability, NestedUpsert) { } TEST_F(FindAndModifyRetryability, AttemptingToRetryUpsertWithUpdateWithoutUpsertErrors) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setUpsert(false); auto insertOplog = makeOplogEntry(repl::OpTime(), // optime @@ -254,7 +258,8 @@ TEST_F(FindAndModifyRetryability, AttemptingToRetryUpsertWithUpdateWithoutUpsert } TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPostImageButOplogHasPre) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(true); repl::OpTime imageOpTime(Timestamp(120, 3), 1); @@ -278,7 +283,8 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPostImageButOplogHasPre) { } TEST_F(FindAndModifyRetryability, ErrorIfRequestIsUpdateButOplogIsDelete) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(true); repl::OpTime imageOpTime(Timestamp(120, 3), 1); @@ -301,7 +307,8 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsUpdateButOplogIsDelete) { } TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPreImageButOplogHasPost) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(false); repl::OpTime imageOpTime(Timestamp(120, 3), 1); @@ -325,7 +332,8 @@ TEST_F(FindAndModifyRetryability, ErrorIfRequestIsPreImageButOplogHasPost) { } TEST_F(FindAndModifyRetryability, UpdateWithPreImage) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(false); repl::OpTime imageOpTime(Timestamp(120, 3), 1); @@ -351,7 +359,8 @@ TEST_F(FindAndModifyRetryability, UpdateWithPreImage) { } TEST_F(FindAndModifyRetryability, NestedUpdateWithPreImage) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(false); repl::OpTime imageOpTime(Timestamp(120, 3), 1); @@ -383,7 +392,8 @@ TEST_F(FindAndModifyRetryability, NestedUpdateWithPreImage) { } TEST_F(FindAndModifyRetryability, UpdateWithPostImage) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(true); repl::OpTime imageOpTime(Timestamp(120, 3), 1); @@ -409,7 +419,8 @@ TEST_F(FindAndModifyRetryability, UpdateWithPostImage) { } TEST_F(FindAndModifyRetryability, NestedUpdateWithPostImage) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(true); repl::OpTime imageOpTime(Timestamp(120, 3), 1); @@ -441,7 +452,8 @@ TEST_F(FindAndModifyRetryability, NestedUpdateWithPostImage) { } TEST_F(FindAndModifyRetryability, UpdateWithPostImageButOplogDoesNotExistShouldError) { - auto request = FindAndModifyRequest::makeUpdate(kNs, BSONObj(), BSONObj()); + auto request = FindAndModifyRequest::makeUpdate( + kNs, BSONObj(), write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); request.setShouldReturnNew(true); repl::OpTime imageOpTime(Timestamp(120, 3), 1); diff --git a/src/mongo/db/persistent_task_store.h b/src/mongo/db/persistent_task_store.h index 4b0b25af5f6..3c256144f8e 100644 --- a/src/mongo/db/persistent_task_store.h +++ b/src/mongo/db/persistent_task_store.h @@ -87,7 +87,7 @@ public: auto commandResponse = dbClient.runCommand([&] { write_ops::Update updateOp(_storageNss); - write_ops::UpdateModification updateModification(update); + auto updateModification = write_ops::UpdateModification::parseFromClassicUpdate(update); write_ops::UpdateOpEntry updateEntry(query.obj, updateModification); updateEntry.setMulti(false); updateEntry.setUpsert(upsert); diff --git a/src/mongo/db/pipeline/document_source_merge.cpp b/src/mongo/db/pipeline/document_source_merge.cpp index 2b8223d8753..72e3089bd71 100644 --- a/src/mongo/db/pipeline/document_source_merge.cpp +++ b/src/mongo/db/pipeline/document_source_merge.cpp @@ -148,8 +148,8 @@ MergeStrategy makeInsertStrategy() { BatchTransform makeUpdateTransform(const std::string& updateOp) { return [updateOp](auto& batch) { for (auto&& obj : batch) { - std::get<UpdateModification>(obj) = - BSON(updateOp << std::get<UpdateModification>(obj).getUpdateClassic()); + std::get<UpdateModification>(obj) = UpdateModification::parseFromClassicUpdate( + BSON(updateOp << std::get<UpdateModification>(obj).getUpdateClassic())); } }; } diff --git a/src/mongo/db/pipeline/document_source_merge.h b/src/mongo/db/pipeline/document_source_merge.h index 6d88c77fefa..f3c76be7e2f 100644 --- a/src/mongo/db/pipeline/document_source_merge.h +++ b/src/mongo/db/pipeline/document_source_merge.h @@ -159,7 +159,7 @@ private: */ auto makeBatchUpdateModification(const Document& doc) const { return _pipeline ? write_ops::UpdateModification(*_pipeline) - : write_ops::UpdateModification(doc.toBson()); + : write_ops::UpdateModification::parseFromClassicUpdate(doc.toBson()); } /** diff --git a/src/mongo/db/query/find_and_modify_request.cpp b/src/mongo/db/query/find_and_modify_request.cpp index 582f4753d13..9f2a5e6d192 100644 --- a/src/mongo/db/query/find_and_modify_request.cpp +++ b/src/mongo/db/query/find_and_modify_request.cpp @@ -367,7 +367,7 @@ void FindAndModifyRequest::setQuery(BSONObj query) { _query = query.getOwned(); } void FindAndModifyRequest::setUpdateObj(BSONObj updateObj) { - _update.emplace(updateObj.getOwned()); + _update.emplace(write_ops::UpdateModification::parseFromClassicUpdate(updateObj.getOwned())); } void FindAndModifyRequest::setShouldReturnNew(bool shouldReturnNew) { diff --git a/src/mongo/db/query/find_and_modify_request_test.cpp b/src/mongo/db/query/find_and_modify_request_test.cpp index f9f01b82769..115e0e25178 100644 --- a/src/mongo/db/query/find_and_modify_request_test.cpp +++ b/src/mongo/db/query/find_and_modify_request_test.cpp @@ -41,7 +41,10 @@ namespace { TEST(FindAndModifyRequest, BasicUpdate) { const BSONObj query(BSON("x" << 1)); const BSONObj update(BSON("y" << 1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); BSONObj expectedObj(fromjson(R"json({ findAndModify: 'user', @@ -71,7 +74,10 @@ TEST(FindAndModifyRequest, PipelineUpdate) { TEST(FindAndModifyRequest, UpdateWithUpsert) { const BSONObj query(BSON("x" << 1)); const BSONObj update(BSON("y" << 1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setUpsert(true); BSONObj expectedObj(fromjson(R"json({ @@ -87,7 +93,10 @@ TEST(FindAndModifyRequest, UpdateWithUpsert) { TEST(FindAndModifyRequest, UpdateWithUpsertFalse) { const BSONObj query(BSON("x" << 1)); const BSONObj update(BSON("y" << 1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setUpsert(false); BSONObj expectedObj(fromjson(R"json({ @@ -104,7 +113,10 @@ TEST(FindAndModifyRequest, UpdateWithProjection) { const BSONObj update(BSON("y" << 1)); const BSONObj field(BSON("z" << 1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setFieldProjection(field); BSONObj expectedObj(fromjson(R"json({ @@ -121,7 +133,10 @@ TEST(FindAndModifyRequest, UpdateWithNewTrue) { const BSONObj query(BSON("x" << 1)); const BSONObj update(BSON("y" << 1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setShouldReturnNew(true); BSONObj expectedObj(fromjson(R"json({ @@ -138,7 +153,10 @@ TEST(FindAndModifyRequest, UpdateWithNewFalse) { const BSONObj query(BSON("x" << 1)); const BSONObj update(BSON("y" << 1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setShouldReturnNew(false); BSONObj expectedObj(fromjson(R"json({ @@ -155,7 +173,10 @@ TEST(FindAndModifyRequest, UpdateWithSort) { const BSONObj update(BSON("y" << 1)); const BSONObj sort(BSON("z" << -1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setSort(sort); BSONObj expectedObj(fromjson(R"json({ @@ -173,7 +194,10 @@ TEST(FindAndModifyRequest, UpdateWithHint) { const BSONObj update(BSON("y" << 1)); const BSONObj hint(BSON("z" << -1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setHint(hint); BSONObj expectedObj(fromjson(R"json({ @@ -192,7 +216,10 @@ TEST(FindAndModifyRequest, UpdateWithCollation) { const BSONObj collation(BSON("locale" << "en_US")); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setCollation(collation); BSONObj expectedObj(fromjson(R"json({ @@ -210,7 +237,10 @@ TEST(FindAndModifyRequest, UpdateWithArrayFilters) { const BSONObj update(BSON("y" << 1)); const std::vector<BSONObj> arrayFilters{BSON("i" << 0)}; - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setArrayFilters(arrayFilters); BSONObj expectedObj(fromjson(R"json({ @@ -228,7 +258,10 @@ TEST(FindAndModifyRequest, UpdateWithWriteConcern) { const BSONObj update(BSON("y" << 1)); const WriteConcernOptions writeConcern(2, WriteConcernOptions::SyncMode::FSYNC, 150); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setWriteConcern(writeConcern); BSONObj expectedObj(fromjson(R"json({ @@ -245,7 +278,10 @@ TEST(FindAndModifyRequest, UpdateWithRuntimeConstants) { const BSONObj query(BSON("x" << 1)); const BSONObj update(BSON("y" << 1)); - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setRuntimeConstants({Date_t(), Timestamp(1, 0)}); BSONObj expectedObj(fromjson(R"json({ @@ -273,7 +309,10 @@ TEST(FindAndModifyRequest, UpdateWithFullSpec) { const WriteConcernOptions writeConcern(2, WriteConcernOptions::SyncMode::FSYNC, 150); auto rtc = RuntimeConstants{Date_t(), Timestamp(1, 0)}; - auto request = FindAndModifyRequest::makeUpdate(NamespaceString("test.user"), query, update); + auto request = FindAndModifyRequest::makeUpdate( + NamespaceString("test.user"), + query, + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setFieldProjection(field); request.setShouldReturnNew(true); request.setSort(sort); diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 78bc154592f..7a0a79476e0 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -1196,7 +1196,8 @@ Status applyOperation_inlock(OperationContext* opCtx, auto request = UpdateRequest(); request.setNamespaceString(requestNss); request.setQuery(b.done()); - request.setUpdateModification(o); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(o)); request.setUpsert(); request.setFromOplogApplication(true); diff --git a/src/mongo/db/repl/rs_rollback.cpp b/src/mongo/db/repl/rs_rollback.cpp index e74f850acfb..fb186e4192c 100644 --- a/src/mongo/db/repl/rs_rollback.cpp +++ b/src/mongo/db/repl/rs_rollback.cpp @@ -1863,7 +1863,8 @@ void rollback_internal::syncFixUp(OperationContext* opCtx, request.setNamespaceString(*nss); request.setQuery(pattern); - request.setUpdateModification(idAndDoc.second); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(idAndDoc.second)); request.setGod(); request.setUpsert(); diff --git a/src/mongo/db/repl/storage_interface_impl.cpp b/src/mongo/db/repl/storage_interface_impl.cpp index a6e9efc5011..08269bdfaad 100644 --- a/src/mongo/db/repl/storage_interface_impl.cpp +++ b/src/mongo/db/repl/storage_interface_impl.cpp @@ -975,7 +975,8 @@ Status StorageInterfaceImpl::upsertById(OperationContext* opCtx, auto request = UpdateRequest(); request.setNamespaceString(collection->ns()); request.setQuery(query); - request.setUpdateModification(update); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(update)); request.setUpsert(true); invariant(!request.isMulti()); // This follows from using an exact _id query. invariant(!request.shouldReturnAnyDocs()); @@ -1025,7 +1026,8 @@ Status StorageInterfaceImpl::putSingleton(OperationContext* opCtx, auto request = UpdateRequest(); request.setNamespaceString(nss); request.setQuery({}); - request.setUpdateModification(update.obj); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(update.obj)); request.setUpsert(true); return _updateWithQuery(opCtx, request, update.timestamp); } @@ -1037,7 +1039,8 @@ Status StorageInterfaceImpl::updateSingleton(OperationContext* opCtx, auto request = UpdateRequest(); request.setNamespaceString(nss); request.setQuery(query); - request.setUpdateModification(update.obj); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(update.obj)); invariant(!request.isUpsert()); return _updateWithQuery(opCtx, request, update.timestamp); } diff --git a/src/mongo/db/s/add_shard_util.cpp b/src/mongo/db/s/add_shard_util.cpp index 0dae94c0102..d1b9b6da219 100644 --- a/src/mongo/db/s/add_shard_util.cpp +++ b/src/mongo/db/s/add_shard_util.cpp @@ -65,7 +65,8 @@ BSONObj createShardIdentityUpsertForAddShard(const AddShard& addShardCmd) { updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(BSON("_id" << kShardIdentityDocumentId)); - entry.setU(addShardCmd.getShardIdentity().toBSON()); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate( + addShardCmd.getShardIdentity().toBSON())); entry.setUpsert(true); return entry; }()}); diff --git a/src/mongo/db/s/config/config_server_test_fixture.cpp b/src/mongo/db/s/config/config_server_test_fixture.cpp index 964bdb97428..8710cb63fcd 100644 --- a/src/mongo/db/s/config/config_server_test_fixture.cpp +++ b/src/mongo/db/s/config/config_server_test_fixture.cpp @@ -233,22 +233,23 @@ Status ConfigServerTestFixture::updateToConfigCollection(OperationContext* opCtx const BSONObj& query, const BSONObj& update, const bool upsert) { - auto updateResponse = getConfigShard()->runCommand(opCtx, - kReadPref, - ns.db().toString(), - [&]() { - write_ops::Update updateOp(ns); - updateOp.setUpdates({[&] { - write_ops::UpdateOpEntry entry; - entry.setQ(query); - entry.setU(update); - entry.setUpsert(upsert); - return entry; - }()}); - return updateOp.toBSON({}); - }(), - Shard::kDefaultConfigCommandTimeout, - Shard::RetryPolicy::kNoRetry); + auto updateResponse = getConfigShard()->runCommand( + opCtx, + kReadPref, + ns.db().toString(), + [&]() { + write_ops::Update updateOp(ns); + updateOp.setUpdates({[&] { + write_ops::UpdateOpEntry entry; + entry.setQ(query); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(update)); + entry.setUpsert(upsert); + return entry; + }()}); + return updateOp.toBSON({}); + }(), + Shard::kDefaultConfigCommandTimeout, + Shard::RetryPolicy::kNoRetry); BatchedCommandResponse batchResponse; diff --git a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp index 43ca6be9c7c..d6544e922d2 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_collection_operations.cpp @@ -152,7 +152,7 @@ Status updateConfigDocumentInTxn(OperationContext* opCtx, updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(update); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(update)); entry.setUpsert(upsert); entry.setMulti(useMultiUpdate); return entry; diff --git a/src/mongo/db/s/migration_util.cpp b/src/mongo/db/s/migration_util.cpp index 95b16ea0254..83eff60f19d 100644 --- a/src/mongo/db/s/migration_util.cpp +++ b/src/mongo/db/s/migration_util.cpp @@ -667,8 +667,9 @@ void markAsReadyRangeDeletionTaskOnRecipient(OperationContext* opCtx, const UUID& migrationId) { write_ops::Update updateOp(NamespaceString::kRangeDeletionNamespace); auto queryFilter = BSON(RangeDeletionTask::kIdFieldName << migrationId); - auto updateModification = write_ops::UpdateModification( - BSON("$unset" << BSON(RangeDeletionTask::kPendingFieldName << ""))); + auto updateModification = + write_ops::UpdateModification(write_ops::UpdateModification::parseFromClassicUpdate( + BSON("$unset" << BSON(RangeDeletionTask::kPendingFieldName << "")))); write_ops::UpdateOpEntry updateEntry(queryFilter, updateModification); updateEntry.setMulti(false); updateEntry.setUpsert(false); @@ -700,7 +701,8 @@ void advanceTransactionOnRecipient(OperationContext* opCtx, write_ops::Update updateOp(NamespaceString::kServerConfigurationNamespace); auto queryFilter = BSON("_id" << "migrationCoordinatorStats"); - auto updateModification = write_ops::UpdateModification(BSON("$inc" << BSON("count" << 1))); + auto updateModification = write_ops::UpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(BSON("$inc" << BSON("count" << 1)))); write_ops::UpdateOpEntry updateEntry(queryFilter, updateModification); updateEntry.setMulti(false); diff --git a/src/mongo/db/s/resharding/resharding_coordinator_service.cpp b/src/mongo/db/s/resharding/resharding_coordinator_service.cpp index f21e90ccb9f..f43d6c0e031 100644 --- a/src/mongo/db/s/resharding/resharding_coordinator_service.cpp +++ b/src/mongo/db/s/resharding/resharding_coordinator_service.cpp @@ -248,7 +248,8 @@ void ReshardingCoordinatorService::ReshardingCoordinator::_runUpdates( updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(_id); - entry.setU(updatedStateDoc.toBSON()); + entry.setU( + write_ops::UpdateModification::parseFromClassicUpdate(updatedStateDoc.toBSON())); return entry; }()}); return updateOp.serialize( diff --git a/src/mongo/db/s/shard_local_test.cpp b/src/mongo/db/s/shard_local_test.cpp index d7314c965cf..4945d7a1c04 100644 --- a/src/mongo/db/s/shard_local_test.cpp +++ b/src/mongo/db/s/shard_local_test.cpp @@ -100,7 +100,8 @@ void ShardLocalTest::tearDown() { StatusWith<Shard::CommandResponse> ShardLocalTest::runFindAndModifyRunCommand(NamespaceString nss, BSONObj find, BSONObj set) { - FindAndModifyRequest findAndModifyRequest = FindAndModifyRequest::makeUpdate(nss, find, set); + FindAndModifyRequest findAndModifyRequest = FindAndModifyRequest::makeUpdate( + nss, find, write_ops::UpdateModification::parseFromClassicUpdate(set)); findAndModifyRequest.setUpsert(true); findAndModifyRequest.setShouldReturnNew(true); findAndModifyRequest.setWriteConcern(WriteConcernOptions( diff --git a/src/mongo/db/s/shard_metadata_util.cpp b/src/mongo/db/s/shard_metadata_util.cpp index b9f369a7d69..c5f96374520 100644 --- a/src/mongo/db/s/shard_metadata_util.cpp +++ b/src/mongo/db/s/shard_metadata_util.cpp @@ -228,7 +228,7 @@ Status updateShardCollectionsEntry(OperationContext* opCtx, updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(builder.obj()); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(builder.obj())); entry.setUpsert(upsert); return entry; }()}); @@ -271,7 +271,7 @@ Status updateShardDatabasesEntry(OperationContext* opCtx, updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(builder.obj()); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(builder.obj())); entry.setUpsert(upsert); return entry; }()}); diff --git a/src/mongo/db/s/sharding_initialization_mongod.cpp b/src/mongo/db/s/sharding_initialization_mongod.cpp index 2012a41690b..0e0fb8d6de0 100644 --- a/src/mongo/db/s/sharding_initialization_mongod.cpp +++ b/src/mongo/db/s/sharding_initialization_mongod.cpp @@ -468,7 +468,8 @@ void ShardingInitializationMongoD::updateShardIdentityConfigString( auto updateReq = UpdateRequest(); updateReq.setNamespaceString(NamespaceString::kServerConfigurationNamespace); updateReq.setQuery(BSON("_id" << ShardIdentityType::IdName)); - updateReq.setUpdateModification(updateObj); + updateReq.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(updateObj)); try { AutoGetOrCreateDb autoDb( diff --git a/src/mongo/db/s/sharding_state_recovery.cpp b/src/mongo/db/s/sharding_state_recovery.cpp index 9ef5345f44a..b2628aa3334 100644 --- a/src/mongo/db/s/sharding_state_recovery.cpp +++ b/src/mongo/db/s/sharding_state_recovery.cpp @@ -160,7 +160,8 @@ Status modifyRecoveryDocument(OperationContext* opCtx, auto updateReq = UpdateRequest(); updateReq.setNamespaceString(NamespaceString::kServerConfigurationNamespace); updateReq.setQuery(RecoveryDocument::getQuery()); - updateReq.setUpdateModification(updateObj); + updateReq.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(updateObj)); updateReq.setUpsert(); UpdateResult result = update(opCtx, autoGetOrCreateDb->getDb(), updateReq); diff --git a/src/mongo/db/s/transaction_coordinator_util.cpp b/src/mongo/db/s/transaction_coordinator_util.cpp index e682b5c56d1..0e1cfa83006 100644 --- a/src/mongo/db/s/transaction_coordinator_util.cpp +++ b/src/mongo/db/s/transaction_coordinator_util.cpp @@ -145,7 +145,7 @@ repl::OpTime persistParticipantListBlocking(OperationContext* opCtx, TransactionCoordinatorDocument doc; doc.setId(std::move(sessionInfo)); doc.setParticipants(std::move(participantList)); - entry.setU(doc.toBSON()); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(doc.toBSON())); entry.setUpsert(true); return entry; @@ -337,13 +337,13 @@ repl::OpTime persistDecisionBlocking(OperationContext* opCtx, << buildParticipantListMatchesConditions(participantList) << "$or" << BSON_ARRAY(noDecision << sameDecision))); - entry.setU([&] { + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate([&] { TransactionCoordinatorDocument doc; doc.setId(sessionInfo); doc.setParticipants(std::move(participantList)); doc.setDecision(decision); return doc.toBSON(); - }()); + }())); return entry; }()}); diff --git a/src/mongo/db/transaction_participant.cpp b/src/mongo/db/transaction_participant.cpp index d90a57692eb..f4e650b47f3 100644 --- a/src/mongo/db/transaction_participant.cpp +++ b/src/mongo/db/transaction_participant.cpp @@ -2355,7 +2355,8 @@ UpdateRequest TransactionParticipant::Participant::_makeUpdateRequest( auto updateRequest = UpdateRequest(); updateRequest.setNamespaceString(NamespaceString::kSessionTransactionsTableNamespace); - updateRequest.setUpdateModification(sessionTxnRecord.toBSON()); + updateRequest.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(sessionTxnRecord.toBSON())); updateRequest.setQuery(BSON(SessionTxnRecord::kSessionIdFieldName << _sessionId().toBSON())); updateRequest.setUpsert(true); diff --git a/src/mongo/db/update/update_driver_test.cpp b/src/mongo/db/update/update_driver_test.cpp index f490fec9a24..f93d5343661 100644 --- a/src/mongo/db/update/update_driver_test.cpp +++ b/src/mongo/db/update/update_driver_test.cpp @@ -62,11 +62,15 @@ namespace { using str::stream; using unittest::assertGet; +write_ops::UpdateModification makeUpdateMod(const BSONObj& bson) { + return write_ops::UpdateModification::parseFromClassicUpdate(bson); +} + TEST(Parse, Normal) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1}}"), arrayFilters)); + ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(fromjson("{$set:{a:1}}")), arrayFilters)); ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement); } @@ -74,7 +78,7 @@ TEST(Parse, MultiMods) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1, b:1}}"), arrayFilters)); + ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(fromjson("{$set:{a:1, b:1}}")), arrayFilters)); ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement); } @@ -82,7 +86,8 @@ TEST(Parse, MixingMods) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set:{a:1}, $unset:{b:1}}"), arrayFilters)); + ASSERT_DOES_NOT_THROW( + driver.parse(makeUpdateMod(fromjson("{$set:{a:1}, $unset:{b:1}}")), arrayFilters)); ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement); } @@ -90,7 +95,8 @@ TEST(Parse, ObjectReplacment) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{obj: \"obj replacement\"}"), arrayFilters)); + ASSERT_DOES_NOT_THROW( + driver.parse(makeUpdateMod(fromjson("{obj: \"obj replacement\"}")), arrayFilters)); ASSERT_TRUE(driver.type() == UpdateDriver::UpdateType::kReplacement); } @@ -122,14 +128,14 @@ TEST(Parse, EmptyMod) { UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; // Verifies that {$set: {}} is accepted. - ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$set: {}}"), arrayFilters)); + ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(fromjson("{$set: {}}")), arrayFilters)); } TEST(Parse, WrongMod) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_THROWS_CODE_AND_WHAT(driver.parse(fromjson("{$xyz:{a:1}}"), arrayFilters), + ASSERT_THROWS_CODE_AND_WHAT(driver.parse(makeUpdateMod(fromjson("{$xyz:{a:1}}")), arrayFilters), AssertionException, ErrorCodes::FailedToParse, "Unknown modifier: $xyz. Expected a valid update modifier or " @@ -140,11 +146,12 @@ TEST(Parse, WrongType) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_THROWS_CODE_AND_WHAT(driver.parse(fromjson("{$set:[{a:1}]}"), arrayFilters), - AssertionException, - ErrorCodes::FailedToParse, - "Modifiers operate on fields but we found type array instead. For " - "example: {$mod: {<field>: ...}} not {$set: [ { a: 1 } ]}"); + ASSERT_THROWS_CODE_AND_WHAT( + driver.parse(makeUpdateMod(fromjson("{$set:[{a:1}]}")), arrayFilters), + AssertionException, + ErrorCodes::FailedToParse, + "Modifiers operate on fields but we found type array instead. For " + "example: {$mod: {<field>: ...}} not {$set: [ { a: 1 } ]}"); } TEST(Parse, ModsWithLaterObjReplacement) { @@ -152,7 +159,8 @@ TEST(Parse, ModsWithLaterObjReplacement) { UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; ASSERT_THROWS_CODE_AND_WHAT( - driver.parse(fromjson("{$set:{a:1}, obj: \"obj replacement\"}"), arrayFilters), + driver.parse(makeUpdateMod(fromjson("{$set:{a:1}, obj: \"obj replacement\"}")), + arrayFilters), AssertionException, ErrorCodes::FailedToParse, "Unknown modifier: obj. Expected a valid update modifier or pipeline-style update " @@ -163,7 +171,8 @@ TEST(Parse, SetOnInsert) { boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_DOES_NOT_THROW(driver.parse(fromjson("{$setOnInsert:{a:1}}"), arrayFilters)); + ASSERT_DOES_NOT_THROW( + driver.parse(makeUpdateMod(fromjson("{$setOnInsert:{a:1}}")), arrayFilters)); ASSERT_FALSE(driver.type() == UpdateDriver::UpdateType::kReplacement); } @@ -174,7 +183,7 @@ TEST(Collator, SetCollationUpdatesModifierInterfaces) { UpdateDriver driver(expCtx); std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; - ASSERT_DOES_NOT_THROW(driver.parse(updateDocument, arrayFilters)); + ASSERT_DOES_NOT_THROW(driver.parse(makeUpdateMod(updateDocument), arrayFilters)); const bool validateForStorage = true; const FieldRefSet emptyImmutablePaths; @@ -209,8 +218,8 @@ public: new ExpressionContext(_opCtx.get(), nullptr, NamespaceString("foo")))), _driverRepl(new UpdateDriver( new ExpressionContext(_opCtx.get(), nullptr, NamespaceString("foo")))) { - _driverOps->parse(fromjson("{$set:{'_':1}}"), _arrayFilters); - _driverRepl->parse(fromjson("{}"), _arrayFilters); + _driverOps->parse(makeUpdateMod(fromjson("{$set:{'_':1}}")), _arrayFilters); + _driverRepl->parse(makeUpdateMod(fromjson("{}")), _arrayFilters); } mutablebson::Document& doc() { @@ -578,6 +587,7 @@ public: ASSERT(expr->getPlaceholder()); arrayFilters[expr->getPlaceholder().get()] = std::move(expr); } + _driver->setFromOplogApplication(fromOplog); _driver->refreshIndexKeys(indexData); _driver->parse(updateSpec, arrayFilters); @@ -607,61 +617,61 @@ public: TEST_F(ModifiedPathsTestFixture, SetFieldInRoot) { BSONObj spec = fromjson("{$set: {a: 1}}"); mutablebson::Document doc(fromjson("{a: 0}")); - runUpdate(&doc, spec); + runUpdate(&doc, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{a}"); } TEST_F(ModifiedPathsTestFixture, IncFieldInRoot) { BSONObj spec = fromjson("{$inc: {a: 1}}"); mutablebson::Document doc(fromjson("{a: 0}")); - runUpdate(&doc, spec); + runUpdate(&doc, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{a}"); } TEST_F(ModifiedPathsTestFixture, UnsetFieldInRoot) { BSONObj spec = fromjson("{$unset: {a: ''}}"); mutablebson::Document doc(fromjson("{a: 0}")); - runUpdate(&doc, spec); + runUpdate(&doc, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{a}"); } TEST_F(ModifiedPathsTestFixture, UpdateArrayElement) { BSONObj spec = fromjson("{$set: {'a.0.b': 1}}"); mutablebson::Document doc(fromjson("{a: [{b: 0}]}")); - runUpdate(&doc, spec); + runUpdate(&doc, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{a.0.b}"); } TEST_F(ModifiedPathsTestFixture, SetBeyondTheEndOfArrayShouldReturnPathToArray) { BSONObj spec = fromjson("{$set: {'a.1.b': 1}}"); mutablebson::Document doc(fromjson("{a: [{b: 0}]}")); - runUpdate(&doc, spec); + runUpdate(&doc, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{a}"); } TEST_F(ModifiedPathsTestFixture, InsertingAndUpdatingArrayShouldReturnPathToArray) { BSONObj spec = fromjson("{$set: {'a.0.b': 1, 'a.1.c': 2}}"); mutablebson::Document doc(fromjson("{a: [{b: 0}]}")); - runUpdate(&doc, spec); + runUpdate(&doc, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{a}"); spec = fromjson("{$set: {'a.10.b': 1, 'a.1.c': 2}}"); mutablebson::Document doc2(fromjson("{a: [{b: 0}, {b: 0}]}")); - runUpdate(&doc2, spec); + runUpdate(&doc2, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{a}"); } TEST_F(ModifiedPathsTestFixture, UpdateWithPositionalOperator) { BSONObj spec = fromjson("{$set: {'a.$': 1}}"); mutablebson::Document doc(fromjson("{a: [0, 1, 2]}")); - runUpdate(&doc, spec, "0"_sd); + runUpdate(&doc, makeUpdateMod(spec), "0"_sd); ASSERT_EQ(_modifiedPaths, "{a.0}"); } TEST_F(ModifiedPathsTestFixture, UpdateWithPositionalOperatorToNestedField) { BSONObj spec = fromjson("{$set: {'a.$.b': 1}}"); mutablebson::Document doc(fromjson("{a: [{b: 1}, {b: 2}]}")); - runUpdate(&doc, spec, "1"_sd); + runUpdate(&doc, makeUpdateMod(spec), "1"_sd); ASSERT_EQ(_modifiedPaths, "{a.1.b}"); } @@ -669,7 +679,7 @@ TEST_F(ModifiedPathsTestFixture, ArrayFilterThatMatchesNoElements) { BSONObj spec = fromjson("{$set: {'a.$[i]': 1}}"); BSONObj arrayFilter = fromjson("{i: 0}"); mutablebson::Document doc(fromjson("{a: [1, 2, 3]}")); - runUpdate(&doc, spec, ""_sd, {arrayFilter}); + runUpdate(&doc, makeUpdateMod(spec), ""_sd, {arrayFilter}); ASSERT_EQ(_modifiedPaths, "{a}"); } @@ -677,7 +687,7 @@ TEST_F(ModifiedPathsTestFixture, ArrayFilterThatMatchesNoElements) { TEST_F(ModifiedPathsTestFixture, ReplaceFullDocumentAlwaysAffectsIndex) { BSONObj spec = fromjson("{a: 1, b: 1}}"); mutablebson::Document doc(fromjson("{a: 0, b: 0}")); - runUpdate(&doc, spec); + runUpdate(&doc, makeUpdateMod(spec)); ASSERT_EQ(_modifiedPaths, "{}"); } @@ -692,13 +702,21 @@ TEST_F(ModifiedPathsTestFixture, PipelineUpdatesAlwaysAffectsIndex) { TEST_F(ModifiedPathsTestFixture, DeltaUpdateNotAffectingIndex) { BSONObj spec = fromjson("{d: {a: false}}"); mutablebson::Document doc(fromjson("{a: [{b: 0}]}")); - runUpdate(&doc, write_ops::UpdateModification(spec, {}), ""_sd, {}, true /* fromOplog */); + runUpdate(&doc, + write_ops::UpdateModification::parseFromV2Delta(spec), + ""_sd, + {}, + true /* fromOplog */); ASSERT(!_driver->modsAffectIndices()); UpdateIndexData indexData; indexData.addPath(FieldRef("p")); - runUpdate( - &doc, write_ops::UpdateModification(spec, {}), ""_sd, {}, true /* fromOplog */, &indexData); + runUpdate(&doc, + write_ops::UpdateModification::parseFromV2Delta(spec), + ""_sd, + {}, + true /* fromOplog */, + &indexData); ASSERT(!_driver->modsAffectIndices()); } @@ -708,8 +726,12 @@ TEST_F(ModifiedPathsTestFixture, DeltaUpdateAffectingIndex) { UpdateIndexData indexData; indexData.addPath(FieldRef("q")); indexData.addPath(FieldRef("a.p")); - runUpdate( - &doc, write_ops::UpdateModification(spec, {}), ""_sd, {}, true /* fromOplog */, &indexData); + runUpdate(&doc, + write_ops::UpdateModification::parseFromV2Delta(spec), + ""_sd, + {}, + true /* fromOplog */, + &indexData); ASSERT(_driver->modsAffectIndices()); } diff --git a/src/mongo/db/update/update_serialization_test.cpp b/src/mongo/db/update/update_serialization_test.cpp index 734d8c19e6a..8fa262ab46a 100644 --- a/src/mongo/db/update/update_serialization_test.cpp +++ b/src/mongo/db/update/update_serialization_test.cpp @@ -55,7 +55,7 @@ auto updateRoundTrip(const char* json, const std::vector<std::string> filterName std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> filters; for (const auto& name : filterNames) filters[name] = nullptr; - driver.parse(bson, filters); + driver.parse(write_ops::UpdateModification::parseFromClassicUpdate(bson), filters); return mongo::tojson(driver.serialize().getDocument().toBson(), mongo::JsonStringFormat::LegacyStrict); } diff --git a/src/mongo/dbtests/query_stage_update.cpp b/src/mongo/dbtests/query_stage_update.cpp index 5479714d190..e1e01a3d008 100644 --- a/src/mongo/dbtests/query_stage_update.cpp +++ b/src/mongo/dbtests/query_stage_update.cpp @@ -219,7 +219,8 @@ public: request.setUpsert(); request.setQuery(query); - request.setUpdateModification(updates); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(updates)); const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; const auto constants = boost::none; @@ -293,7 +294,8 @@ public: request.setMulti(); request.setQuery(query); - request.setUpdateModification(updates); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(updates)); const std::map<StringData, std::unique_ptr<ExpressionWithPlaceholder>> arrayFilters; const auto constants = boost::none; @@ -402,7 +404,8 @@ public: // Populate the request. request.setQuery(query); - request.setUpdateModification(fromjson("{$set: {x: 0}}")); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(fromjson("{$set: {x: 0}}"))); request.setSort(BSONObj()); request.setMulti(false); request.setReturnDocs(UpdateRequest::RETURN_OLD); @@ -494,7 +497,8 @@ public: // Populate the request. request.setQuery(query); - request.setUpdateModification(fromjson("{$set: {x: 0}}")); + request.setUpdateModification( + write_ops::UpdateModification::parseFromClassicUpdate(fromjson("{$set: {x: 0}}"))); request.setSort(BSONObj()); request.setMulti(false); request.setReturnDocs(UpdateRequest::RETURN_NEW); diff --git a/src/mongo/embedded/stitch_support/stitch_support.cpp b/src/mongo/embedded/stitch_support/stitch_support.cpp index 41693e92cd8..090bf4b6958 100644 --- a/src/mongo/embedded/stitch_support/stitch_support.cpp +++ b/src/mongo/embedded/stitch_support/stitch_support.cpp @@ -243,7 +243,9 @@ struct stitch_support_v1_update { this->parsedFilters = uassertStatusOK( mongo::parsedUpdateArrayFilters(expCtx, arrayFilterVector, mongo::kDummyNamespaceStr)); - updateDriver.parse(this->updateExpr, parsedFilters); + updateDriver.parse( + mongo::write_ops::UpdateModification::parseFromClassicUpdate(this->updateExpr), + parsedFilters); uassert(51037, "Updates with a positional operator require a matcher object.", diff --git a/src/mongo/s/catalog/dist_lock_catalog_impl.cpp b/src/mongo/s/catalog/dist_lock_catalog_impl.cpp index d8574212532..8a2622f4790 100644 --- a/src/mongo/s/catalog/dist_lock_catalog_impl.cpp +++ b/src/mongo/s/catalog/dist_lock_catalog_impl.cpp @@ -194,7 +194,8 @@ Status DistLockCatalogImpl::ping(OperationContext* opCtx, StringData processID, auto request = FindAndModifyRequest::makeUpdate(_lockPingNS, BSON(LockpingsType::process() << processID), - BSON("$set" << BSON(LockpingsType::ping(ping)))); + write_ops::UpdateModification::parseFromClassicUpdate( + BSON("$set" << BSON(LockpingsType::ping(ping))))); request.setUpsert(true); request.setWriteConcern(kMajorityWriteConcern); @@ -227,7 +228,7 @@ StatusWith<LocksType> DistLockCatalogImpl::grabLock(OperationContext* opCtx, auto request = FindAndModifyRequest::makeUpdate( _locksNS, BSON(LocksType::name() << lockID << LocksType::state(LocksType::UNLOCKED)), - BSON("$set" << newLockDetails)); + write_ops::UpdateModification::parseFromClassicUpdate(BSON("$set" << newLockDetails))); request.setUpsert(true); request.setShouldReturnNew(true); request.setWriteConcern(writeConcern); @@ -282,7 +283,9 @@ StatusWith<LocksType> DistLockCatalogImpl::overtakeLock(OperationContext* opCtx, << LocksType::why() << why)); auto request = FindAndModifyRequest::makeUpdate( - _locksNS, BSON("$or" << orQueryBuilder.arr()), BSON("$set" << newLockDetails)); + _locksNS, + BSON("$or" << orQueryBuilder.arr()), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("$set" << newLockDetails))); request.setShouldReturnNew(true); request.setWriteConcern(kMajorityWriteConcern); @@ -315,7 +318,8 @@ Status DistLockCatalogImpl::unlock(OperationContext* opCtx, const OID& lockSessi FindAndModifyRequest request = FindAndModifyRequest::makeUpdate( _locksNS, BSON(LocksType::lockID(lockSessionID)), - BSON("$set" << BSON(LocksType::state(LocksType::UNLOCKED)))); + write_ops::UpdateModification::parseFromClassicUpdate( + BSON("$set" << BSON(LocksType::state(LocksType::UNLOCKED))))); request.setWriteConcern(kMajorityWriteConcern); return _unlock(opCtx, request); } @@ -326,7 +330,8 @@ Status DistLockCatalogImpl::unlock(OperationContext* opCtx, FindAndModifyRequest request = FindAndModifyRequest::makeUpdate( _locksNS, BSON(LocksType::lockID(lockSessionID) << LocksType::name(name.toString())), - BSON("$set" << BSON(LocksType::state(LocksType::UNLOCKED)))); + write_ops::UpdateModification::parseFromClassicUpdate( + BSON("$set" << BSON(LocksType::state(LocksType::UNLOCKED))))); request.setWriteConcern(kMajorityWriteConcern); return _unlock(opCtx, request); } @@ -358,7 +363,8 @@ Status DistLockCatalogImpl::unlockAll(OperationContext* opCtx, const std::string updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(BSON(LocksType::process(processID))); - entry.setU(BSON("$set" << BSON(LocksType::state(LocksType::UNLOCKED)))); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate( + BSON("$set" << BSON(LocksType::state(LocksType::UNLOCKED))))); entry.setUpsert(false); entry.setMulti(true); return entry; diff --git a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp index 10751b45ed6..334bb82504d 100644 --- a/src/mongo/s/catalog/sharding_catalog_client_impl.cpp +++ b/src/mongo/s/catalog/sharding_catalog_client_impl.cpp @@ -917,7 +917,7 @@ StatusWith<bool> ShardingCatalogClientImpl::_updateConfigDocument( updateOp.setUpdates({[&] { write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(update); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(update)); entry.setUpsert(upsert); entry.setMulti(false); return entry; diff --git a/src/mongo/s/write_ops/batch_write_exec_test.cpp b/src/mongo/s/write_ops/batch_write_exec_test.cpp index c2a859a6a2c..5f74ae91cd0 100644 --- a/src/mongo/s/write_ops/batch_write_exec_test.cpp +++ b/src/mongo/s/write_ops/batch_write_exec_test.cpp @@ -333,9 +333,10 @@ TEST_F(BatchWriteExecTest, SingleUpdateTargetsShardWithLet) { }()); updateOp.setLet(let); updateOp.setRuntimeConstants(rtc); - updateOp.setUpdates(std::vector{write_ops::UpdateOpEntry(q, - {BSON("Key" - << "100")})}); + updateOp.setUpdates(std::vector{write_ops::UpdateOpEntry( + q, + write_ops::UpdateModification::parseFromClassicUpdate(BSON("Key" + << "100")))}); return updateOp; }()); updateRequest.setWriteConcern(BSONObj()); @@ -602,8 +603,9 @@ TEST_F(BatchWriteExecTest, StaleShardVersionReturnedFromBatchWithSingleMultiWrit writeCommandBase.setOrdered(false); return writeCommandBase; }()); - updateOp.setUpdates( - std::vector{write_ops::UpdateOpEntry(BSON("_id" << 100), {BSON("Key" << 100)})}); + updateOp.setUpdates(std::vector{write_ops::UpdateOpEntry( + BSON("_id" << 100), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("Key" << 100)))}); return updateOp; }()); request.setWriteConcern(BSONObj()); @@ -700,9 +702,13 @@ TEST_F(BatchWriteExecTest, writeCommandBase.setOrdered(false); return writeCommandBase; }()); - updateOp.setUpdates( - std::vector{write_ops::UpdateOpEntry(BSON("id" << 150), {BSON("x" << 1)}), - write_ops::UpdateOpEntry(BSON("id" << 200), {BSON("y" << 2)})}); + updateOp.setUpdates(std::vector{ + write_ops::UpdateOpEntry( + BSON("id" << 150), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("x" << 1))), + write_ops::UpdateOpEntry( + BSON("id" << 200), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("y" << 2)))}); return updateOp; }()); request.setWriteConcern(BSONObj()); @@ -816,9 +822,13 @@ TEST_F(BatchWriteExecTest, RetryableErrorReturnedFromMultiWriteWithShard1Firs) { writeCommandBase.setOrdered(false); return writeCommandBase; }()); - updateOp.setUpdates( - std::vector{write_ops::UpdateOpEntry(BSON("id" << 150), {BSON("x" << 1)}), - write_ops::UpdateOpEntry(BSON("id" << 200), {BSON("y" << 2)})}); + updateOp.setUpdates(std::vector{ + write_ops::UpdateOpEntry( + BSON("id" << 150), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("x" << 1))), + write_ops::UpdateOpEntry( + BSON("id" << 200), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("y" << 2)))}); return updateOp; }()); request.setWriteConcern(BSONObj()); @@ -943,9 +953,13 @@ TEST_F(BatchWriteExecTest, RetryableErrorReturnedFromMultiWriteWithShard1FirstOK writeCommandBase.setOrdered(false); return writeCommandBase; }()); - updateOp.setUpdates( - std::vector{write_ops::UpdateOpEntry(BSON("id" << 150), {BSON("x" << 1)}), - write_ops::UpdateOpEntry(BSON("id" << 200), {BSON("y" << 2)})}); + updateOp.setUpdates(std::vector{ + write_ops::UpdateOpEntry( + BSON("id" << 150), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("x" << 1))), + write_ops::UpdateOpEntry( + BSON("id" << 200), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("y" << 2)))}); return updateOp; }()); request.setWriteConcern(BSONObj()); @@ -1070,8 +1084,9 @@ TEST_F(BatchWriteExecTest, RetryableErrorReturnedFromWriteWithShard1SSVShard2OK) writeCommandBase.setOrdered(false); return writeCommandBase; }()); - updateOp.setUpdates( - std::vector{write_ops::UpdateOpEntry(BSON("_id" << 150), {BSON("x" << 1)})}); + updateOp.setUpdates(std::vector{write_ops::UpdateOpEntry( + BSON("_id" << 150), + write_ops::UpdateModification::parseFromClassicUpdate(BSON("x" << 1)))}); return updateOp; }()); request.setWriteConcern(BSONObj()); diff --git a/src/mongo/s/write_ops/batch_write_op_test.cpp b/src/mongo/s/write_ops/batch_write_op_test.cpp index 6d6e2d6e2fe..93155d454aa 100644 --- a/src/mongo/s/write_ops/batch_write_op_test.cpp +++ b/src/mongo/s/write_ops/batch_write_op_test.cpp @@ -69,7 +69,7 @@ write_ops::DeleteOpEntry buildDelete(const BSONObj& query, bool multi) { write_ops::UpdateOpEntry buildUpdate(const BSONObj& query, bool multi) { write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(BSONObj()); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(BSONObj())); entry.setMulti(multi); return entry; } @@ -77,7 +77,7 @@ write_ops::UpdateOpEntry buildUpdate(const BSONObj& query, bool multi) { write_ops::UpdateOpEntry buildUpdate(const BSONObj& query, const BSONObj& updateExpr, bool multi) { write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(updateExpr); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(updateExpr)); entry.setMulti(multi); return entry; } diff --git a/src/mongo/s/write_ops/chunk_manager_targeter_test.cpp b/src/mongo/s/write_ops/chunk_manager_targeter_test.cpp index 5ae9163c5a7..b11aa4b1a0f 100644 --- a/src/mongo/s/write_ops/chunk_manager_targeter_test.cpp +++ b/src/mongo/s/write_ops/chunk_manager_targeter_test.cpp @@ -50,7 +50,7 @@ auto buildUpdate(const NamespaceString& nss, BSONObj query, BSONObj update, bool write_ops::Update updateOp(nss); write_ops::UpdateOpEntry entry; entry.setQ(query); - entry.setU(update); + entry.setU(write_ops::UpdateModification::parseFromClassicUpdate(update)); entry.setUpsert(upsert); updateOp.setUpdates(std::vector{entry}); return BatchedCommandRequest{std::move(updateOp)}; |