diff options
author | David Storch <david.storch@10gen.com> | 2016-09-26 13:47:05 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2016-09-26 17:56:56 -0400 |
commit | 1d6dce66f73719e8bf710d5e1e19169b27f91344 (patch) | |
tree | 4e349ca3714ee4b16cd84616a7a1d4531b03c39d | |
parent | 50fd4e6c8e735ab00879547365f61a808b3f0313 (diff) | |
download | mongo-1d6dce66f73719e8bf710d5e1e19169b27f91344.tar.gz |
SERVER-24755 fix explain to handle collection drop during yield
-rw-r--r-- | src/mongo/db/query/explain.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/query/plan_executor.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/query/plan_executor.h | 4 |
3 files changed, 16 insertions, 1 deletions
diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp index 944c730ebf4..ab63567f770 100644 --- a/src/mongo/db/query/explain.cpp +++ b/src/mongo/db/query/explain.cpp @@ -722,13 +722,18 @@ void Explain::explainStages(PlanExecutor* exec, executePlanStatus = exec->executePlan(); } + // If executing the query failed because it was killed, then the collection may no longer be + // valid. We indicate this by setting our collection pointer to null. + if (executePlanStatus == ErrorCodes::QueryPlanKilled) { + collection = nullptr; + } + // Get stats for the winning plan. If there is only a single candidate plan, it is considered // the winner. unique_ptr<PlanStageStats> winningStats( mps ? std::move(mps->getStats()->children[mps->bestPlanIdx()]) : std::move(exec->getStats())); - // // Use the stats trees to produce explain BSON. // diff --git a/src/mongo/db/query/plan_executor.cpp b/src/mongo/db/query/plan_executor.cpp index ec4d3bf0c1d..d162e998bab 100644 --- a/src/mongo/db/query/plan_executor.cpp +++ b/src/mongo/db/query/plan_executor.cpp @@ -530,12 +530,18 @@ Status PlanExecutor::executePlan() { } if (PlanExecutor::DEAD == state || PlanExecutor::FAILURE == state) { + if (killed()) { + return Status(ErrorCodes::QueryPlanKilled, + str::stream() << "Operation aborted because: " << *_killReason); + } + return Status(ErrorCodes::OperationFailed, str::stream() << "Exec error: " << WorkingSetCommon::toStatusString(obj) << ", state: " << PlanExecutor::statestr(state)); } + invariant(!killed()); invariant(PlanExecutor::IS_EOF == state); return Status::OK(); } diff --git a/src/mongo/db/query/plan_executor.h b/src/mongo/db/query/plan_executor.h index a321ded213d..207fc6765c2 100644 --- a/src/mongo/db/query/plan_executor.h +++ b/src/mongo/db/query/plan_executor.h @@ -298,6 +298,10 @@ public: * underlying tree without getting results back. * * If a YIELD_AUTO policy is set on this executor, then this will automatically yield. + * + * Returns ErrorCodes::QueryPlanKilled if the plan executor was killed during a yield. If this + * error occurs, it is illegal to subsequently access the collection, since it may have been + * dropped. */ Status executePlan(); |