diff options
author | Alberto Massari <alberto.massari@mongodb.com> | 2022-12-21 19:56:54 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-12-21 21:14:53 +0000 |
commit | 5977e706431fd5705b59115ec0e0d2d7a2203246 (patch) | |
tree | 2161b9d853c2e7453a19d12b88bd39bc9bf87dd5 | |
parent | 9ac3279cc3459b31a597ed4659e07ad93f073d8f (diff) | |
download | mongo-5977e706431fd5705b59115ec0e0d2d7a2203246.tar.gz |
SERVER-65364 Allow fine-grained selection of indexes to update
36 files changed, 521 insertions, 156 deletions
diff --git a/src/mongo/bson/bsonobj.cpp b/src/mongo/bson/bsonobj.cpp index 88715dd68de..6f5ca8aec3f 100644 --- a/src/mongo/bson/bsonobj.cpp +++ b/src/mongo/bson/bsonobj.cpp @@ -89,6 +89,8 @@ int compareObjects(const BSONObj& firstObj, /* BSONObj ------------------------------------------------------------*/ +const BSONObj BSONObj::kEmptyObject; + void BSONObj::_assertInvalid(int maxSize) const { StringBuilder ss; int os = objsize(); diff --git a/src/mongo/bson/bsonobj.h b/src/mongo/bson/bsonobj.h index 83453bcc9e1..0c24e4cd676 100644 --- a/src/mongo/bson/bsonobj.h +++ b/src/mongo/bson/bsonobj.h @@ -123,6 +123,7 @@ public: using ComparisonRulesSet = BSONComparatorInterfaceBase<BSONObj>::ComparisonRulesSet; static constexpr char kMinBSONLength = 5; + static const BSONObj kEmptyObject; /** * Construct an empty BSONObj -- that is, {}. diff --git a/src/mongo/db/catalog/collection_test.cpp b/src/mongo/db/catalog/collection_test.cpp index 48c653f975f..4337263b70a 100644 --- a/src/mongo/db/catalog/collection_test.cpp +++ b/src/mongo/db/catalog/collection_test.cpp @@ -278,8 +278,14 @@ TEST_F(CollectionTest, VerifyIndexIsUpdated) { WriteUnitOfWork wuow(opCtx); Snapshotted<BSONObj> oldSnap(opCtx->recoveryUnit()->getSnapshotId(), oldDoc); CollectionUpdateArgs args{oldDoc}; - collection_internal::updateDocument( - opCtx, coll, oldRecordId, oldSnap, newDoc, true, nullptr, &args); + collection_internal::updateDocument(opCtx, + coll, + oldRecordId, + oldSnap, + newDoc, + collection_internal::kUpdateAllIndexes, + nullptr, + &args); wuow.commit(); } auto indexRecordId = userIdx->getEntry()->accessMethod()->asSortedData()->findSingle( @@ -329,7 +335,7 @@ TEST_F(CollectionTest, VerifyIndexIsUpdatedWithDamages) { oldSnap, damagesOutput.damageSource.get(), damagesOutput.damages, - true, + collection_internal::kUpdateAllIndexes, nullptr, &args); ASSERT_OK(newDocStatus); diff --git a/src/mongo/db/catalog/collection_write_path.cpp b/src/mongo/db/catalog/collection_write_path.cpp index 266f31f42eb..a3fab3026e3 100644 --- a/src/mongo/db/catalog/collection_write_path.cpp +++ b/src/mongo/db/catalog/collection_write_path.cpp @@ -400,7 +400,7 @@ RecordId updateDocument(OperationContext* opCtx, const RecordId& oldLocation, const Snapshotted<BSONObj>& oldDoc, const BSONObj& newDoc, - bool indexesAffected, + const BSONObj* opDiff, OpDebug* opDebug, CollectionUpdateArgs* args) { { @@ -473,7 +473,8 @@ RecordId updateDocument(OperationContext* opCtx, uassertStatusOK(collection->getRecordStore()->updateRecord( opCtx, oldLocation, newDoc.objdata(), newDoc.objsize())); - if (indexesAffected) { + // don't update the indexes if kUpdateNoIndexes has been specified. + if (opDiff != kUpdateNoIndexes) { int64_t keysInserted = 0; int64_t keysDeleted = 0; @@ -481,6 +482,7 @@ RecordId updateDocument(OperationContext* opCtx, collection, args->preImageDoc, newDoc, + opDiff, oldLocation, &keysInserted, &keysDeleted)); @@ -512,7 +514,7 @@ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx, const Snapshotted<BSONObj>& oldDoc, const char* damageSource, const mutablebson::DamageVector& damages, - bool indexesAffected, + const BSONObj* opDiff, OpDebug* opDebug, CollectionUpdateArgs* args) { dassert(opCtx->lockState()->isCollectionLockedForMode(collection->ns(), MODE_IX)); @@ -551,12 +553,19 @@ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx, args->changeStreamPreAndPostImagesEnabledForCollection = collection->isChangeStreamPreAndPostImagesEnabled(); - if (indexesAffected) { + // don't update the indexes if kUpdateNoIndexes has been specified. + if (opDiff != kUpdateNoIndexes) { int64_t keysInserted = 0; int64_t keysDeleted = 0; - uassertStatusOK(collection->getIndexCatalog()->updateRecord( - opCtx, collection, oldDoc.value(), args->updatedDoc, loc, &keysInserted, &keysDeleted)); + uassertStatusOK(collection->getIndexCatalog()->updateRecord(opCtx, + collection, + oldDoc.value(), + args->updatedDoc, + opDiff, + loc, + &keysInserted, + &keysDeleted)); if (opDebug) { opDebug->additiveMetrics.incrementKeysInserted(keysInserted); diff --git a/src/mongo/db/catalog/collection_write_path.h b/src/mongo/db/catalog/collection_write_path.h index e492aef05ca..482c5911634 100644 --- a/src/mongo/db/catalog/collection_write_path.h +++ b/src/mongo/db/catalog/collection_write_path.h @@ -45,6 +45,12 @@ enum class StoreDeletedDoc { Off, On }; enum class RetryableWrite { kYes, kNo }; /** + * Constants used for the opDiff argument in updateDocument and updateDocumentWithDamages. + */ +constexpr const BSONObj* kUpdateAllIndexes = nullptr; +constexpr const BSONObj* kUpdateNoIndexes = &BSONObj::kEmptyObject; + +/** * Inserts a document into the record store for a bulk loader that manages the index building. The * bulk loader is notified with the RecordId of the document inserted into the RecordStore through * the 'OnRecordInsertedFn' callback. @@ -94,6 +100,9 @@ Status checkFailCollectionInsertsFailPoint(const NamespaceString& ns, const BSON * * If the document fits in the old space, it is put there; if not, it is moved. * Sets 'args.updatedDoc' to the updated version of the document with damages applied, on success. + * 'opDiff' Optional argument. If set to kUpdateAllIndexes, all the indexes are updated. If it is + * set to kUpdateNoIndexes, no indexes are updated. Otherwise, it is the precomputed difference + * between 'oldDoc' and 'newDoc', used to determine which indexes need to be updated. * 'opDebug' Optional argument. When not null, will be used to record operation statistics. * @return the post update location of the doc (may or may not be the same as oldLocation) */ @@ -102,7 +111,7 @@ RecordId updateDocument(OperationContext* opCtx, const RecordId& oldLocation, const Snapshotted<BSONObj>& oldDoc, const BSONObj& newDoc, - bool indexesAffected, + const BSONObj* opDiff, OpDebug* opDebug, CollectionUpdateArgs* args); @@ -117,7 +126,7 @@ StatusWith<BSONObj> updateDocumentWithDamages(OperationContext* opCtx, const Snapshotted<BSONObj>& oldDoc, const char* damageSource, const mutablebson::DamageVector& damages, - bool indexesAffected, + const BSONObj* opDiff, OpDebug* opDebug, CollectionUpdateArgs* args); diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h index 7a038076125..e4006aa773e 100644 --- a/src/mongo/db/catalog/index_catalog.h +++ b/src/mongo/db/catalog/index_catalog.h @@ -490,6 +490,9 @@ public: /** * Both 'keysInsertedOut' and 'keysDeletedOut' are required and will be set to the number of * index keys inserted and deleted by this operation, respectively. + * The 'opDiff' argument specifies an optional document containing the differences between + * 'oldDoc' and 'newDoc' that can be used to decide which indexes have to be modified. If + * set to null, all indexes should be updated. * * This method may throw. */ @@ -497,6 +500,7 @@ public: const CollectionPtr& coll, const BSONObj& oldDoc, const BSONObj& newDoc, + const BSONObj* opDiff, const RecordId& recordId, int64_t* keysInsertedOut, int64_t* keysDeletedOut) const = 0; diff --git a/src/mongo/db/catalog/index_catalog_entry.h b/src/mongo/db/catalog/index_catalog_entry.h index 0a21729e758..b4f6d6d582e 100644 --- a/src/mongo/db/catalog/index_catalog_entry.h +++ b/src/mongo/db/catalog/index_catalog_entry.h @@ -55,6 +55,7 @@ class IndexBuildInterceptor; class IndexDescriptor; class MatchExpression; class OperationContext; +class UpdateIndexData; class IndexCatalogEntry : public std::enable_shared_from_this<IndexCatalogEntry> { public: @@ -190,6 +191,8 @@ public: virtual boost::optional<Timestamp> getMinimumVisibleSnapshot() const = 0; virtual void setMinimumVisibleSnapshot(Timestamp name) = 0; + + virtual const UpdateIndexData& getIndexedPaths() const = 0; }; class IndexCatalogEntryContainer { diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp index 31619ec9136..65de03edfed 100644 --- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp @@ -126,6 +126,7 @@ IndexCatalogEntryImpl::IndexCatalogEntryImpl(OperationContext* const opCtx, void IndexCatalogEntryImpl::setAccessMethod(std::unique_ptr<IndexAccessMethod> accessMethod) { invariant(!_accessMethod); _accessMethod = std::move(accessMethod); + CollectionQueryInfo::computeUpdateIndexData(this, _accessMethod.get(), &_indexedPaths); } bool IndexCatalogEntryImpl::isReady(OperationContext* opCtx) const { diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.h b/src/mongo/db/catalog/index_catalog_entry_impl.h index 9d6c40f95b1..8955ba64947 100644 --- a/src/mongo/db/catalog/index_catalog_entry_impl.h +++ b/src/mongo/db/catalog/index_catalog_entry_impl.h @@ -38,6 +38,7 @@ #include "mongo/db/index/multikey_paths.h" #include "mongo/db/matcher/expression.h" #include "mongo/db/record_id.h" +#include "mongo/db/update_index_data.h" #include "mongo/platform/atomic_word.h" #include "mongo/platform/mutex.h" @@ -190,6 +191,10 @@ public: */ void setMinimumVisibleSnapshot(Timestamp newMinimumVisibleSnapshot) final; + const UpdateIndexData& getIndexedPaths() const final { + return _indexedPaths; + } + private: /** * Sets this index to be multikey when we are running inside a multi-document transaction. @@ -247,5 +252,8 @@ private: // Used to improve lookups without having to search for the index name // accessing the collection metadata. int _indexOffset; + + // Describes the paths indexed by this index. + UpdateIndexData _indexedPaths; }; } // namespace mongo diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp index f3cab48c45a..ed48ba36774 100644 --- a/src/mongo/db/catalog/index_catalog_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_impl.cpp @@ -76,6 +76,7 @@ #include "mongo/db/storage/storage_parameters_gen.h" #include "mongo/db/storage/storage_util.h" #include "mongo/db/ttl_collection_cache.h" +#include "mongo/db/update/document_diff_calculator.h" #include "mongo/db/vector_clock.h" #include "mongo/logv2/log.h" #include "mongo/util/assert_util.h" @@ -1852,32 +1853,43 @@ Status IndexCatalogImpl::updateRecord(OperationContext* const opCtx, const CollectionPtr& coll, const BSONObj& oldDoc, const BSONObj& newDoc, + const BSONObj* opDiff, const RecordId& recordId, int64_t* const keysInsertedOut, int64_t* const keysDeletedOut) const { *keysInsertedOut = 0; *keysDeletedOut = 0; - // Ready indexes go directly through the IndexAccessMethod. - for (IndexCatalogEntryContainer::const_iterator it = _readyIndexes.begin(); - it != _readyIndexes.end(); - ++it) { - IndexCatalogEntry* entry = it->get(); - auto status = _updateRecord( - opCtx, coll, entry, oldDoc, newDoc, recordId, keysInsertedOut, keysDeletedOut); - if (!status.isOK()) - return status; - } + const size_t numIndexesToUpdate = _readyIndexes.size() + _buildingIndexes.size(); + if (numIndexesToUpdate > 0) { + mongo::doc_diff::BitVector toUpdate; + if (opDiff) { + std::vector<const UpdateIndexData*> allIndexPaths; + allIndexPaths.reserve(numIndexesToUpdate); + for (auto& indexes : {std::ref(_readyIndexes), std::ref(_buildingIndexes)}) { + for (const auto& indexEntry : indexes.get()) { + dassert(!indexEntry->getIndexedPaths().isEmpty()); + allIndexPaths.push_back(&indexEntry->getIndexedPaths()); + } + } + toUpdate = mongo::doc_diff::anyIndexesMightBeAffected(*opDiff, allIndexPaths); + } else { + toUpdate = mongo::doc_diff::BitVector(numIndexesToUpdate); + toUpdate.set(); + } - // Building indexes go through the interceptor. - for (IndexCatalogEntryContainer::const_iterator it = _buildingIndexes.begin(); - it != _buildingIndexes.end(); - ++it) { - IndexCatalogEntry* entry = it->get(); - auto status = _updateRecord( - opCtx, coll, entry, oldDoc, newDoc, recordId, keysInsertedOut, keysDeletedOut); - if (!status.isOK()) - return status; + for (size_t pos = toUpdate.find_first(); pos != mongo::doc_diff::BitVector::npos; + pos = toUpdate.find_next(pos)) { + const IndexCatalogEntry* entry = (pos < _readyIndexes.size()) + ? (_readyIndexes.begin() + pos)->get() + : (_buildingIndexes.begin() + (pos - _readyIndexes.size()))->get(); + + auto status = _updateRecord( + opCtx, coll, entry, oldDoc, newDoc, recordId, keysInsertedOut, keysDeletedOut); + if (!status.isOK()) { + return status; + } + } } return Status::OK(); } diff --git a/src/mongo/db/catalog/index_catalog_impl.h b/src/mongo/db/catalog/index_catalog_impl.h index 3c09fec3fb4..463408421d4 100644 --- a/src/mongo/db/catalog/index_catalog_impl.h +++ b/src/mongo/db/catalog/index_catalog_impl.h @@ -257,6 +257,7 @@ public: const CollectionPtr& coll, const BSONObj& oldDoc, const BSONObj& newDoc, + const BSONObj* opDiff, const RecordId& recordId, int64_t* keysInsertedOut, int64_t* keysDeletedOut) const override; diff --git a/src/mongo/db/catalog/views_for_database.cpp b/src/mongo/db/catalog/views_for_database.cpp index e41ed08f9db..07706e1f0d8 100644 --- a/src/mongo/db/catalog/views_for_database.cpp +++ b/src/mongo/db/catalog/views_for_database.cpp @@ -332,7 +332,7 @@ Status ViewsForDatabase::_upsertIntoCatalog(OperationContext* opCtx, id, oldView, viewObj, - true /* indexesAffected */, + collection_internal::kUpdateAllIndexes, &CurOp::get(opCtx)->debug(), &args); } diff --git a/src/mongo/db/dbhelpers.cpp b/src/mongo/db/dbhelpers.cpp index 0aad03060cd..a05560fd078 100644 --- a/src/mongo/db/dbhelpers.cpp +++ b/src/mongo/db/dbhelpers.cpp @@ -387,8 +387,14 @@ bool Helpers::findByIdAndNoopUpdate(OperationContext* opCtx, CollectionUpdateArgs args(snapshottedDoc.value()); args.criteria = idQuery; args.update = BSONObj(); - collection_internal::updateDocument( - opCtx, collection, recordId, snapshottedDoc, result, false, nullptr, &args); + collection_internal::updateDocument(opCtx, + collection, + recordId, + snapshottedDoc, + result, + collection_internal::kUpdateNoIndexes, + nullptr, + &args); return true; } diff --git a/src/mongo/db/exec/update_stage.cpp b/src/mongo/db/exec/update_stage.cpp index 7e6423854c6..5e1b5eff939 100644 --- a/src/mongo/db/exec/update_stage.cpp +++ b/src/mongo/db/exec/update_stage.cpp @@ -41,6 +41,7 @@ #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/s/operation_sharding_state.h" #include "mongo/db/update/path_support.h" +#include "mongo/db/update/update_oplog_entry_serialization.h" #include "mongo/logv2/log.h" #include "mongo/s/grid.h" #include "mongo/s/would_change_owning_shard_exception.h" @@ -273,17 +274,18 @@ BSONObj UpdateStage::transformAndUpdate(const Snapshotted<BSONObj>& oldObj, checkUpdateChangesShardKeyFields(boost::none /* newObj */, oldObj); } + auto diff = update_oplog_entry::extractDiffFromOplogEntry(logObj); WriteUnitOfWork wunit(opCtx()); - newObj = uassertStatusOK( - collection_internal::updateDocumentWithDamages(opCtx(), - collection(), - recordId, - oldObj, - source, - _damages, - driver->modsAffectIndices(), - _params.opDebug, - &args)); + newObj = uassertStatusOK(collection_internal::updateDocumentWithDamages( + opCtx(), + collection(), + recordId, + oldObj, + source, + _damages, + diff.has_value() ? &*diff : collection_internal::kUpdateAllIndexes, + _params.opDebug, + &args)); invariant(oldObj.snapshotId() == opCtx()->recoveryUnit()->getSnapshotId()); wunit.commit(); } @@ -304,15 +306,18 @@ BSONObj UpdateStage::transformAndUpdate(const Snapshotted<BSONObj>& oldObj, if (_isUserInitiatedWrite) { checkUpdateChangesShardKeyFields(newObj, oldObj); } + + auto diff = update_oplog_entry::extractDiffFromOplogEntry(logObj); WriteUnitOfWork wunit(opCtx()); - newRecordId = collection_internal::updateDocument(opCtx(), - collection(), - recordId, - oldObj, - newObj, - driver->modsAffectIndices(), - _params.opDebug, - &args); + newRecordId = collection_internal::updateDocument( + opCtx(), + collection(), + recordId, + oldObj, + newObj, + diff.has_value() ? &*diff : collection_internal::kUpdateAllIndexes, + _params.opDebug, + &args); invariant(oldObj.snapshotId() == opCtx()->recoveryUnit()->getSnapshotId()); wunit.commit(); } diff --git a/src/mongo/db/index/index_access_method.cpp b/src/mongo/db/index/index_access_method.cpp index 6e62bd1eb10..62b8b5be476 100644 --- a/src/mongo/db/index/index_access_method.cpp +++ b/src/mongo/db/index/index_access_method.cpp @@ -258,7 +258,6 @@ Status SortedDataIndexAccessMethod::update(OperationContext* opCtx, const InsertDeleteOptions& options, int64_t* numInserted, int64_t* numDeleted) { - UpdateTicket updateTicket; prepareUpdate(opCtx, coll, oldDoc, newDoc, loc, options, &updateTicket); diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp index 49fb1dd32fb..49286f8019d 100644 --- a/src/mongo/db/ops/write_ops_exec.cpp +++ b/src/mongo/db/ops/write_ops_exec.cpp @@ -1444,15 +1444,19 @@ Status performAtomicTimeseriesWrites( args.source = OperationSource::kTimeseriesInsert; BSONObj updated; - bool indexesAffected = true; + BSONObj diffFromUpdate; + const BSONObj* diffOnIndexes = + collection_internal::kUpdateAllIndexes; // Assume all indexes are affected. if (update.getU().type() == write_ops::UpdateModification::Type::kDelta) { + diffFromUpdate = update.getU().getDiff(); auto result = doc_diff::applyDiff(original.value(), - update.getU().getDiff(), + diffFromUpdate, &CollectionQueryInfo::get(*coll).getIndexKeys(opCtx), static_cast<bool>(repl::tenantMigrationInfo(opCtx))); updated = result.postImage; - indexesAffected = result.indexesAffected; - args.update = update_oplog_entry::makeDeltaOplogEntry(update.getU().getDiff()); + diffOnIndexes = + result.indexesAffected ? &diffFromUpdate : collection_internal::kUpdateNoIndexes; + args.update = update_oplog_entry::makeDeltaOplogEntry(diffFromUpdate); } else if (update.getU().type() == write_ops::UpdateModification::Type::kTransform) { const auto& transform = update.getU().getTransform(); auto transformed = transform(original.value()); @@ -1472,7 +1476,7 @@ Status performAtomicTimeseriesWrites( } collection_internal::updateDocument( - opCtx, *coll, recordId, original, updated, indexesAffected, &curOp->debug(), &args); + opCtx, *coll, recordId, original, updated, diffOnIndexes, &curOp->debug(), &args); if (slot) { if (participant) { // Manually sets the timestamp so that the "prevOpTime" field in the oplog entry is diff --git a/src/mongo/db/query/collection_query_info.cpp b/src/mongo/db/query/collection_query_info.cpp index 55261978b21..1f689e766db 100644 --- a/src/mongo/db/query/collection_query_info.cpp +++ b/src/mongo/db/query/collection_query_info.cpp @@ -118,78 +118,84 @@ const UpdateIndexData& CollectionQueryInfo::getIndexKeys(OperationContext* opCtx return _indexedPaths; } -void CollectionQueryInfo::computeIndexKeys(OperationContext* opCtx, const CollectionPtr& coll) { - _indexedPaths.clear(); +void CollectionQueryInfo::computeUpdateIndexData(const IndexCatalogEntry* entry, + const IndexAccessMethod* accessMethod, + UpdateIndexData* outData) { + const IndexDescriptor* descriptor = entry->descriptor(); + if (bool isWildcard = (descriptor->getAccessMethodName() == IndexNames::WILDCARD); + isWildcard || descriptor->getAccessMethodName() == IndexNames::COLUMN) { + // Obtain the projection used by the $** index's key generator. + const auto* pathProj = isWildcard + ? static_cast<const IndexPathProjection*>( + static_cast<const WildcardAccessMethod*>(accessMethod)->getWildcardProjection()) + : static_cast<const IndexPathProjection*>( + static_cast<const ColumnStoreAccessMethod*>(accessMethod) + ->getColumnstoreProjection()); + // If the projection is an exclusion, then we must check the new document's keys on all + // updates, since we do not exhaustively know the set of paths to be indexed. + if (pathProj->exec()->getType() == + TransformerInterface::TransformerType::kExclusionProjection) { + outData->allPathsIndexed(); + } else { + // If a subtree was specified in the keyPattern, or if an inclusion projection is + // present, then we need only index the path(s) preserved by the projection. + const auto& exhaustivePaths = pathProj->exhaustivePaths(); + invariant(exhaustivePaths); + for (const auto& path : *exhaustivePaths) { + outData->addPath(path); + } + } + } else if (descriptor->getAccessMethodName() == IndexNames::TEXT) { + fts::FTSSpec ftsSpec(descriptor->infoObj()); - auto it = coll->getIndexCatalog()->getIndexIterator( - opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished); - while (it->more()) { - const IndexCatalogEntry* entry = it->next(); - const IndexDescriptor* descriptor = entry->descriptor(); - const IndexAccessMethod* iam = entry->accessMethod(); - - if (bool isWildcard = (descriptor->getAccessMethodName() == IndexNames::WILDCARD); - isWildcard || descriptor->getAccessMethodName() == IndexNames::COLUMN) { - // Obtain the projection used by the $** index's key generator. - const auto* pathProj = isWildcard - ? static_cast<const IndexPathProjection*>( - static_cast<const WildcardAccessMethod*>(iam)->getWildcardProjection()) - : static_cast<const IndexPathProjection*>( - static_cast<const ColumnStoreAccessMethod*>(iam)->getColumnstoreProjection()); - // If the projection is an exclusion, then we must check the new document's keys on all - // updates, since we do not exhaustively know the set of paths to be indexed. - if (pathProj->exec()->getType() == - TransformerInterface::TransformerType::kExclusionProjection) { - _indexedPaths.allPathsIndexed(); - } else { - // If a subtree was specified in the keyPattern, or if an inclusion projection is - // present, then we need only index the path(s) preserved by the projection. - const auto& exhaustivePaths = pathProj->exhaustivePaths(); - invariant(exhaustivePaths); - for (const auto& path : *exhaustivePaths) { - _indexedPaths.addPath(path); - } + if (ftsSpec.wildcard()) { + outData->allPathsIndexed(); + } else { + for (size_t i = 0; i < ftsSpec.numExtraBefore(); ++i) { + outData->addPath(FieldRef(ftsSpec.extraBefore(i))); } - } else if (descriptor->getAccessMethodName() == IndexNames::TEXT) { - fts::FTSSpec ftsSpec(descriptor->infoObj()); - - if (ftsSpec.wildcard()) { - _indexedPaths.allPathsIndexed(); - } else { - for (size_t i = 0; i < ftsSpec.numExtraBefore(); ++i) { - _indexedPaths.addPath(FieldRef(ftsSpec.extraBefore(i))); - } - for (fts::Weights::const_iterator it = ftsSpec.weights().begin(); - it != ftsSpec.weights().end(); - ++it) { - _indexedPaths.addPath(FieldRef(it->first)); - } - for (size_t i = 0; i < ftsSpec.numExtraAfter(); ++i) { - _indexedPaths.addPath(FieldRef(ftsSpec.extraAfter(i))); - } - // Any update to a path containing "language" as a component could change the - // language of a subdocument. Add the override field as a path component. - _indexedPaths.addPathComponent(ftsSpec.languageOverrideField()); + for (fts::Weights::const_iterator it = ftsSpec.weights().begin(); + it != ftsSpec.weights().end(); + ++it) { + outData->addPath(FieldRef(it->first)); } - } else { - BSONObj key = descriptor->keyPattern(); - BSONObjIterator j(key); - while (j.more()) { - BSONElement e = j.next(); - _indexedPaths.addPath(FieldRef(e.fieldName())); + for (size_t i = 0; i < ftsSpec.numExtraAfter(); ++i) { + outData->addPath(FieldRef(ftsSpec.extraAfter(i))); } + // Any update to a path containing "language" as a component could change the + // language of a subdocument. Add the override field as a path component. + outData->addPathComponent(ftsSpec.languageOverrideField()); + } + } else { + BSONObj key = descriptor->keyPattern(); + BSONObjIterator j(key); + while (j.more()) { + BSONElement e = j.next(); + outData->addPath(FieldRef(e.fieldName())); } + } - // handle partial indexes - const MatchExpression* filter = entry->getFilterExpression(); - if (filter) { - stdx::unordered_set<std::string> paths; - QueryPlannerIXSelect::getFields(filter, &paths); - for (auto it = paths.begin(); it != paths.end(); ++it) { - _indexedPaths.addPath(FieldRef(*it)); - } + // handle partial indexes + const MatchExpression* filter = entry->getFilterExpression(); + if (filter) { + stdx::unordered_set<std::string> paths; + QueryPlannerIXSelect::getFields(filter, &paths); + for (auto it = paths.begin(); it != paths.end(); ++it) { + outData->addPath(FieldRef(*it)); } } +} + +void CollectionQueryInfo::computeUpdateIndexData(OperationContext* opCtx, + const CollectionPtr& coll) { + _indexedPaths.clear(); + + auto it = coll->getIndexCatalog()->getIndexIterator( + opCtx, IndexCatalog::InclusionPolicy::kReady | IndexCatalog::InclusionPolicy::kUnfinished); + while (it->more()) { + const IndexCatalogEntry* entry = it->next(); + computeUpdateIndexData(entry, entry->accessMethod(), &_indexedPaths); + } _keysComputed = true; } @@ -261,7 +267,7 @@ void CollectionQueryInfo::init(OperationContext* opCtx, const CollectionPtr& col void CollectionQueryInfo::rebuildIndexData(OperationContext* opCtx, const CollectionPtr& coll) { _keysComputed = false; - computeIndexKeys(opCtx, coll); + computeUpdateIndexData(opCtx, coll); updatePlanCacheIndexEntries(opCtx, coll); } diff --git a/src/mongo/db/query/collection_query_info.h b/src/mongo/db/query/collection_query_info.h index e5fbffe720f..2b621d69a2a 100644 --- a/src/mongo/db/query/collection_query_info.h +++ b/src/mongo/db/query/collection_query_info.h @@ -58,6 +58,12 @@ public: static CollectionQueryInfo& get(Collection* collection) { return CollectionQueryInfo::getCollectionQueryInfo(collection); } + /** + * Populate the outData structure using the index keys found in the index definition. + */ + static void computeUpdateIndexData(const IndexCatalogEntry* entry, + const IndexAccessMethod* accessMethod, + UpdateIndexData* outData); /** * Gets the PlanCache for this collection. @@ -145,7 +151,7 @@ private: PlanCacheIndexabilityState planCacheIndexabilityState; }; - void computeIndexKeys(OperationContext* opCtx, const CollectionPtr& coll); + void computeUpdateIndexData(OperationContext* opCtx, const CollectionPtr& coll); void updatePlanCacheIndexEntries(OperationContext* opCtx, const CollectionPtr& coll); // --- index keys cache diff --git a/src/mongo/db/repl/storage_timestamp_test.cpp b/src/mongo/db/repl/storage_timestamp_test.cpp index 9accf4a37b8..70a54a98b63 100644 --- a/src/mongo/db/repl/storage_timestamp_test.cpp +++ b/src/mongo/db/repl/storage_timestamp_test.cpp @@ -3205,7 +3205,7 @@ TEST_F(RetryableFindAndModifyTest, RetryableFindAndModifyUpdate) { record->id, Snapshotted<BSONObj>(_opCtx->recoveryUnit()->getSnapshotId(), oldObj), newObj, - false, + collection_internal::kUpdateNoIndexes, nullptr, &args); wuow.commit(); @@ -3258,8 +3258,16 @@ TEST_F(RetryableFindAndModifyTest, RetryableFindAndModifyUpdateWithDamages) { auto record = cursor->next(); invariant(record); WriteUnitOfWork wuow(_opCtx); - const auto statusWith = collection_internal::updateDocumentWithDamages( - _opCtx, *autoColl, record->id, objSnapshot, source, damages, false, nullptr, &args); + const auto statusWith = + collection_internal::updateDocumentWithDamages(_opCtx, + *autoColl, + record->id, + objSnapshot, + source, + damages, + collection_internal::kUpdateNoIndexes, + nullptr, + &args); wuow.commit(); ASSERT_OK(statusWith.getStatus()); } diff --git a/src/mongo/db/repl/tenant_migration_donor_service.cpp b/src/mongo/db/repl/tenant_migration_donor_service.cpp index e68cb891b50..3906900198f 100644 --- a/src/mongo/db/repl/tenant_migration_donor_service.cpp +++ b/src/mongo/db/repl/tenant_migration_donor_service.cpp @@ -666,7 +666,7 @@ ExecutorFuture<repl::OpTime> TenantMigrationDonorService::Instance::_updateState originalRecordId, originalSnapshot, updatedStateDocBson, - false, + collection_internal::kUpdateNoIndexes, nullptr /* OpDebug* */, &args); diff --git a/src/mongo/db/serverless/shard_split_donor_service.cpp b/src/mongo/db/serverless/shard_split_donor_service.cpp index f0d930c171b..ed52e344a70 100644 --- a/src/mongo/db/serverless/shard_split_donor_service.cpp +++ b/src/mongo/db/serverless/shard_split_donor_service.cpp @@ -975,14 +975,15 @@ ExecutorFuture<repl::OpTime> ShardSplitDonorService::DonorStateMachine::_updateS args.oplogSlots = {oplogSlot}; args.update = updatedStateDocBson; - collection_internal::updateDocument(opCtx, - *collection, - originalRecordId, - originalSnapshot, - updatedStateDocBson, - false, - nullptr /* OpDebug* */, - &args); + collection_internal::updateDocument( + opCtx, + *collection, + originalRecordId, + originalSnapshot, + updatedStateDocBson, + collection_internal::kUpdateNoIndexes, + nullptr /* OpDebug* */, + &args); return oplogSlot; }(); diff --git a/src/mongo/db/transaction/transaction_participant.cpp b/src/mongo/db/transaction/transaction_participant.cpp index 2d5b49665d1..e615798495f 100644 --- a/src/mongo/db/transaction/transaction_participant.cpp +++ b/src/mongo/db/transaction/transaction_participant.cpp @@ -451,14 +451,14 @@ void updateSessionEntry(OperationContext* opCtx, args.criteria = toUpdateIdDoc; args.update = updateMod; - // Specify indexesAffected = false because the sessions collection has two indexes: {_id: 1} and + // Specify kUpdateNoIndexes because the sessions collection has two indexes: {_id: 1} and // {parentLsid: 1, _id.txnNumber: 1, _id: 1}, and none of the fields are mutable. collection_internal::updateDocument(opCtx, *collection, recordId, Snapshotted<BSONObj>(startingSnapshotId, originalDoc), updateMod, - false, /* indexesAffected */ + collection_internal::kUpdateNoIndexes, nullptr, &args); diff --git a/src/mongo/db/update/addtoset_node_test.cpp b/src/mongo/db/update/addtoset_node_test.cpp index c09d1eb71e5..6c031e43875 100644 --- a/src/mongo/db/update/addtoset_node_test.cpp +++ b/src/mongo/db/update/addtoset_node_test.cpp @@ -133,6 +133,7 @@ TEST_F(AddToSetNodeTest, ApplyNonEach) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 1]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -153,6 +154,7 @@ TEST_F(AddToSetNodeTest, ApplyNonEachArray) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, [1]]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -172,6 +174,7 @@ TEST_F(AddToSetNodeTest, ApplyEach) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 1, 2]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -191,6 +194,7 @@ TEST_F(AddToSetNodeTest, ApplyToEmptyArray) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [1, 2]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -210,6 +214,7 @@ TEST_F(AddToSetNodeTest, ApplyDeduplicateElementsToAdd) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 1]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -230,6 +235,7 @@ TEST_F(AddToSetNodeTest, ApplyDoNotAddExistingElements) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 1]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -250,6 +256,7 @@ TEST_F(AddToSetNodeTest, ApplyDoNotDeduplicateExistingElements) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 0, 1]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -269,6 +276,7 @@ TEST_F(AddToSetNodeTest, ApplyNoElementsToAdd) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -288,6 +296,7 @@ TEST_F(AddToSetNodeTest, ApplyNoNonDuplicateElementsToAdd) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -307,6 +316,7 @@ TEST_F(AddToSetNodeTest, ApplyCreateArray) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 1]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -326,6 +336,7 @@ TEST_F(AddToSetNodeTest, ApplyCreateEmptyArrayIsNotNoop) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: []}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -348,6 +359,7 @@ TEST_F(AddToSetNodeTest, ApplyDeduplicationOfElementsToAddRespectsCollation) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: ['abc', 'def']}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -370,6 +382,7 @@ TEST_F(AddToSetNodeTest, ApplyComparisonToExistingElementsRespectsCollation) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: ['ABC', 'def']}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -393,6 +406,7 @@ TEST_F(AddToSetNodeTest, ApplyRespectsCollationFromSetCollator) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: ['abc', 'def']}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -438,6 +452,7 @@ TEST_F(AddToSetNodeTest, ApplyNestedArray) { auto result = node.apply(getApplyParams(doc.root()["a"][1]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{ _id : 1, a : [1, [1]] }"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -458,6 +473,7 @@ TEST_F(AddToSetNodeTest, ApplyIndexesNotAffected) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_FALSE(doc.isInPlaceModeEnabled()); assertOplogEntry(fromjson("{$v: 2, diff: {u: {a: [0, 1]}}}")); @@ -476,6 +492,7 @@ TEST_F(AddToSetNodeTest, ApplyNoIndexDataOrLogBuilder) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 1]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); diff --git a/src/mongo/db/update/arithmetic_node_test.cpp b/src/mongo/db/update/arithmetic_node_test.cpp index 9aeb06c5b88..328ecbb8d62 100644 --- a/src/mongo/db/update/arithmetic_node_test.cpp +++ b/src/mongo/db/update/arithmetic_node_test.cpp @@ -123,6 +123,7 @@ TEST_F(ArithmeticNodeTest, ApplyIncNoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 5}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -142,6 +143,7 @@ TEST_F(ArithmeticNodeTest, ApplyMulNoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 5}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -161,6 +163,7 @@ TEST_F(ArithmeticNodeTest, ApplyRoundingNoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 6.022e23}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -180,6 +183,7 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyPathToCreate) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 11}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -200,6 +204,7 @@ TEST_F(ArithmeticNodeTest, ApplyCreatePath) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {d: 5, b: {c: 6}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -220,6 +225,7 @@ TEST_F(ArithmeticNodeTest, ApplyExtendPath) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {c: 1, b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.b}"); @@ -237,6 +243,7 @@ TEST_F(ArithmeticNodeTest, ApplyCreatePathFromRoot) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{c: 5, a: {b: 6}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -257,6 +264,7 @@ TEST_F(ArithmeticNodeTest, ApplyPositional) { auto result = node.apply(getApplyParams(doc.root()["a"][1]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [0, 7, 2]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -295,6 +303,7 @@ TEST_F(ArithmeticNodeTest, ApplyNonViablePathToCreateFromReplicationIsNoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 5}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -314,6 +323,7 @@ TEST_F(ArithmeticNodeTest, ApplyNoIndexDataNoLogBuilder) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 11}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -331,6 +341,7 @@ TEST_F(ArithmeticNodeTest, ApplyDoesNotAffectIndexes) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 11}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -348,6 +359,7 @@ TEST_F(ArithmeticNodeTest, IncTypePromotionIsNotANoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: NumberLong(2)}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -365,6 +377,7 @@ TEST_F(ArithmeticNodeTest, MulTypePromotionIsNotANoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: NumberLong(2)}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -382,6 +395,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromIntToDecimalIsNotANoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: NumberDecimal(\"5.0\")}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -401,6 +415,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromLongToDecimalIsNotANoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: NumberDecimal(\"5.0\")}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -420,6 +435,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionFromDoubleToDecimalIsNotANoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: NumberDecimal(\"5.25\")}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -443,6 +459,7 @@ TEST_F(ArithmeticNodeTest, ApplyPromoteToFloatingPoint) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1.2}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -460,6 +477,7 @@ TEST_F(ArithmeticNodeTest, IncrementedDecimalStaysDecimal) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: NumberDecimal(\"11.5\")}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -485,6 +503,7 @@ TEST_F(ArithmeticNodeTest, OverflowIntToLong) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(mongo::NumberLong, doc.root()["a"].getType()); ASSERT_EQUALS(BSON("a" << static_cast<long long>(initialValue) + 1), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -505,6 +524,7 @@ TEST_F(ArithmeticNodeTest, UnderflowIntToLong) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(mongo::NumberLong, doc.root()["a"].getType()); ASSERT_EQUALS(BSON("a" << static_cast<long long>(initialValue) - 1), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -524,6 +544,7 @@ TEST_F(ArithmeticNodeTest, IncModeCanBeReused) { auto result = node.apply(getApplyParams(doc1.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 2}"), doc1); ASSERT_TRUE(doc1.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -534,6 +555,7 @@ TEST_F(ArithmeticNodeTest, IncModeCanBeReused) { result = node.apply(getApplyParams(doc2.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 3}"), doc2); ASSERT_TRUE(doc1.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -551,6 +573,7 @@ TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsInc) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{b: 6, a: NumberLong(5)}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -568,6 +591,7 @@ TEST_F(ArithmeticNodeTest, CreatedNumberHasSameTypeAsMul) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{b: 6, a: NumberLong(0)}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -585,6 +609,7 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyDocument) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -671,6 +696,7 @@ TEST_F(ArithmeticNodeTest, ApplyNewPath) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{b: 1, a: 2}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -704,6 +730,7 @@ TEST_F(ArithmeticNodeTest, ApplyNoOpDottedPath) { auto result = node.apply(getApplyParams(doc.root()["a"]["b"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b : 2}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.b}"); @@ -721,6 +748,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionOnDottedPathIsNotANoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]["b"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b : NumberLong(2)}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.b}"); @@ -754,6 +782,7 @@ TEST_F(ArithmeticNodeTest, ApplyInPlaceDottedPath) { auto result = node.apply(getApplyParams(doc.root()["a"]["b"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: 3}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.b}"); @@ -771,6 +800,7 @@ TEST_F(ArithmeticNodeTest, ApplyPromotionDottedPath) { auto result = node.apply(getApplyParams(doc.root()["a"]["b"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: NumberLong(5)}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.b}"); @@ -788,6 +818,7 @@ TEST_F(ArithmeticNodeTest, ApplyDottedPathEmptyDoc) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.b}"); @@ -805,6 +836,7 @@ TEST_F(ArithmeticNodeTest, ApplyFieldWithDot) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{'a.b':4, a: {b: 2}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.b}"); @@ -822,6 +854,7 @@ TEST_F(ArithmeticNodeTest, ApplyNoOpArrayIndex) { auto result = node.apply(getApplyParams(doc.root()["a"][2]["b"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.2.b}"); @@ -840,6 +873,7 @@ TEST_F(ArithmeticNodeTest, TypePromotionInArrayIsNotANoOp) { auto result = node.apply(getApplyParams(doc.root()["a"][2]["b"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: NumberLong(2)}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.2.b}"); @@ -873,6 +907,7 @@ TEST_F(ArithmeticNodeTest, ApplyInPlaceArrayIndex) { auto result = node.apply(getApplyParams(doc.root()["a"][2]["b"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: 3}]}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.2.b}"); @@ -891,6 +926,7 @@ TEST_F(ArithmeticNodeTest, ApplyAppendArray) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [{b: 0},{b: 1},{b: 2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -909,6 +945,7 @@ TEST_F(ArithmeticNodeTest, ApplyPaddingArray) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [{b: 0},null,{b: 2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -927,6 +964,7 @@ TEST_F(ArithmeticNodeTest, ApplyNumericObject) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: 0, '2': {b: 2}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.2.b}"); @@ -947,6 +985,7 @@ TEST_F(ArithmeticNodeTest, ApplyNumericField) { auto result = node.apply(getApplyParams(doc.root()["a"]["2"]["b"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {'2': {b: 3}}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.2.b}"); @@ -967,6 +1006,7 @@ TEST_F(ArithmeticNodeTest, ApplyExtendNumericField) { auto result = node.apply(getApplyParams(doc.root()["a"]["2"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {'2': {c: 1, b: 2}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.2.b}"); @@ -985,6 +1025,7 @@ TEST_F(ArithmeticNodeTest, ApplyNumericFieldToEmptyObject) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {'2': {b: 2}}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a.2.b}"); @@ -1003,6 +1044,7 @@ TEST_F(ArithmeticNodeTest, ApplyEmptyArray) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: [null, null, {b: 2}]}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); ASSERT_EQUALS(getModifiedPaths(), "{a}"); @@ -1073,6 +1115,7 @@ TEST_F(ArithmeticNodeTest, ApplyDeserializedDocNotNoOp) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1, b: NumberInt(0)}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -1094,6 +1137,7 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNoOp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: NumberInt(2)}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -1115,6 +1159,7 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNestedNoop) { auto result = node.apply(getApplyParams(doc.root()["a"]["b"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: NumberInt(1)}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -1136,6 +1181,7 @@ TEST_F(ArithmeticNodeTest, ApplyToDeserializedDocNestedNotNoop) { auto result = node.apply(getApplyParams(doc.root()["a"]["b"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: 3}}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); diff --git a/src/mongo/db/update/compare_node_test.cpp b/src/mongo/db/update/compare_node_test.cpp index 367525b1356..c72d0a41fe5 100644 --- a/src/mongo/db/update/compare_node_test.cpp +++ b/src/mongo/db/update/compare_node_test.cpp @@ -68,6 +68,7 @@ TEST_F(CompareNodeTest, ApplyMaxSameNumber) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -86,6 +87,7 @@ TEST_F(CompareNodeTest, ApplyMinSameNumber) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -104,6 +106,7 @@ TEST_F(CompareNodeTest, ApplyMaxNumberIsLess) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -122,6 +125,7 @@ TEST_F(CompareNodeTest, ApplyMinNumberIsMore) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -140,6 +144,7 @@ TEST_F(CompareNodeTest, ApplyMaxSameValInt) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1.0}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -158,6 +163,7 @@ TEST_F(CompareNodeTest, ApplyMaxSameValIntZero) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 0.0}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -176,6 +182,7 @@ TEST_F(CompareNodeTest, ApplyMinSameValIntZero) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 0.0}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -194,6 +201,7 @@ TEST_F(CompareNodeTest, ApplyMissingFieldMinNumber) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 0}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -212,6 +220,7 @@ TEST_F(CompareNodeTest, ApplyExistingNumberMinNumber) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 0}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -230,6 +239,7 @@ TEST_F(CompareNodeTest, ApplyMissingFieldMaxNumber) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 0}"), doc); ASSERT_FALSE(doc.isInPlaceModeEnabled()); @@ -248,6 +258,7 @@ TEST_F(CompareNodeTest, ApplyExistingNumberMaxNumber) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 2}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -266,6 +277,7 @@ TEST_F(CompareNodeTest, ApplyExistingDateMaxDate) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {$date: 123123123}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -284,6 +296,7 @@ TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxDoc) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: 3}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -302,6 +315,7 @@ TEST_F(CompareNodeTest, ApplyExistingEmbeddedDocMaxNumber) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_TRUE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: {b: 2}}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -323,6 +337,7 @@ TEST_F(CompareNodeTest, ApplyMinRespectsCollation) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 'dba'}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -345,6 +360,7 @@ TEST_F(CompareNodeTest, ApplyMinRespectsCollationFromSetCollator) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 'dba'}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -367,6 +383,7 @@ TEST_F(CompareNodeTest, ApplyMaxRespectsCollationFromSetCollator) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 'abd'}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -411,6 +428,7 @@ TEST_F(CompareNodeTest, ApplyIndexesNotAffected) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); @@ -429,6 +447,7 @@ TEST_F(CompareNodeTest, ApplyNoIndexDataOrLogBuilder) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(fromjson("{a: 1}"), doc); ASSERT_TRUE(doc.isInPlaceModeEnabled()); } diff --git a/src/mongo/db/update/current_date_node_test.cpp b/src/mongo/db/update/current_date_node_test.cpp index 540a4b26f3b..2643d2bd28a 100644 --- a/src/mongo/db/update/current_date_node_test.cpp +++ b/src/mongo/db/update/current_date_node_test.cpp @@ -143,6 +143,7 @@ TEST_F(CurrentDateNodeTest, ApplyTrue) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(doc.root().countChildren(), 1U); ASSERT_TRUE(doc.root()["a"].ok()); @@ -163,6 +164,7 @@ TEST_F(CurrentDateNodeTest, ApplyFalse) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(doc.root().countChildren(), 1U); ASSERT_TRUE(doc.root()["a"].ok()); @@ -183,6 +185,7 @@ TEST_F(CurrentDateNodeTest, ApplyDate) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(doc.root().countChildren(), 1U); ASSERT_TRUE(doc.root()["a"].ok()); @@ -203,6 +206,7 @@ TEST_F(CurrentDateNodeTest, ApplyTimestamp) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(doc.root().countChildren(), 1U); ASSERT_TRUE(doc.root()["a"].ok()); @@ -223,6 +227,7 @@ TEST_F(CurrentDateNodeTest, ApplyFieldDoesNotExist) { auto result = node.apply(getApplyParams(doc.root()), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_TRUE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(doc.root().countChildren(), 1U); ASSERT_TRUE(doc.root()["a"].ok()); @@ -245,6 +250,7 @@ TEST_F(CurrentDateNodeTest, ApplyIndexesNotAffected) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); assertOplogEntryIsUpdateOfExpectedType(getOplogEntry(), "a"); } @@ -261,6 +267,7 @@ TEST_F(CurrentDateNodeTest, ApplyNoIndexDataOrLogBuilder) { auto result = node.apply(getApplyParams(doc.root()["a"]), getUpdateNodeApplyParams()); ASSERT_FALSE(result.noop); ASSERT_FALSE(result.indexesAffected); + ASSERT_EQUALS(result.indexesAffected, getIndexAffectedFromLogEntry()); ASSERT_EQUALS(doc.root().countChildren(), 1U); ASSERT_TRUE(doc.root()["a"].ok()); diff --git a/src/mongo/db/update/document_diff_calculator.cpp b/src/mongo/db/update/document_diff_calculator.cpp index 19969f7644f..5252a8ebd0a 100644 --- a/src/mongo/db/update/document_diff_calculator.cpp +++ b/src/mongo/db/update/document_diff_calculator.cpp @@ -334,6 +334,114 @@ void serializeInlineDiff(diff_tree::DocumentSubDiffNode const* node, BSONObjBuil } } } + +void anyIndexesMightBeAffected(ArrayDiffReader* reader, + const std::vector<const UpdateIndexData*>& indexData, + FieldRef* fieldRef, + BitVector* result); + +void anyIndexesMightBeAffected(DocumentDiffReader* reader, + const std::vector<const UpdateIndexData*>& indexData, + FieldRef* fieldRef, + BitVector* result) { + boost::optional<StringData> delItem; + while ((delItem = reader->nextDelete())) { + FieldRef::FieldRefTempAppend tempAppend(*fieldRef, *delItem); + for (size_t i = 0; i < indexData.size(); i++) { + if (!(*result)[i]) { + (*result)[i] = indexData[i]->mightBeIndexed(*fieldRef); + } + } + // early exit + if (result->all()) { + return; + } + } + + boost::optional<BSONElement> updItem; + while ((updItem = reader->nextUpdate())) { + FieldRef::FieldRefTempAppend tempAppend(*fieldRef, updItem->fieldNameStringData()); + for (size_t i = 0; i < indexData.size(); i++) { + if (!(*result)[i]) { + (*result)[i] = indexData[i]->mightBeIndexed(*fieldRef); + } + } + // early exit + if (result->all()) { + return; + } + } + + boost::optional<BSONElement> insItem; + while ((insItem = reader->nextInsert())) { + FieldRef::FieldRefTempAppend tempAppend(*fieldRef, insItem->fieldNameStringData()); + for (size_t i = 0; i < indexData.size(); i++) { + if (!(*result)[i]) { + (*result)[i] = indexData[i]->mightBeIndexed(*fieldRef); + } + } + // early exit + if (result->all()) { + return; + } + } + + for (auto subItem = reader->nextSubDiff(); subItem; subItem = reader->nextSubDiff()) { + FieldRef::FieldRefTempAppend tempAppend(*fieldRef, subItem->first); + stdx::visit( + OverloadedVisitor{[&indexData, &fieldRef, &result](DocumentDiffReader& item) { + anyIndexesMightBeAffected(&item, indexData, fieldRef, result); + }, + [&indexData, &fieldRef, &result](ArrayDiffReader& item) { + anyIndexesMightBeAffected(&item, indexData, fieldRef, result); + }}, + subItem->second); + // early exit + if (result->all()) { + return; + } + } +} + +void anyIndexesMightBeAffected(ArrayDiffReader* reader, + const std::vector<const UpdateIndexData*>& indexData, + FieldRef* fieldRef, + BitVector* result) { + if (reader->newSize()) { + for (size_t i = 0; i < indexData.size(); i++) { + if (!(*result)[i]) { + (*result)[i] = indexData[i]->mightBeIndexed(*fieldRef); + } + } + // early exit + if (result->all()) { + return; + } + } + for (auto item = reader->next(); item; item = reader->next()) { + auto idxAsStr = std::to_string(item->first); + FieldRef::FieldRefTempAppend tempAppend(*fieldRef, idxAsStr); + stdx::visit( + OverloadedVisitor{[&indexData, &fieldRef, &result](BSONElement& update) { + for (size_t i = 0; i < indexData.size(); i++) { + if (!(*result)[i]) { + (*result)[i] = indexData[i]->mightBeIndexed(*fieldRef); + } + } + }, + [&indexData, &fieldRef, &result](DocumentDiffReader& item) { + anyIndexesMightBeAffected(&item, indexData, fieldRef, result); + }, + [&indexData, &fieldRef, &result](ArrayDiffReader& item) { + anyIndexesMightBeAffected(&item, indexData, fieldRef, result); + }}, + item->second); + // early exit + if (result->all()) { + return; + } + } +} } // namespace boost::optional<DiffResult> computeOplogDiff(const BSONObj& pre, @@ -362,4 +470,18 @@ boost::optional<BSONObj> computeInlineDiff(const BSONObj& pre, const BSONObj& po return bob.obj(); } + +BitVector anyIndexesMightBeAffected(const Diff& diff, + const std::vector<const UpdateIndexData*>& indexData) { + invariant(!indexData.empty()); + BitVector result(indexData.size()); + if (diff.isEmpty()) { + return result; + } + + DocumentDiffReader reader(diff); + FieldRef path; + anyIndexesMightBeAffected(&reader, indexData, &path, &result); + return result; +} } // namespace mongo::doc_diff diff --git a/src/mongo/db/update/document_diff_calculator.h b/src/mongo/db/update/document_diff_calculator.h index a8ce159edbf..f1850a34e03 100644 --- a/src/mongo/db/update/document_diff_calculator.h +++ b/src/mongo/db/update/document_diff_calculator.h @@ -29,11 +29,12 @@ #pragma once +#include "boost/dynamic_bitset.hpp" + #include "mongo/bson/bsonobj.h" #include "mongo/db/update/document_diff_serialization.h" #include "mongo/db/update_index_data.h" - namespace mongo::doc_diff { struct DiffResult { @@ -81,4 +82,13 @@ boost::optional<DiffResult> computeOplogDiff(const BSONObj& pre, */ boost::optional<BSONObj> computeInlineDiff(const BSONObj& pre, const BSONObj& post); +using BitVector = boost::dynamic_bitset<size_t>; +/** + * Returns a bitset of the same size of the indexData argument, where each bit indicates + * whether one of the modifications described in the diff document affects one of the + * indexed paths described in the matching object. + */ +BitVector anyIndexesMightBeAffected(const Diff& diff, + const std::vector<const UpdateIndexData*>& indexData); + }; // namespace mongo::doc_diff diff --git a/src/mongo/db/update/update_node_test_fixture.h b/src/mongo/db/update/update_node_test_fixture.h index 5125c77cfce..609eb1f2833 100644 --- a/src/mongo/db/update/update_node_test_fixture.h +++ b/src/mongo/db/update/update_node_test_fixture.h @@ -31,7 +31,9 @@ #include "mongo/db/concurrency/locker_noop_service_context_test_fixture.h" #include "mongo/db/service_context.h" +#include "mongo/db/update/document_diff_calculator.h" #include "mongo/db/update/update_node.h" +#include "mongo/db/update/update_oplog_entry_serialization.h" #include "mongo/db/update/v2_log_builder.h" #include "mongo/unittest/unittest.h" @@ -89,6 +91,21 @@ protected: return applyParams; } + bool getIndexAffectedFromLogEntry() { + if (!_logBuilder || !_indexData) { + return false; + } + // Keep the object alive, extractDiffFromOplogEntry returns a subdocument of this document. + BSONObj logEntry = getOplogEntry(); + auto diff = update_oplog_entry::extractDiffFromOplogEntry(logEntry); + if (!diff) { + return false; + } + return mongo::doc_diff::anyIndexesMightBeAffected( + *diff, std::vector<const UpdateIndexData*>{_indexData.get()}) + .any(); + } + UpdateNode::UpdateNodeApplyParams getUpdateNodeApplyParams() { UpdateNode::UpdateNodeApplyParams applyParams; applyParams.pathToCreate = _pathToCreate; diff --git a/src/mongo/db/update/update_oplog_entry_serialization.cpp b/src/mongo/db/update/update_oplog_entry_serialization.cpp index 274fe568baa..daee76db1c2 100644 --- a/src/mongo/db/update/update_oplog_entry_serialization.cpp +++ b/src/mongo/db/update/update_oplog_entry_serialization.cpp @@ -40,6 +40,18 @@ BSONObj makeDeltaOplogEntry(const doc_diff::Diff& diff) { return builder.obj(); } +boost::optional<BSONObj> extractDiffFromOplogEntry(const BSONObj& opLog) { + auto version = opLog["$v"]; + if (version.ok() && + version.numberInt() == static_cast<int>(UpdateOplogEntryVersion::kDeltaV2)) { + auto diff = opLog[kDiffObjectFieldName]; + if (diff.type() == BSONType::Object) { + return diff.embeddedObject(); + } + } + return {}; +} + namespace { BSONElement extractNewValueForFieldFromV1Entry(const BSONObj& oField, StringData fieldName) { // Check the '$set' section. diff --git a/src/mongo/db/update/update_oplog_entry_serialization.h b/src/mongo/db/update/update_oplog_entry_serialization.h index 24ace4c3315..a438c9ee5e2 100644 --- a/src/mongo/db/update/update_oplog_entry_serialization.h +++ b/src/mongo/db/update/update_oplog_entry_serialization.h @@ -67,6 +67,11 @@ enum class FieldRemovedStatus { kFieldRemoved, kFieldNotRemoved, kUnknown }; BSONObj makeDeltaOplogEntry(const doc_diff::Diff& diff); /** + * Given a $v: 2 delta-style oplog entry, return the embedded diff object. + */ +boost::optional<BSONObj> extractDiffFromOplogEntry(const BSONObj& opLog); + +/** * Produce the contents of the 'o' field of a replacement style oplog entry. */ inline BSONObj makeReplacementOplogEntry(const BSONObj& replacement) { diff --git a/src/mongo/db/update_index_data.cpp b/src/mongo/db/update_index_data.cpp index 5d1ce33fc34..0c5a6a4f5b8 100644 --- a/src/mongo/db/update_index_data.cpp +++ b/src/mongo/db/update_index_data.cpp @@ -126,6 +126,10 @@ void UpdateIndexData::clear() { _allPathsIndexed = false; } +bool UpdateIndexData::isEmpty() const { + return !_allPathsIndexed && _canonicalPaths.empty() && _pathComponents.empty(); +} + bool UpdateIndexData::mightBeIndexed(const FieldRef& path) const { if (_allPathsIndexed) { return true; diff --git a/src/mongo/db/update_index_data.h b/src/mongo/db/update_index_data.h index 7fb7f5f553b..d23f0fbea9c 100644 --- a/src/mongo/db/update_index_data.h +++ b/src/mongo/db/update_index_data.h @@ -78,6 +78,11 @@ public: bool mightBeIndexed(const FieldRef& path) const; + /** + * Return whether this structure has been cleared or has not been initialized yet. + */ + bool isEmpty() const; + private: /** * Returns true if 'b' is a prefix of 'a', or if the two paths are equal. diff --git a/src/mongo/dbtests/multikey_paths_test.cpp b/src/mongo/dbtests/multikey_paths_test.cpp index f77b68b7c44..6498311e026 100644 --- a/src/mongo/dbtests/multikey_paths_test.cpp +++ b/src/mongo/dbtests/multikey_paths_test.cpp @@ -251,7 +251,6 @@ TEST_F(MultikeyPathsTest, PathsUpdatedOnDocumentUpdate) { auto oldDoc = collection->docFor(_opCtx.get(), record->id); { WriteUnitOfWork wuow(_opCtx.get()); - const bool indexesAffected = true; OpDebug* opDebug = nullptr; CollectionUpdateArgs args{oldDoc.value()}; collection_internal::updateDocument( @@ -260,7 +259,7 @@ TEST_F(MultikeyPathsTest, PathsUpdatedOnDocumentUpdate) { record->id, oldDoc, BSON("_id" << 0 << "a" << 5 << "b" << BSON_ARRAY(1 << 2 << 3)), - indexesAffected, + collection_internal::kUpdateAllIndexes, opDebug, &args); wuow.commit(); @@ -302,19 +301,18 @@ TEST_F(MultikeyPathsTest, PathsUpdatedOnDocumentUpdateWithDamages) { auto damagesOutput = doc_diff::computeDamages(oldDoc.value(), diffResult->diff, false); { WriteUnitOfWork wuow(_opCtx.get()); - const bool indexesAffected = true; OpDebug* opDebug = nullptr; CollectionUpdateArgs args{oldDoc.value()}; - auto newDocResult = - collection_internal::updateDocumentWithDamages(_opCtx.get(), - *collection, - record->id, - oldDoc, - damagesOutput.damageSource.get(), - damagesOutput.damages, - indexesAffected, - opDebug, - &args); + auto newDocResult = collection_internal::updateDocumentWithDamages( + _opCtx.get(), + *collection, + record->id, + oldDoc, + damagesOutput.damageSource.get(), + damagesOutput.damages, + collection_internal::kUpdateAllIndexes, + opDebug, + &args); ASSERT_TRUE(newDocResult.getValue().woCompare(newDoc) == 0); ASSERT_TRUE(newDocResult.isOK()); wuow.commit(); diff --git a/src/mongo/dbtests/query_stage_count.cpp b/src/mongo/dbtests/query_stage_count.cpp index d5db5948ddb..c4b7df24d5d 100644 --- a/src/mongo/dbtests/query_stage_count.cpp +++ b/src/mongo/dbtests/query_stage_count.cpp @@ -131,7 +131,7 @@ public: oldrecordId, Snapshotted<BSONObj>(_opCtx.recoveryUnit()->getSnapshotId(), oldDoc), newDoc, - true, + collection_internal::kUpdateAllIndexes, nullptr, &args); wunit.commit(); diff --git a/src/mongo/dbtests/query_stage_sort.cpp b/src/mongo/dbtests/query_stage_sort.cpp index fed69ed967a..d7b67d4cb85 100644 --- a/src/mongo/dbtests/query_stage_sort.cpp +++ b/src/mongo/dbtests/query_stage_sort.cpp @@ -400,8 +400,14 @@ public: CollectionUpdateArgs args{oldDoc.value()}; { WriteUnitOfWork wuow(&_opCtx); - collection_internal::updateDocument( - &_opCtx, coll, *it, oldDoc, newDoc(oldDoc), false, nullptr, &args); + collection_internal::updateDocument(&_opCtx, + coll, + *it, + oldDoc, + newDoc(oldDoc), + collection_internal::kUpdateNoIndexes, + nullptr, + &args); wuow.commit(); } exec->restoreState(&coll); @@ -419,8 +425,14 @@ public: oldDoc = coll->docFor(&_opCtx, *it); { WriteUnitOfWork wuow(&_opCtx); - collection_internal::updateDocument( - &_opCtx, coll, *it++, oldDoc, newDoc(oldDoc), false, nullptr, &args); + collection_internal::updateDocument(&_opCtx, + coll, + *it++, + oldDoc, + newDoc(oldDoc), + collection_internal::kUpdateNoIndexes, + nullptr, + &args); wuow.commit(); } } |