summaryrefslogtreecommitdiff
path: root/src/mongo/db/query/get_executor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/query/get_executor.cpp')
-rw-r--r--src/mongo/db/query/get_executor.cpp97
1 files changed, 37 insertions, 60 deletions
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index 602be15dbc2..db04d6a276a 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -29,13 +29,10 @@
#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
-#include "mongo/db/curop.h"
#include "mongo/platform/basic.h"
#include "mongo/db/query/get_executor.h"
-#include "mongo/util/duration.h"
-#include "mongo/util/tick_source.h"
#include <boost/optional.hpp>
#include <limits>
#include <memory>
@@ -110,7 +107,6 @@
#include "mongo/logv2/log.h"
#include "mongo/scripting/engine.h"
#include "mongo/util/str.h"
-#include "mongo/util/timer.h"
namespace mongo {
MONGO_FAIL_POINT_DEFINE(includeFakeColumnarIndex);
@@ -220,15 +216,10 @@ IndexEntry indexEntryFromIndexCatalogEntry(OperationContext* opCtx,
MultikeyMetadataAccessStats mkAccessStats;
if (canonicalQuery) {
- RelevantFieldIndexMap fieldIndexProps;
- QueryPlannerIXSelect::getFields(canonicalQuery->root(), &fieldIndexProps);
- stdx::unordered_set<std::string> projectedFields;
- for (auto&& [fieldName, _] : fieldIndexProps) {
- if (projection_executor_utils::applyProjectionToOneField(
- wildcardProjection->exec(), fieldName)) {
- projectedFields.insert(fieldName);
- }
- }
+ stdx::unordered_set<std::string> fields;
+ QueryPlannerIXSelect::getFields(canonicalQuery->root(), &fields);
+ const auto projectedFields = projection_executor_utils::applyProjectionToFields(
+ wildcardProjection->exec(), fields);
multikeyPathSet =
getWildcardMultikeyPathSet(wam, opCtx, projectedFields, &mkAccessStats);
@@ -293,8 +284,7 @@ void fillOutIndexEntries(OperationContext* opCtx,
const CanonicalQuery* canonicalQuery,
const CollectionPtr& collection,
std::vector<IndexEntry>& entries) {
- auto ii = collection->getIndexCatalog()->getIndexIterator(
- opCtx, IndexCatalog::InclusionPolicy::kReady);
+ auto ii = collection->getIndexCatalog()->getIndexIterator(opCtx, false);
while (ii->more()) {
const IndexCatalogEntry* ice = ii->next();
@@ -607,8 +597,6 @@ public:
StatusWith<std::unique_ptr<ResultType>> prepare() {
const auto& mainColl = getMainCollection();
-
- ON_BLOCK_EXIT([&] { CurOp::get(_opCtx)->stopQueryPlanningTimer(); });
if (!mainColl) {
LOGV2_DEBUG(20921,
2,
@@ -708,8 +696,10 @@ public:
"Only one plan is available",
"query"_attr = redact(_cq->toStringShort()),
"planSummary"_attr = result->getPlanSummary());
+
return std::move(result);
}
+
return buildMultiPlan(std::move(solutions));
}
@@ -1278,12 +1268,12 @@ std::unique_ptr<sbe::RuntimePlanner> makeRuntimePlannerIfNeeded(
return nullptr;
}
-std::unique_ptr<PlanYieldPolicySBE> makeSbeYieldPolicy(OperationContext* opCtx,
- PlanYieldPolicy::YieldPolicy policy,
- const Yieldable* yieldable,
- NamespaceString nss) {
- return std::make_unique<PlanYieldPolicySBE>(opCtx,
- policy,
+std::unique_ptr<PlanYieldPolicySBE> makeSbeYieldPolicy(
+ OperationContext* opCtx,
+ PlanYieldPolicy::YieldPolicy requestedYieldPolicy,
+ const Yieldable* yieldable,
+ NamespaceString nss) {
+ return std::make_unique<PlanYieldPolicySBE>(requestedYieldPolicy,
opCtx->getServiceContext()->getFastClockSource(),
internalQueryExecYieldIterations.load(),
Milliseconds{internalQueryExecYieldPeriodMS.load()},
@@ -1321,16 +1311,16 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getSlotBasedExe
auto&& [roots, solutions] = planningResult->extractResultData();
// In some circumstances (e.g. when have multiple candidate plans or using a cached one), we
// might need to execute the plan(s) to pick the best one or to confirm the choice.
- if (auto runTimePlanner = makeRuntimePlannerIfNeeded(opCtx,
- collections,
- cq.get(),
- solutions.size(),
- planningResult->decisionWorks(),
- planningResult->needsSubplanning(),
- yieldPolicy.get(),
- plannerParams.options)) {
+ if (auto planner = makeRuntimePlannerIfNeeded(opCtx,
+ collections,
+ cq.get(),
+ solutions.size(),
+ planningResult->decisionWorks(),
+ planningResult->needsSubplanning(),
+ yieldPolicy.get(),
+ plannerParams.options)) {
// Do the runtime planning and pick the best candidate plan.
- auto candidates = runTimePlanner->plan(std::move(solutions), std::move(roots));
+ auto candidates = planner->plan(std::move(solutions), std::move(roots));
return plan_executor_factory::make(opCtx,
std::move(cq),
@@ -1401,11 +1391,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor(
}
}
- // There's a special case of the projection optimization being skipped when a query has any
- // user-defined "let" variable and the query may be run with SBE. Here we make sure the
- // projection is optimized for the classic engine.
- canonicalQuery->optimizeProjection();
-
return getClassicExecutor(
opCtx, mainColl, std::move(canonicalQuery), yieldPolicy, plannerParams);
}
@@ -1418,7 +1403,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor(
PlanYieldPolicy::YieldPolicy yieldPolicy,
size_t plannerOptions) {
MultipleCollectionAccessor multi{collection};
-
return getExecutor(opCtx,
multi,
std::move(canonicalQuery),
@@ -1438,8 +1422,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorFind
std::function<void(CanonicalQuery*)> extractAndAttachPipelineStages,
bool permitYield,
QueryPlannerParams plannerParams) {
- auto yieldPolicy = permitYield ? PlanYieldPolicy::YieldPolicy::YIELD_AUTO
- : PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY;
+ auto yieldPolicy = (permitYield && !opCtx->inMultiDocumentTransaction())
+ ? PlanYieldPolicy::YieldPolicy::YIELD_AUTO
+ : PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY;
if (OperationShardingState::isComingFromRouter(opCtx)) {
plannerParams.options |= QueryPlannerParams::INCLUDE_SHARD_FILTER;
@@ -1460,7 +1445,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorFind
std::function<void(CanonicalQuery*)> extractAndAttachPipelineStages,
bool permitYield,
size_t plannerOptions) {
-
MultipleCollectionAccessor multi{*coll};
return getExecutorFind(opCtx,
multi,
@@ -1542,13 +1526,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele
expCtx->setIsCappedDelete();
}
- // If the parsed delete does not have a user-specified collation, set it from the collection
- // default.
- if (collection && parsedDelete->getRequest()->getCollation().isEmpty() &&
- collection->getDefaultCollator()) {
- parsedDelete->setCollator(collection->getDefaultCollator()->clone());
- }
-
if (collection && collection->isCapped() && opCtx->inMultiDocumentTransaction()) {
// This check is duplicated from CollectionImpl::deleteDocument() for two reasons:
// - Performing a remove on an empty capped collection would not call
@@ -1676,7 +1653,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele
ClassicPrepareExecutionHelper helper{
opCtx, collection, ws.get(), cq.get(), nullptr, defaultPlannerOptions};
auto executionResult = helper.prepare();
-
if (!executionResult.isOK()) {
return executionResult.getStatus();
}
@@ -1686,9 +1662,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDele
deleteStageParams->canonicalQuery = cq.get();
const bool batchDelete =
- (deleteStageParams->isMulti && !opCtx->inMultiDocumentTransaction() &&
- !deleteStageParams->fromMigrate && !deleteStageParams->returnDeleted &&
- deleteStageParams->sort.isEmpty() && !deleteStageParams->numStatsForDoc) &&
+ (deleteStageParams->isMulti && !deleteStageParams->fromMigrate &&
+ !deleteStageParams->returnDeleted && deleteStageParams->sort.isEmpty() &&
+ !deleteStageParams->numStatsForDoc) &&
((gInternalBatchUserMultiDeletesForTest.load() &&
nss.ns() == "__internalBatchedDeletesTesting.Collection0") ||
(batchDeletesByDefault.shouldFail()));
@@ -1864,7 +1840,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorUpda
ClassicPrepareExecutionHelper helper{
opCtx, collection, ws.get(), cq.get(), nullptr, defaultPlannerOptions};
auto executionResult = helper.prepare();
-
if (!executionResult.isOK()) {
return executionResult.getStatus();
}
@@ -2138,8 +2113,8 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun
OperationContext* opCtx = expCtx->opCtx;
std::unique_ptr<WorkingSet> ws = std::make_unique<WorkingSet>();
- auto findCommand = std::make_unique<FindCommandRequest>(nss);
+ auto findCommand = std::make_unique<FindCommandRequest>(nss);
findCommand->setFilter(request.getQuery());
auto collation = request.getCollation().value_or(BSONObj());
findCommand->setCollation(collation);
@@ -2160,7 +2135,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun
}
std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());
- const auto yieldPolicy = PlanYieldPolicy::YieldPolicy::YIELD_AUTO;
+ const auto yieldPolicy = opCtx->inMultiDocumentTransaction()
+ ? PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY
+ : PlanYieldPolicy::YieldPolicy::YIELD_AUTO;
const auto skip = request.getSkip().value_or(0);
const auto limit = request.getLimit().value_or(0);
@@ -2213,7 +2190,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun
if (!executionResult.isOK()) {
return executionResult.getStatus();
}
-
auto [root, querySolution] = executionResult.getValue()->extractResultData();
invariant(root);
@@ -2222,7 +2198,6 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun
expCtx.get(), collection, limit, skip, ws.get(), root.release());
// We must have a tree of stages in order to have a valid plan executor, but the query
// solution may be NULL. Takes ownership of all args other than 'collection' and 'opCtx'
-
return plan_executor_factory::make(std::move(cq),
std::move(ws),
std::move(root),
@@ -2418,8 +2393,8 @@ QueryPlannerParams fillOutPlannerParamsForDistinct(OperationContext* opCtx,
// If the caller did not request a "strict" distinct scan then we may choose a plan which
// unwinds arrays and treats each element in an array as its own key.
const bool mayUnwindArrays = !(plannerOptions & QueryPlannerParams::STRICT_DISTINCT_ONLY);
- auto ii = collection->getIndexCatalog()->getIndexIterator(
- opCtx, IndexCatalog::InclusionPolicy::kReady);
+ std::unique_ptr<IndexCatalog::IndexIterator> ii =
+ collection->getIndexCatalog()->getIndexIterator(opCtx, false);
auto query = parsedDistinct.getQuery()->getFindCommandRequest().getFilter();
while (ii->more()) {
const IndexCatalogEntry* ice = ii->next();
@@ -2657,7 +2632,9 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDist
auto expCtx = parsedDistinct->getQuery()->getExpCtx();
OperationContext* opCtx = expCtx->opCtx;
- const auto yieldPolicy = PlanYieldPolicy::YieldPolicy::YIELD_AUTO;
+ const auto yieldPolicy = opCtx->inMultiDocumentTransaction()
+ ? PlanYieldPolicy::YieldPolicy::INTERRUPT_ONLY
+ : PlanYieldPolicy::YieldPolicy::YIELD_AUTO;
if (!collection) {
// Treat collections that do not exist as empty collections.