summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Boros <ian.boros@mongodb.com>2020-03-03 15:26:40 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-04-13 21:11:41 +0000
commit5388b23cb85e84eb4ce5a2c03b250e62ff89ea1f (patch)
tree5f607e0c9b5e8bd333ffdfc600abfbea5e99b32b
parentc58d35e8b8cd53875a4296e5e70070e2667194d9 (diff)
downloadmongo-5388b23cb85e84eb4ce5a2c03b250e62ff89ea1f.tar.gz
SERVER-46921 make collection of timing info opt in in PlanStage
-rw-r--r--src/mongo/db/commands/find_cmd.cpp3
-rw-r--r--src/mongo/db/commands/list_collections.cpp8
-rw-r--r--src/mongo/db/commands/list_indexes.cpp2
-rw-r--r--src/mongo/db/commands/map_reduce_agg.cpp4
-rw-r--r--src/mongo/db/commands/run_aggregate.cpp3
-rw-r--r--src/mongo/db/curop.h4
-rw-r--r--src/mongo/db/exec/cached_plan.cpp2
-rw-r--r--src/mongo/db/exec/multi_plan.cpp16
-rw-r--r--src/mongo/db/exec/plan_stage.cpp22
-rw-r--r--src/mongo/db/exec/plan_stage.h47
-rw-r--r--src/mongo/db/exec/plan_stats.h10
-rw-r--r--src/mongo/db/exec/scoped_timer.h1
-rw-r--r--src/mongo/db/exec/stagedebug_cmd.cpp2
-rw-r--r--src/mongo/db/exec/subplan.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source.cpp6
-rw-r--r--src/mongo/db/pipeline/document_source.h5
-rw-r--r--src/mongo/db/pipeline/expression_context.cpp17
-rw-r--r--src/mongo/db/pipeline/expression_context.h18
-rw-r--r--src/mongo/db/pipeline/expression_context_for_test.h11
-rw-r--r--src/mongo/db/pipeline/pipeline.cpp3
-rw-r--r--src/mongo/db/pipeline/pipeline_d.cpp2
-rw-r--r--src/mongo/db/query/explain.cpp10
-rw-r--r--src/mongo/db/query/get_executor.cpp12
-rw-r--r--src/mongo/db/query/internal_plans.cpp12
-rw-r--r--src/mongo/db/query/plan_executor.h13
-rw-r--r--src/mongo/db/query/plan_executor_impl.cpp19
-rw-r--r--src/mongo/db/query/plan_summary_stats.h3
-rw-r--r--src/mongo/dbtests/cursor_manager_test.cpp2
-rw-r--r--src/mongo/dbtests/documentsourcetests.cpp8
-rw-r--r--src/mongo/dbtests/query_plan_executor.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_collscan.cpp8
-rw-r--r--src/mongo/dbtests/query_stage_merge_sort.cpp16
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp2
-rw-r--r--src/mongo/dbtests/query_stage_sort.cpp6
-rw-r--r--src/mongo/dbtests/query_stage_tests.cpp2
-rw-r--r--src/mongo/s/commands/cluster_map_reduce_agg.cpp4
36 files changed, 179 insertions, 128 deletions
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 6046efd2364..d578e04ca6d 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -113,7 +113,8 @@ boost::intrusive_ptr<ExpressionContext> makeExpressionContext(
std::move(collator),
nullptr, // mongoProcessInterface
StringMap<ExpressionContext::ResolvedNamespace>{},
- boost::none // uuid
+ boost::none, // uuid
+ CurOp::get(opCtx)->dbProfileLevel() > 0 // mayDbProfile
);
expCtx->tempDir = storageGlobalParams.dbpath + "/_tmp";
return expCtx;
diff --git a/src/mongo/db/commands/list_collections.cpp b/src/mongo/db/commands/list_collections.cpp
index fae03f2159a..7c4517c0744 100644
--- a/src/mongo/db/commands/list_collections.cpp
+++ b/src/mongo/db/commands/list_collections.cpp
@@ -364,8 +364,12 @@ public:
}
}
- exec = uassertStatusOK(PlanExecutor::make(
- opCtx, std::move(ws), std::move(root), nullptr, PlanExecutor::NO_YIELD, cursorNss));
+ exec = uassertStatusOK(PlanExecutor::make(expCtx,
+ std::move(ws),
+ std::move(root),
+ nullptr,
+ PlanExecutor::NO_YIELD,
+ cursorNss));
for (long long objCount = 0; objCount < batchSize; objCount++) {
Document nextDoc;
diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp
index 0c3cf1c3053..b50fbc89ad6 100644
--- a/src/mongo/db/commands/list_indexes.cpp
+++ b/src/mongo/db/commands/list_indexes.cpp
@@ -174,7 +174,7 @@ public:
}
exec = uassertStatusOK(PlanExecutor::make(
- opCtx, std::move(ws), std::move(root), nullptr, PlanExecutor::NO_YIELD, nss));
+ expCtx, std::move(ws), std::move(root), nullptr, PlanExecutor::NO_YIELD, nss));
for (long long objCount = 0; objCount < batchSize; objCount++) {
Document nextDoc;
diff --git a/src/mongo/db/commands/map_reduce_agg.cpp b/src/mongo/db/commands/map_reduce_agg.cpp
index 4f29ccdb627..4535e0d8abd 100644
--- a/src/mongo/db/commands/map_reduce_agg.cpp
+++ b/src/mongo/db/commands/map_reduce_agg.cpp
@@ -96,7 +96,9 @@ auto makeExpressionContext(OperationContext* opCtx,
std::move(resolvedCollator),
MongoProcessInterface::create(opCtx),
StringMap<ExpressionContext::ResolvedNamespace>{}, // resolvedNamespaces
- uuid);
+ uuid,
+ CurOp::get(opCtx)->dbProfileLevel() > 0 // mayDbProfile
+ );
expCtx->tempDir = storageGlobalParams.dbpath + "/_tmp";
return expCtx;
}
diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp
index 6f8e47dc7a8..68b919233fe 100644
--- a/src/mongo/db/commands/run_aggregate.cpp
+++ b/src/mongo/db/commands/run_aggregate.cpp
@@ -375,7 +375,8 @@ boost::intrusive_ptr<ExpressionContext> makeExpressionContext(
std::move(collator),
MongoProcessInterface::create(opCtx),
uassertStatusOK(resolveInvolvedNamespaces(opCtx, request)),
- uuid);
+ uuid,
+ CurOp::get(opCtx)->dbProfileLevel() > 0);
expCtx->tempDir = storageGlobalParams.dbpath + "/_tmp";
expCtx->inMultiDocumentTransaction = opCtx->inMultiDocumentTransaction();
diff --git a/src/mongo/db/curop.h b/src/mongo/db/curop.h
index 8c8c66f5514..2e11e447718 100644
--- a/src/mongo/db/curop.h
+++ b/src/mongo/db/curop.h
@@ -427,6 +427,10 @@ public:
*/
void raiseDbProfileLevel(int dbProfileLevel);
+ int dbProfileLevel() const {
+ return _dbprofile;
+ }
+
/**
* Gets the network operation type. No lock is required if called by the thread executing
* the operation, but the lock must be held if called from another thread.
diff --git a/src/mongo/db/exec/cached_plan.cpp b/src/mongo/db/exec/cached_plan.cpp
index a5571725990..4930433ce74 100644
--- a/src/mongo/db/exec/cached_plan.cpp
+++ b/src/mongo/db/exec/cached_plan.cpp
@@ -76,7 +76,7 @@ Status CachedPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) {
// Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of
// execution work that happens here, so this is needed for the time accounting to
// make sense.
- ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
+ auto optTimer = getOptTimer();
// During plan selection, the list of indices we are using to plan must remain stable, so the
// query will die during yield recovery if any index has been dropped. However, once plan
diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp
index 4fa9b8766a2..94c1eebae42 100644
--- a/src/mongo/db/exec/multi_plan.cpp
+++ b/src/mongo/db/exec/multi_plan.cpp
@@ -61,6 +61,15 @@ using std::vector;
// static
const char* MultiPlanStage::kStageType = "MULTI_PLAN";
+namespace {
+void markShouldCollectTimingInfoOnSubtree(PlanStage* root) {
+ root->markShouldCollectTimingInfo();
+ for (auto&& child : root->getChildren()) {
+ markShouldCollectTimingInfoOnSubtree(child.get());
+ }
+}
+} // namespace
+
MultiPlanStage::MultiPlanStage(ExpressionContext* expCtx,
const Collection* collection,
CanonicalQuery* cq,
@@ -79,6 +88,11 @@ void MultiPlanStage::addPlan(std::unique_ptr<QuerySolution> solution,
WorkingSet* ws) {
_children.emplace_back(std::move(root));
_candidates.push_back(CandidatePlan(std::move(solution), _children.back().get(), ws));
+
+ // Tell the new candidate plan that it must collect timing info. This timing info will
+ // later be stored in the plan cache, and may be used for explain output.
+ PlanStage* newChild = _children.back().get();
+ markShouldCollectTimingInfoOnSubtree(newChild);
}
bool MultiPlanStage::isEOF() {
@@ -201,7 +215,7 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) {
// Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of
// execution work that happens here, so this is needed for the time accounting to
// make sense.
- ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
+ auto optTimer = getOptTimer();
size_t numWorks = getTrialPeriodWorks(opCtx(), collection());
size_t numResults = getTrialPeriodNumToReturn(*_query);
diff --git a/src/mongo/db/exec/plan_stage.cpp b/src/mongo/db/exec/plan_stage.cpp
index 06ae012db86..22bdbbc41b9 100644
--- a/src/mongo/db/exec/plan_stage.cpp
+++ b/src/mongo/db/exec/plan_stage.cpp
@@ -33,32 +33,10 @@
#include "mongo/db/exec/plan_stage.h"
-#include "mongo/db/exec/scoped_timer.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context.h"
namespace mongo {
-
-PlanStage::StageState PlanStage::work(WorkingSetID* out) {
- invariant(_opCtx);
- ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
- ++_commonStats.works;
-
- StageState workResult = doWork(out);
-
- if (StageState::ADVANCED == workResult) {
- ++_commonStats.advanced;
- } else if (StageState::NEED_TIME == workResult) {
- ++_commonStats.needTime;
- } else if (StageState::NEED_YIELD == workResult) {
- ++_commonStats.needYield;
- } else if (StageState::FAILURE == workResult) {
- _commonStats.failed = true;
- }
-
- return workResult;
-}
-
void PlanStage::saveState() {
++_commonStats.yields;
for (auto&& child : _children) {
diff --git a/src/mongo/db/exec/plan_stage.h b/src/mongo/db/exec/plan_stage.h
index 3a9475a5ca4..652bc62d051 100644
--- a/src/mongo/db/exec/plan_stage.h
+++ b/src/mongo/db/exec/plan_stage.h
@@ -33,6 +33,7 @@
#include <vector>
#include "mongo/db/exec/plan_stats.h"
+#include "mongo/db/exec/scoped_timer.h"
#include "mongo/db/exec/working_set.h"
#include "mongo/db/pipeline/expression_context.h"
@@ -109,6 +110,11 @@ public:
PlanStage(const char* typeName, ExpressionContext* expCtx)
: _commonStats(typeName), _opCtx(expCtx->opCtx), _expCtx(expCtx) {
invariant(expCtx);
+ if (expCtx->explain || expCtx->mayDbProfile) {
+ // Populating the field for execution time indicates that this stage should time each
+ // call to work().
+ _commonStats.executionTimeMillis.emplace(0);
+ }
}
protected:
@@ -194,7 +200,25 @@ public:
* Stage returns StageState::ADVANCED if *out is set to the next unit of output. Otherwise,
* returns another value of StageState to indicate the stage's status.
*/
- StageState work(WorkingSetID* out);
+ StageState work(WorkingSetID* out) {
+ auto optTimer(getOptTimer());
+
+ ++_commonStats.works;
+
+ StageState workResult = doWork(out);
+
+ if (StageState::ADVANCED == workResult) {
+ ++_commonStats.advanced;
+ } else if (StageState::NEED_TIME == workResult) {
+ ++_commonStats.needTime;
+ } else if (StageState::NEED_YIELD == workResult) {
+ ++_commonStats.needYield;
+ } else if (StageState::FAILURE == workResult) {
+ _commonStats.failed = true;
+ }
+
+ return workResult;
+ }
/**
* Returns true if no more work can be done on the query / out of results.
@@ -338,6 +362,15 @@ public:
*/
virtual const SpecificStats* getSpecificStats() const = 0;
+ /**
+ * Force this stage to collect timing info during its execution. Must not be called after
+ * execution has started.
+ */
+ void markShouldCollectTimingInfo() {
+ invariant(!_commonStats.executionTimeMillis || *_commonStats.executionTimeMillis == 0);
+ _commonStats.executionTimeMillis.emplace(0);
+ }
+
protected:
/**
* Performs one unit of work. See comment at work() above.
@@ -388,6 +421,18 @@ protected:
return _expCtx;
}
+ /**
+ * Returns an optional timer which is used to collect time spent executing the current
+ * stage. May return boost::none if it is not necessary to collect timing info.
+ */
+ boost::optional<ScopedTimer> getOptTimer() {
+ if (_commonStats.executionTimeMillis) {
+ return {{getClock(), _commonStats.executionTimeMillis.get_ptr()}};
+ }
+
+ return boost::none;
+ }
+
Children _children;
CommonStats _commonStats;
diff --git a/src/mongo/db/exec/plan_stats.h b/src/mongo/db/exec/plan_stats.h
index ea75f673b81..8e3d2dfadff 100644
--- a/src/mongo/db/exec/plan_stats.h
+++ b/src/mongo/db/exec/plan_stats.h
@@ -68,7 +68,6 @@ struct CommonStats {
advanced(0),
needTime(0),
needYield(0),
- executionTimeMillis(0),
failed(false),
isEOF(false) {}
@@ -92,8 +91,13 @@ struct CommonStats {
// is no filter affixed, then 'filter' should be an empty BSONObj.
BSONObj filter;
- // Time elapsed while working inside this stage.
- long long executionTimeMillis;
+ // Time elapsed while working inside this stage. When this field is set to boost::none,
+ // timing info will not be collected during query execution.
+ //
+ // The field must be populated when running explain or when running with the profiler on. It
+ // must also be populated when multi planning, in order to gather stats stored in the plan
+ // cache.
+ boost::optional<long long> executionTimeMillis;
// TODO: have some way of tracking WSM sizes (or really any series of #s). We can measure
// the size of our inputs and the size of our outputs. We can do a lot with the WS here.
diff --git a/src/mongo/db/exec/scoped_timer.h b/src/mongo/db/exec/scoped_timer.h
index 33ddb192873..c11c424e59a 100644
--- a/src/mongo/db/exec/scoped_timer.h
+++ b/src/mongo/db/exec/scoped_timer.h
@@ -45,6 +45,7 @@ class ScopedTimer {
ScopedTimer& operator=(const ScopedTimer&) = delete;
public:
+ ScopedTimer(ScopedTimer&& other) = default;
ScopedTimer(ClockSource* cs, long long* counter);
~ScopedTimer();
diff --git a/src/mongo/db/exec/stagedebug_cmd.cpp b/src/mongo/db/exec/stagedebug_cmd.cpp
index 7baabe4a011..13489617671 100644
--- a/src/mongo/db/exec/stagedebug_cmd.cpp
+++ b/src/mongo/db/exec/stagedebug_cmd.cpp
@@ -183,7 +183,7 @@ public:
expCtx.get(), ws.get(), std::move(userRoot), nullptr, collection);
auto statusWithPlanExecutor = PlanExecutor::make(
- opCtx, std::move(ws), std::move(rootFetch), collection, PlanExecutor::YIELD_AUTO);
+ expCtx, std::move(ws), std::move(rootFetch), collection, PlanExecutor::YIELD_AUTO);
fassert(28536, statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp
index 054f48e3a2b..910a061e3d2 100644
--- a/src/mongo/db/exec/subplan.cpp
+++ b/src/mongo/db/exec/subplan.cpp
@@ -424,7 +424,7 @@ Status SubplanStage::choosePlanWholeQuery(PlanYieldPolicy* yieldPolicy) {
Status SubplanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) {
// Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of
// work that happens here, so this is needed for the time accounting to make sense.
- ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
+ auto optTimer = getOptTimer();
// During plan selection, the list of indices we are using to plan must remain stable, so the
// query will die during yield recovery if any index has been dropped. However, once plan
diff --git a/src/mongo/db/pipeline/document_source.cpp b/src/mongo/db/pipeline/document_source.cpp
index f6b5b38c486..51e8d8b85df 100644
--- a/src/mongo/db/pipeline/document_source.cpp
+++ b/src/mongo/db/pipeline/document_source.cpp
@@ -54,7 +54,11 @@ using std::vector;
DocumentSource::DocumentSource(const StringData stageName,
const intrusive_ptr<ExpressionContext>& pCtx)
- : pSource(nullptr), pExpCtx(pCtx), _commonStats(stageName.rawData()) {}
+ : pSource(nullptr), pExpCtx(pCtx), _commonStats(stageName.rawData()) {
+ if (pExpCtx->shouldCollectDocumentSourceExecStats()) {
+ _commonStats.executionTimeMillis.emplace(0);
+ }
+}
namespace {
struct ParserRegistration {
diff --git a/src/mongo/db/pipeline/document_source.h b/src/mongo/db/pipeline/document_source.h
index 3e04bb594bf..9ea177d52d5 100644
--- a/src/mongo/db/pipeline/document_source.h
+++ b/src/mongo/db/pipeline/document_source.h
@@ -255,7 +255,7 @@ public:
GetNextResult getNext() {
pExpCtx->checkForInterrupt();
- if (MONGO_likely(!pExpCtx->shouldCollectExecStats())) {
+ if (MONGO_likely(!pExpCtx->shouldCollectDocumentSourceExecStats())) {
return doGetNext();
}
@@ -264,7 +264,8 @@ public:
auto fcs = serviceCtx->getFastClockSource();
invariant(fcs);
- ScopedTimer timer(fcs, &_commonStats.executionTimeMillis);
+ invariant(_commonStats.executionTimeMillis);
+ ScopedTimer timer(fcs, _commonStats.executionTimeMillis.get_ptr());
++_commonStats.works;
GetNextResult next = doGetNext();
diff --git a/src/mongo/db/pipeline/expression_context.cpp b/src/mongo/db/pipeline/expression_context.cpp
index 0c6f80e8b82..fb790531f29 100644
--- a/src/mongo/db/pipeline/expression_context.cpp
+++ b/src/mongo/db/pipeline/expression_context.cpp
@@ -50,7 +50,8 @@ ExpressionContext::ExpressionContext(OperationContext* opCtx,
std::unique_ptr<CollatorInterface> collator,
std::shared_ptr<MongoProcessInterface> processInterface,
StringMap<ResolvedNamespace> resolvedNamespaces,
- boost::optional<UUID> collUUID)
+ boost::optional<UUID> collUUID,
+ bool mayDbProfile)
: ExpressionContext(opCtx,
request.getExplain(),
request.isFromMongos(),
@@ -63,7 +64,8 @@ ExpressionContext::ExpressionContext(OperationContext* opCtx,
std::move(collator),
std::move(processInterface),
std::move(resolvedNamespaces),
- std::move(collUUID)) {
+ std::move(collUUID),
+ mayDbProfile) {
if (request.getIsMapReduceCommand()) {
// mapReduce command JavaScript invocation is only subject to the server global
// 'jsHeapLimitMB' limit.
@@ -84,7 +86,8 @@ ExpressionContext::ExpressionContext(
std::unique_ptr<CollatorInterface> collator,
const std::shared_ptr<MongoProcessInterface>& mongoProcessInterface,
StringMap<ExpressionContext::ResolvedNamespace> resolvedNamespaces,
- boost::optional<UUID> collUUID)
+ boost::optional<UUID> collUUID,
+ bool mayDbProfile)
: explain(explain),
fromMongos(fromMongos),
needsMerge(needsMerge),
@@ -98,6 +101,7 @@ ExpressionContext::ExpressionContext(
? TimeZoneDatabase::get(opCtx->getServiceContext())
: nullptr),
variablesParseState(variables.useIdGenerator()),
+ mayDbProfile(mayDbProfile),
_collator(std::move(collator)),
_documentComparator(_collator.get()),
_valueComparator(_collator.get()),
@@ -117,7 +121,8 @@ ExpressionContext::ExpressionContext(
ExpressionContext::ExpressionContext(OperationContext* opCtx,
std::unique_ptr<CollatorInterface> collator,
const NamespaceString& nss,
- const boost::optional<RuntimeConstants>& runtimeConstants)
+ const boost::optional<RuntimeConstants>& runtimeConstants,
+ bool mayDbProfile)
: ns(nss),
opCtx(opCtx),
mongoProcessInterface(std::make_shared<StubMongoProcessInterface>()),
@@ -125,6 +130,7 @@ ExpressionContext::ExpressionContext(OperationContext* opCtx,
? TimeZoneDatabase::get(opCtx->getServiceContext())
: nullptr),
variablesParseState(variables.useIdGenerator()),
+ mayDbProfile(mayDbProfile),
_collator(std::move(collator)),
_documentComparator(_collator.get()),
_valueComparator(_collator.get()) {
@@ -182,7 +188,8 @@ intrusive_ptr<ExpressionContext> ExpressionContext::copyWith(
std::move(collator),
mongoProcessInterface,
_resolvedNamespaces,
- uuid);
+ uuid,
+ mayDbProfile);
expCtx->inMongos = inMongos;
expCtx->maxFeatureCompatibilityVersion = maxFeatureCompatibilityVersion;
diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h
index cbb0aab0c4b..80104b06a37 100644
--- a/src/mongo/db/pipeline/expression_context.h
+++ b/src/mongo/db/pipeline/expression_context.h
@@ -107,7 +107,8 @@ public:
std::unique_ptr<CollatorInterface> collator,
std::shared_ptr<MongoProcessInterface> mongoProcessInterface,
StringMap<ExpressionContext::ResolvedNamespace> resolvedNamespaces,
- boost::optional<UUID> collUUID);
+ boost::optional<UUID> collUUID,
+ bool mayDbProfile = true);
/**
* Constructs an ExpressionContext to be used for Pipeline parsing and evaluation. This version
@@ -126,7 +127,8 @@ public:
std::unique_ptr<CollatorInterface> collator,
const std::shared_ptr<MongoProcessInterface>& mongoProcessInterface,
StringMap<ExpressionContext::ResolvedNamespace> resolvedNamespaces,
- boost::optional<UUID> collUUID);
+ boost::optional<UUID> collUUID,
+ bool mayDbProfile);
/**
* Constructs an ExpressionContext suitable for use outside of the aggregation system, including
@@ -137,7 +139,8 @@ public:
ExpressionContext(OperationContext* opCtx,
std::unique_ptr<CollatorInterface> collator,
const NamespaceString& ns,
- const boost::optional<RuntimeConstants>& runtimeConstants = boost::none);
+ const boost::optional<RuntimeConstants>& runtimeConstants = boost::none,
+ bool mayDbProfile = true);
/**
* Used by a pipeline to check for interrupts so that killOp() works. Throws a UserAssertion if
@@ -170,7 +173,10 @@ public:
return _collator.get();
}
- bool shouldCollectExecStats() const {
+ /**
+ * Whether to track timing information and "work" counts in the agg layer.
+ */
+ bool shouldCollectDocumentSourceExecStats() const {
return static_cast<bool>(explain);
}
@@ -352,6 +358,10 @@ public:
// True if this ExpressionContext is used to parse a collection validator expression.
bool isParsingCollectionValidator = false;
+ // Indicates where there is any chance this operation will be profiled. Must be set at
+ // construction.
+ const bool mayDbProfile = true;
+
protected:
static const int kInterruptCheckPeriod = 128;
diff --git a/src/mongo/db/pipeline/expression_context_for_test.h b/src/mongo/db/pipeline/expression_context_for_test.h
index 23bd4cce4ce..cb1d0deab58 100644
--- a/src/mongo/db/pipeline/expression_context_for_test.h
+++ b/src/mongo/db/pipeline/expression_context_for_test.h
@@ -75,8 +75,9 @@ public:
RuntimeConstants(Date_t::now(), Timestamp(1, 0)),
{}, // collator
std::make_shared<StubMongoProcessInterface>(),
- {}, // resolvedNamespaces
- {} // collUUID
+ {}, // resolvedNamespaces
+ {}, // collUUID
+ false // mayDbProfile
) {
// If there is an existing global ServiceContext, adopt it. Otherwise, create a new context.
// Similarly, we create a new OperationContext or adopt an existing context as appropriate.
@@ -93,7 +94,6 @@ public:
// Resolve the active OperationContext and set it on the ExpressionContextForTest.
opCtx = _testOpCtx ? _testOpCtx.get() : Client::getCurrent()->getOperationContext();
-
// As we don't have an OperationContext or TimeZoneDatabase prior to base class
// ExpressionContext construction, we must resolve one. If there exists a TimeZoneDatabase
// associated with the current ServiceContext, adopt it. Otherwise, create a
@@ -125,8 +125,9 @@ public:
RuntimeConstants(Date_t::now(), Timestamp(1, 0)),
{}, // collator
std::make_shared<StubMongoProcessInterface>(),
- {}, // resolvedNamespaces
- {} // collUUID
+ {}, // resolvedNamespaces
+ {}, // collUUID
+ false // mayDbProfile
),
_serviceContext(opCtx->getServiceContext()) {
// Resolve the TimeZoneDatabase to be used by this ExpressionContextForTest.
diff --git a/src/mongo/db/pipeline/pipeline.cpp b/src/mongo/db/pipeline/pipeline.cpp
index 2cfa0754d57..156450b961f 100644
--- a/src/mongo/db/pipeline/pipeline.cpp
+++ b/src/mongo/db/pipeline/pipeline.cpp
@@ -64,7 +64,8 @@ Value appendExecStats(Value docSource, const CommonStats& stats) {
invariant(docSource.getType() == BSONType::Object);
MutableDocument doc(docSource.getDocument());
auto nReturned = static_cast<long long>(stats.advanced);
- auto executionTimeMillisEstimate = static_cast<long long>(stats.executionTimeMillis);
+ invariant(stats.executionTimeMillis);
+ auto executionTimeMillisEstimate = static_cast<long long>(*stats.executionTimeMillis);
doc.addField("nReturned", Value(nReturned));
doc.addField("executionTimeMillisEstimate", Value(executionTimeMillisEstimate));
return Value(doc.freeze());
diff --git a/src/mongo/db/pipeline/pipeline_d.cpp b/src/mongo/db/pipeline/pipeline_d.cpp
index b35e720fcf6..926a9e2f7ac 100644
--- a/src/mongo/db/pipeline/pipeline_d.cpp
+++ b/src/mongo/db/pipeline/pipeline_d.cpp
@@ -170,7 +170,7 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> createRandomCursorEx
}
return PlanExecutor::make(
- opCtx, std::move(ws), std::move(root), coll, PlanExecutor::YIELD_AUTO);
+ expCtx, std::move(ws), std::move(root), coll, PlanExecutor::YIELD_AUTO);
}
StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> attemptToGetExecutor(
diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp
index 8e86973cde4..1287315005d 100644
--- a/src/mongo/db/query/explain.cpp
+++ b/src/mongo/db/query/explain.cpp
@@ -327,7 +327,11 @@ void Explain::statsToBSON(const PlanStageStats& stats,
// Some top-level exec stats get pulled out of the root stage.
if (verbosity >= ExplainOptions::Verbosity::kExecStats) {
bob->appendNumber("nReturned", stats.common.advanced);
- bob->appendNumber("executionTimeMillisEstimate", stats.common.executionTimeMillis);
+ // Include executionTimeMillis if it was recorded.
+ if (stats.common.executionTimeMillis) {
+ bob->appendNumber("executionTimeMillisEstimate", *stats.common.executionTimeMillis);
+ }
+
bob->appendNumber("works", stats.common.works);
bob->appendNumber("advanced", stats.common.advanced);
bob->appendNumber("needTime", stats.common.needTime);
@@ -729,7 +733,8 @@ void Explain::generateSinglePlanExecutionInfo(const PlanStageStats* stats,
if (totalTimeMillis) {
out->appendNumber("executionTimeMillis", *totalTimeMillis);
} else {
- out->appendNumber("executionTimeMillisEstimate", stats->common.executionTimeMillis);
+ invariant(stats->common.executionTimeMillis);
+ out->appendNumber("executionTimeMillisEstimate", *stats->common.executionTimeMillis);
}
// Flatten the stats tree into a list.
@@ -957,7 +962,6 @@ void Explain::getSummaryStats(const PlanExecutor& exec, PlanSummaryStats* statsO
// root stage of the plan tree.
const CommonStats* common = root->getCommonStats();
statsOut->nReturned = common->advanced;
- statsOut->executionTimeMillis = common->executionTimeMillis;
// The other fields are aggregations over the stages in the plan tree. We flatten
// the tree into a list and then compute these aggregations.
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 6285c023a37..db1ead9711d 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -780,7 +780,7 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDelete(
"nss_ns"_attr = nss.ns(),
"request_getQuery"_attr = redact(request->getQuery()));
return PlanExecutor::make(
- opCtx, std::move(ws), std::make_unique<EOFStage>(expCtx.get()), nullptr, policy, nss);
+ expCtx, std::move(ws), std::make_unique<EOFStage>(expCtx.get()), nullptr, policy, nss);
}
if (!parsedDelete->hasParsedQuery()) {
@@ -822,7 +822,7 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDelete(
collection,
idHackStage.release());
return PlanExecutor::make(
- opCtx, std::move(ws), std::move(root), collection, policy);
+ expCtx, std::move(ws), std::move(root), collection, policy);
}
}
@@ -946,7 +946,7 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorUpdate(
"nss_ns"_attr = nss.ns(),
"request_getQuery"_attr = redact(request->getQuery()));
return PlanExecutor::make(
- opCtx, std::move(ws), std::make_unique<EOFStage>(expCtx.get()), nullptr, policy, nss);
+ expCtx, std::move(ws), std::make_unique<EOFStage>(expCtx.get()), nullptr, policy, nss);
}
// Pass index information to the update driver, so that it can determine for us whether the
@@ -1228,7 +1228,8 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCount(
// this case we put a CountStage on top of an EOFStage.
unique_ptr<PlanStage> root = std::make_unique<CountStage>(
expCtx.get(), collection, limit, skip, ws.get(), new EOFStage(expCtx.get()));
- return PlanExecutor::make(opCtx, std::move(ws), std::move(root), nullptr, yieldPolicy, nss);
+ return PlanExecutor::make(
+ expCtx, std::move(ws), std::move(root), nullptr, yieldPolicy, nss);
}
// If the query is empty, then we can determine the count by just asking the collection
@@ -1243,7 +1244,8 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCount(
if (useRecordStoreCount) {
unique_ptr<PlanStage> root =
std::make_unique<RecordStoreFastCountStage>(expCtx.get(), collection, skip, limit);
- return PlanExecutor::make(opCtx, std::move(ws), std::move(root), nullptr, yieldPolicy, nss);
+ return PlanExecutor::make(
+ expCtx, std::move(ws), std::move(root), nullptr, yieldPolicy, nss);
}
size_t plannerOptions = QueryPlannerParams::IS_COUNT;
diff --git a/src/mongo/db/query/internal_plans.cpp b/src/mongo/db/query/internal_plans.cpp
index 238f6636e0f..ed03783f598 100644
--- a/src/mongo/db/query/internal_plans.cpp
+++ b/src/mongo/db/query/internal_plans.cpp
@@ -62,7 +62,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> InternalPlanner::collection
auto eof = std::make_unique<EOFStage>(expCtx.get());
// Takes ownership of 'ws' and 'eof'.
auto statusWithPlanExecutor = PlanExecutor::make(
- opCtx, std::move(ws), std::move(eof), nullptr, yieldPolicy, NamespaceString(ns));
+ expCtx, std::move(ws), std::move(eof), nullptr, yieldPolicy, NamespaceString(ns));
invariant(statusWithPlanExecutor.isOK());
return std::move(statusWithPlanExecutor.getValue());
}
@@ -73,7 +73,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> InternalPlanner::collection
// Takes ownership of 'ws' and 'cs'.
auto statusWithPlanExecutor =
- PlanExecutor::make(opCtx, std::move(ws), std::move(cs), collection, yieldPolicy);
+ PlanExecutor::make(expCtx, std::move(ws), std::move(cs), collection, yieldPolicy);
invariant(statusWithPlanExecutor.isOK());
return std::move(statusWithPlanExecutor.getValue());
}
@@ -96,7 +96,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> InternalPlanner::deleteWith
expCtx.get(), std::move(params), ws.get(), collection, root.release());
auto executor =
- PlanExecutor::make(opCtx, std::move(ws), std::move(root), collection, yieldPolicy);
+ PlanExecutor::make(expCtx, std::move(ws), std::move(root), collection, yieldPolicy);
invariant(executor.getStatus());
return std::move(executor.getValue());
}
@@ -128,7 +128,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> InternalPlanner::indexScan(
options);
auto executor =
- PlanExecutor::make(opCtx, std::move(ws), std::move(root), collection, yieldPolicy);
+ PlanExecutor::make(expCtx, std::move(ws), std::move(root), collection, yieldPolicy);
invariant(executor.getStatus());
return std::move(executor.getValue());
}
@@ -163,7 +163,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> InternalPlanner::deleteWith
expCtx.get(), std::move(params), ws.get(), collection, root.release());
auto executor =
- PlanExecutor::make(opCtx, std::move(ws), std::move(root), collection, yieldPolicy);
+ PlanExecutor::make(expCtx, std::move(ws), std::move(root), collection, yieldPolicy);
invariant(executor.getStatus());
return std::move(executor.getValue());
}
@@ -190,7 +190,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> InternalPlanner::updateWith
expCtx.get(), params, ws.get(), collection, idHackStage.release()));
auto executor =
- PlanExecutor::make(opCtx, std::move(ws), std::move(root), collection, yieldPolicy);
+ PlanExecutor::make(expCtx, std::move(ws), std::move(root), collection, yieldPolicy);
invariant(executor.getStatus());
return std::move(executor.getValue());
}
diff --git a/src/mongo/db/query/plan_executor.h b/src/mongo/db/query/plan_executor.h
index ffb54ee7c90..bef0a4d4d27 100644
--- a/src/mongo/db/query/plan_executor.h
+++ b/src/mongo/db/query/plan_executor.h
@@ -287,19 +287,6 @@ public:
std::unique_ptr<QuerySolution> qs = nullptr);
/**
- * This overload is provided for executors that do not have a CanonicalQuery or an
- * ExpressionContext, such as an aggregation command with a $listCollections stage.
- */
- static StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> make(
- OperationContext* opCtx,
- std::unique_ptr<WorkingSet> ws,
- std::unique_ptr<PlanStage> rt,
- const Collection* collection,
- YieldPolicy yieldPolicy,
- NamespaceString nss = NamespaceString(),
- std::unique_ptr<QuerySolution> qs = nullptr);
-
- /**
* A PlanExecutor must be disposed before destruction. In most cases, this will happen
* automatically through a PlanExecutor::Deleter or a ClientCursor.
*/
diff --git a/src/mongo/db/query/plan_executor_impl.cpp b/src/mongo/db/query/plan_executor_impl.cpp
index 8da7932a3d5..ed0744fcdd2 100644
--- a/src/mongo/db/query/plan_executor_impl.cpp
+++ b/src/mongo/db/query/plan_executor_impl.cpp
@@ -165,25 +165,6 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PlanExecutor::make(
yieldPolicy);
}
-StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PlanExecutor::make(
- OperationContext* opCtx,
- std::unique_ptr<WorkingSet> ws,
- std::unique_ptr<PlanStage> rt,
- const Collection* collection,
- YieldPolicy yieldPolicy,
- NamespaceString nss,
- std::unique_ptr<QuerySolution> qs) {
- return PlanExecutorImpl::make(opCtx,
- std::move(ws),
- std::move(rt),
- std::move(qs),
- nullptr,
- nullptr,
- collection,
- nss,
- yieldPolicy);
-}
-
StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> PlanExecutorImpl::make(
OperationContext* opCtx,
unique_ptr<WorkingSet> ws,
diff --git a/src/mongo/db/query/plan_summary_stats.h b/src/mongo/db/query/plan_summary_stats.h
index a5ff98266d2..4660c097795 100644
--- a/src/mongo/db/query/plan_summary_stats.h
+++ b/src/mongo/db/query/plan_summary_stats.h
@@ -47,9 +47,6 @@ struct PlanSummaryStats {
// The total number of documents examined by the plan.
size_t totalDocsExamined = 0U;
- // The number of milliseconds spent inside the root stage's work() method.
- long long executionTimeMillis = 0;
-
// The number of collection scans that occur during execution. Note that more than one
// collection scan may happen during execution (e.g. for $lookup execution).
long long collectionScans = 0;
diff --git a/src/mongo/dbtests/cursor_manager_test.cpp b/src/mongo/dbtests/cursor_manager_test.cpp
index 99e8b00495c..9f3a1ad96de 100644
--- a/src/mongo/dbtests/cursor_manager_test.cpp
+++ b/src/mongo/dbtests/cursor_manager_test.cpp
@@ -75,7 +75,7 @@ public:
auto workingSet = std::make_unique<WorkingSet>();
auto queuedDataStage = std::make_unique<QueuedDataStage>(expCtx.get(), workingSet.get());
- return unittest::assertGet(PlanExecutor::make(opCtx,
+ return unittest::assertGet(PlanExecutor::make(expCtx,
std::move(workingSet),
std::move(queuedDataStage),
nullptr,
diff --git a/src/mongo/dbtests/documentsourcetests.cpp b/src/mongo/dbtests/documentsourcetests.cpp
index 84738eb6e17..2f6e421e159 100644
--- a/src/mongo/dbtests/documentsourcetests.cpp
+++ b/src/mongo/dbtests/documentsourcetests.cpp
@@ -228,8 +228,8 @@ TEST_F(DocumentSourceCursorTest, SerializationNoExplainLevel) {
TEST_F(DocumentSourceCursorTest, SerializationQueryPlannerExplainLevel) {
auto verb = ExplainOptions::Verbosity::kQueryPlanner;
- createSource();
ctx()->explain = verb;
+ createSource();
auto explainResult = source()->serialize(verb);
ASSERT_FALSE(explainResult["$cursor"]["queryPlanner"].missing());
@@ -240,8 +240,8 @@ TEST_F(DocumentSourceCursorTest, SerializationQueryPlannerExplainLevel) {
TEST_F(DocumentSourceCursorTest, SerializationExecStatsExplainLevel) {
auto verb = ExplainOptions::Verbosity::kExecStats;
- createSource();
ctx()->explain = verb;
+ createSource();
// Execute the plan so that the source populates its internal execution stats.
exhaustCursor();
@@ -256,8 +256,8 @@ TEST_F(DocumentSourceCursorTest, SerializationExecStatsExplainLevel) {
TEST_F(DocumentSourceCursorTest, SerializationExecAllPlansExplainLevel) {
auto verb = ExplainOptions::Verbosity::kExecAllPlans;
- createSource();
ctx()->explain = verb;
+ createSource();
// Execute the plan so that the source populates its internal executionStats.
exhaustCursor();
@@ -273,8 +273,8 @@ TEST_F(DocumentSourceCursorTest, SerializationExecAllPlansExplainLevel) {
TEST_F(DocumentSourceCursorTest, ExpressionContextAndSerializeVerbosityMismatch) {
const auto verb1 = ExplainOptions::Verbosity::kExecAllPlans;
const auto verb2 = ExplainOptions::Verbosity::kQueryPlanner;
- createSource();
ctx()->explain = verb1;
+ createSource();
// Execute the plan so that the source populates its internal executionStats.
exhaustCursor();
diff --git a/src/mongo/dbtests/query_plan_executor.cpp b/src/mongo/dbtests/query_plan_executor.cpp
index 25182aa327b..fd7b3f6a111 100644
--- a/src/mongo/dbtests/query_plan_executor.cpp
+++ b/src/mongo/dbtests/query_plan_executor.cpp
@@ -224,7 +224,7 @@ TEST_F(PlanExecutorTest, DropIndexScanAgg) {
auto proxy = std::make_unique<PipelineProxyStage>(_expCtx.get(), std::move(pipeline), ws.get());
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(proxy), collection, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(proxy), collection, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto outerExec = std::move(statusWithPlanExecutor.getValue());
diff --git a/src/mongo/dbtests/query_stage_collscan.cpp b/src/mongo/dbtests/query_stage_collscan.cpp
index 9040569a58c..f17052e3e03 100644
--- a/src/mongo/dbtests/query_stage_collscan.cpp
+++ b/src/mongo/dbtests/query_stage_collscan.cpp
@@ -105,7 +105,7 @@ public:
_expCtx.get(), collection, params, ws.get(), filterExpr.get());
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -195,7 +195,7 @@ TEST_F(QueryStageCollectionScanTest, QueryStageCollscanObjectsInOrderForward) {
std::make_unique<CollectionScan>(_expCtx.get(), collection, params, ws.get(), nullptr);
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -224,7 +224,7 @@ TEST_F(QueryStageCollectionScanTest, QueryStageCollscanObjectsInOrderBackward) {
std::make_unique<CollectionScan>(_expCtx.get(), collection, params, ws.get(), nullptr);
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -377,7 +377,7 @@ TEST_F(QueryStageCollectionScanTest, QueryTestCollscanResumeAfterRecordIdSeekSuc
// Run the rest of the scan and verify the results.
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(ps), collection, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
diff --git a/src/mongo/dbtests/query_stage_merge_sort.cpp b/src/mongo/dbtests/query_stage_merge_sort.cpp
index b6b1fa9e87e..74b6d6d1843 100644
--- a/src/mongo/dbtests/query_stage_merge_sort.cpp
+++ b/src/mongo/dbtests/query_stage_merge_sort.cpp
@@ -187,7 +187,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
// Must fetch if we want to easily pull out an obj.
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -252,7 +252,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -317,7 +317,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -388,7 +388,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -455,7 +455,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -508,7 +508,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -797,7 +797,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
// Must fetch if we want to easily pull out an obj.
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -866,7 +866,7 @@ public:
make_unique<FetchStage>(_expCtx.get(), ws.get(), std::move(ms), nullptr, coll);
// Must fetch if we want to easily pull out an obj.
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index 38d44b1d8f2..59520a3b3aa 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -492,7 +492,7 @@ TEST_F(QueryStageMultiPlanTest, MPSExplainAllPlans) {
// Making a PlanExecutor chooses the best plan.
auto exec = uassertStatusOK(PlanExecutor::make(
- _opCtx.get(), std::move(ws), std::move(mps), ctx.getCollection(), PlanExecutor::NO_YIELD));
+ _expCtx, std::move(ws), std::move(mps), ctx.getCollection(), PlanExecutor::NO_YIELD));
auto root = static_cast<MultiPlanStage*>(exec->getRootStage());
ASSERT_TRUE(root->bestPlanChosen());
diff --git a/src/mongo/dbtests/query_stage_sort.cpp b/src/mongo/dbtests/query_stage_sort.cpp
index 1d6833337bc..a81702662d8 100644
--- a/src/mongo/dbtests/query_stage_sort.cpp
+++ b/src/mongo/dbtests/query_stage_sort.cpp
@@ -131,7 +131,7 @@ public:
// The PlanExecutor will be automatically registered on construction due to the auto
// yield policy, so it can receive invalidations when we remove documents later.
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(ss), coll, PlanExecutor::YIELD_AUTO);
+ _expCtx, std::move(ws), std::move(ss), coll, PlanExecutor::YIELD_AUTO);
invariant(statusWithPlanExecutor.isOK());
return std::move(statusWithPlanExecutor.getValue());
}
@@ -174,7 +174,7 @@ public:
// Must fetch so we can look at the doc as a BSONObj.
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
@@ -590,7 +590,7 @@ public:
// We don't get results back since we're sorting some parallel arrays.
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(fetchStage), coll, PlanExecutor::NO_YIELD);
auto exec = std::move(statusWithPlanExecutor.getValue());
PlanExecutor::ExecState runnerState =
diff --git a/src/mongo/dbtests/query_stage_tests.cpp b/src/mongo/dbtests/query_stage_tests.cpp
index e86d851c7a4..b3003d56213 100644
--- a/src/mongo/dbtests/query_stage_tests.cpp
+++ b/src/mongo/dbtests/query_stage_tests.cpp
@@ -93,7 +93,7 @@ public:
std::make_unique<IndexScan>(_expCtx.get(), params, ws.get(), filterExpr.get());
auto statusWithPlanExecutor = PlanExecutor::make(
- &_opCtx, std::move(ws), std::move(ix), ctx.getCollection(), PlanExecutor::NO_YIELD);
+ _expCtx, std::move(ws), std::move(ix), ctx.getCollection(), PlanExecutor::NO_YIELD);
ASSERT_OK(statusWithPlanExecutor.getStatus());
auto exec = std::move(statusWithPlanExecutor.getValue());
diff --git a/src/mongo/s/commands/cluster_map_reduce_agg.cpp b/src/mongo/s/commands/cluster_map_reduce_agg.cpp
index 6c6365500f4..0223ac3e07c 100644
--- a/src/mongo/s/commands/cluster_map_reduce_agg.cpp
+++ b/src/mongo/s/commands/cluster_map_reduce_agg.cpp
@@ -101,7 +101,9 @@ auto makeExpressionContext(OperationContext* opCtx,
std::make_shared<MongosProcessInterface>(
Grid::get(opCtx)->getExecutorPool()->getArbitraryExecutor()),
std::move(resolvedNamespaces),
- boost::none); // uuid
+ boost::none, // uuid
+ false // mayDbProfile: false because mongos has no profile collection.
+ );
expCtx->inMongos = true;
return expCtx;
}