// static bool WorkingSetCommon::fetch(OperationContext* txn, WorkingSet* workingSet, WorkingSetID id, unowned_ptr<SeekableRecordCursor> cursor) { WorkingSetMember* member = workingSet->get(id); // The RecordFetcher should already have been transferred out of the WSM and used. invariant(!member->hasFetcher()); // We should have a RecordId but need to retrieve the obj. Get the obj now and reset all WSM // state appropriately. invariant(member->hasRecordId()); member->obj.reset(); auto record = cursor->seekExact(member->recordId); if (!record) { return false; } member->obj = {txn->recoveryUnit()->getSnapshotId(), record->data.releaseToBson()}; if (member->isSuspicious) { // Make sure that all of the keyData is still valid for this copy of the document. // This ensures both that index-provided filters and sort orders still hold. // TODO provide a way for the query planner to opt out of this checking if it is // unneeded due to the structure of the plan. invariant(!member->keyData.empty()); for (size_t i = 0; i < member->keyData.size(); i++) { BSONObjSet keys; // There's no need to compute the prefixes of the indexed fields that cause the index to // be multikey when ensuring the keyData is still valid. MultikeyPaths* multikeyPaths = nullptr; member->keyData[i].index->getKeys(member->obj.value(), &keys, multikeyPaths); if (!keys.count(member->keyData[i].keyData)) { // document would no longer be at this position in the index. return false; } } member->isSuspicious = false; } member->keyData.clear(); workingSet->transitionToRecordIdAndObj(id); return true; }
// static bool WorkingSetCommon::fetch(OperationContext* txn, WorkingSetMember* member, unowned_ptr<RecordCursor> cursor) { // The RecordFetcher should already have been transferred out of the WSM and used. invariant(!member->hasFetcher()); // We should have a RecordId but need to retrieve the obj. Get the obj now and reset all WSM // state appropriately. invariant(member->hasLoc()); member->obj.reset(); auto record = cursor->seekExact(member->loc); if (!record) { return false; } member->obj = {txn->recoveryUnit()->getSnapshotId(), record->data.releaseToBson()}; if (member->isSuspicious) { // Make sure that all of the keyData is still valid for this copy of the document. // This ensures both that index-provided filters and sort orders still hold. // TODO provide a way for the query planner to opt out of this checking if it is // unneeded due to the structure of the plan. invariant(!member->keyData.empty()); for (size_t i = 0; i < member->keyData.size(); i++) { BSONObjSet keys; member->keyData[i].index->getKeys(member->obj.value(), &keys); if (!keys.count(member->keyData[i].keyData)) { // document would no longer be at this position in the index. return false; } } member->isSuspicious = false; } member->keyData.clear(); member->state = WorkingSetMember::LOC_AND_UNOWNED_OBJ; return true; }