UpdateResult UpdateExecutor::execute(Database* db) { uassertStatusOK(prepare()); LOG(3) << "processing update : " << *_request; // If we've already done the in-lock preparation, this is a no-op. Status status = prepareInLock(db); uassert(17243, "could not get executor " + _request->getQuery().toString() + "; " + causedBy(status), status.isOK()); // Run the plan (don't need to collect results because UpdateStage always returns // NEED_TIME). uassertStatusOK(_exec->executePlan()); // Get stats from the root stage. invariant(_exec->getRootStage()->stageType() == STAGE_UPDATE); UpdateStage* updateStage = static_cast<UpdateStage*>(_exec->getRootStage()); const UpdateStats* updateStats = static_cast<const UpdateStats*>(updateStage->getSpecificStats()); // Use stats from the root stage to fill out opDebug. _opDebug->nMatched = updateStats->nMatched; _opDebug->nModified = updateStats->nModified; _opDebug->upsert = updateStats->inserted; _opDebug->fastmodinsert = updateStats->fastmodinsert; _opDebug->fastmod = updateStats->fastmod; // Historically, 'opDebug' considers 'nMatched' and 'nModified' to be 1 (rather than 0) if // there is an upsert that inserts a document. The UpdateStage does not participate in this // madness in order to have saner stats reporting for explain. This means that we have to // set these values "manually" in the case of an insert. if (updateStats->inserted) { _opDebug->nMatched = 1; _opDebug->nModified = 1; } // Get summary information about the plan. PlanSummaryStats stats; Explain::getSummaryStats(_exec.get(), &stats); _opDebug->nscanned = stats.totalKeysExamined; _opDebug->nscannedObjects = stats.totalDocsExamined; return UpdateResult(updateStats->nMatched > 0 /* Did we update at least one obj? */, !_driver.isDocReplacement() /* $mod or obj replacement */, _opDebug->nModified /* number of modified docs, no no-ops */, _opDebug->nMatched /* # of docs matched/updated, even no-ops */, updateStats->objInserted); }
long long DeleteExecutor::execute(Database* db) { uassertStatusOK(prepare()); // If we've already done the in-lock preparation, this is a no-op. uassertStatusOK(prepareInLock(db)); invariant(_exec.get()); uassertStatusOK(_exec->executePlan()); // Extract the number of documents deleted from the DeleteStage stats. invariant(_exec->getRootStage()->stageType() == STAGE_DELETE); DeleteStage* deleteStage = static_cast<DeleteStage*>(_exec->getRootStage()); const DeleteStats* deleteStats = static_cast<const DeleteStats*>(deleteStage->getSpecificStats()); return deleteStats->docsDeleted; }