summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/query/classic_runtime_planner_for_sbe/cached_planner.cpp28
-rw-r--r--src/mongo/db/query/classic_runtime_planner_for_sbe/multi_planner.cpp4
-rw-r--r--src/mongo/db/query/classic_runtime_planner_for_sbe/sub_planner.cpp4
-rw-r--r--src/mongo/db/query/sbe_cached_solution_planner.cpp4
4 files changed, 29 insertions, 11 deletions
diff --git a/src/mongo/db/query/classic_runtime_planner_for_sbe/cached_planner.cpp b/src/mongo/db/query/classic_runtime_planner_for_sbe/cached_planner.cpp
index f5e8bb4471e..9700c9cf664 100644
--- a/src/mongo/db/query/classic_runtime_planner_for_sbe/cached_planner.cpp
+++ b/src/mongo/db/query/classic_runtime_planner_for_sbe/cached_planner.cpp
@@ -30,6 +30,7 @@
#include "mongo/db/query/classic_runtime_planner_for_sbe/planner_interface.h"
#include "mongo/db/exec/trial_period_utils.h"
+#include "mongo/db/query/all_indices_required_checker.h"
#include "mongo/db/query/bind_input_params.h"
#include "mongo/db/query/plan_executor_factory.h"
#include "mongo/db/query/planner_analysis.h"
@@ -96,6 +97,7 @@ void recoverWhereExpression(CanonicalQuery* canonicalQuery,
*/
sbe::plan_ranker::CandidatePlan collectExecutionStatsForCachedPlan(
const PlannerDataForSBE& plannerData,
+ const AllIndicesRequiredChecker& indexExistenceChecker,
std::unique_ptr<sbe::PlanStage> root,
stage_builder::PlanStageData data,
size_t maxTrialPeriodNumReads) {
@@ -145,7 +147,7 @@ sbe::plan_ranker::CandidatePlan collectExecutionStatsForCachedPlan(
plannerData.collections,
*plannerData.cq,
plannerData.sbeYieldPolicy.get(),
- AllIndicesRequiredChecker{plannerData.collections}}
+ indexExistenceChecker}
.executeCachedCandidateTrial(&candidate, maxTrialResults);
return candidate;
@@ -154,8 +156,13 @@ sbe::plan_ranker::CandidatePlan collectExecutionStatsForCachedPlan(
// TODO SERVER-87466 Trigger replanning by throwing an exception, instead of creating another
// planner.
std::unique_ptr<PlannerInterface> replan(PlannerDataForSBE plannerData,
+ const AllIndicesRequiredChecker& indexExistenceChecker,
std::string replanReason,
bool shouldCache) {
+ // The trial run might have allowed DDL commands to be executed during yields. Check if the
+ // provided planner parameters still match the current view of the index catalog.
+ indexExistenceChecker.check(plannerData.opCtx, plannerData.collections);
+
// The plan drawn from the cache is being discarded, and should no longer be
// registered with the yield policy.
plannerData.sbeYieldPolicy->clearRegisteredPlans();
@@ -190,6 +197,7 @@ std::unique_ptr<PlannerInterface> replan(PlannerDataForSBE plannerData,
std::unique_ptr<PlannerInterface> makePlannerForCacheEntry(
PlannerDataForSBE plannerData, std::unique_ptr<sbe::CachedPlanHolder> cachedPlanHolder) {
+ AllIndicesRequiredChecker indexExistenceChecker{plannerData.collections};
const auto& decisionReads = cachedPlanHolder->decisionWorks;
auto sbePlan = std::move(cachedPlanHolder->cachedPlan->root);
auto planStageData = std::move(cachedPlanHolder->cachedPlan->planStageData);
@@ -214,6 +222,7 @@ std::unique_ptr<PlannerInterface> makePlannerForCacheEntry(
if (!QueryPlannerAnalysis::isEligibleForHashJoin(collectionInfo->second)) {
return replan(std::move(plannerData),
+ indexExistenceChecker,
str::stream() << "Foreign collection "
<< foreignCollection.toStringForErrorMsg()
<< " is not eligible for hash join anymore",
@@ -230,8 +239,11 @@ std::unique_ptr<PlannerInterface> makePlannerForCacheEntry(
}
const size_t maxReadsBeforeReplan = internalQueryCacheEvictionRatio * *decisionReads;
- auto candidate = collectExecutionStatsForCachedPlan(
- plannerData, std::move(sbePlan), std::move(planStageData), maxReadsBeforeReplan);
+ auto candidate = collectExecutionStatsForCachedPlan(plannerData,
+ indexExistenceChecker,
+ std::move(sbePlan),
+ std::move(planStageData),
+ maxReadsBeforeReplan);
tassert(8523801, "'debugInfo' should be initialized", candidate.data.stageData.debugInfo);
auto explainer = plan_explainer_factory::make(candidate.root.get(),
@@ -254,7 +266,10 @@ std::unique_ptr<PlannerInterface> makePlannerForCacheEntry(
"error"_attr = candidate.status.toString());
std::string replanReason = str::stream() << "cached plan returned: " << candidate.status;
recoverWhereExpression(plannerData.cq, std::move(candidate));
- return replan(std::move(plannerData), std::move(replanReason), /* shouldCache */ false);
+ return replan(std::move(plannerData),
+ indexExistenceChecker,
+ std::move(replanReason),
+ /* shouldCache */ false);
}
if (candidate.exitedEarly) {
@@ -284,7 +299,10 @@ std::unique_ptr<PlannerInterface> makePlannerForCacheEntry(
<< "cached plan was less efficient than expected: expected trial execution to take "
<< decisionReads << " reads but it took at least " << numReads << " reads";
recoverWhereExpression(plannerData.cq, std::move(candidate));
- return replan(std::move(plannerData), std::move(replanReason), /* shouldCache */ true);
+ return replan(std::move(plannerData),
+ indexExistenceChecker,
+ std::move(replanReason),
+ /* shouldCache */ true);
}
// If the trial run did not exit early, it means no replanning is necessary and can return this
diff --git a/src/mongo/db/query/classic_runtime_planner_for_sbe/multi_planner.cpp b/src/mongo/db/query/classic_runtime_planner_for_sbe/multi_planner.cpp
index 837a55f9f72..706ae897f3a 100644
--- a/src/mongo/db/query/classic_runtime_planner_for_sbe/multi_planner.cpp
+++ b/src/mongo/db/query/classic_runtime_planner_for_sbe/multi_planner.cpp
@@ -120,9 +120,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> MultiPlanner::makeExecutor(
MultiPlanner::SbePlanAndData MultiPlanner::_buildSbePlanAndUpdatePlanCache(
const QuerySolution* winningSolution, const plan_ranker::PlanRankingDecision& ranking) {
- auto sbePlanAndData = stage_builder::buildSlotBasedExecutableTree(
- opCtx(), collections(), *cq(), *winningSolution, sbeYieldPolicy());
- sbePlanAndData.second.replanReason = std::move(_replanReason);
+ auto sbePlanAndData = prepareSbePlanAndData(*winningSolution, std::move(_replanReason));
plan_cache_util::updateSbePlanCacheFromClassicCandidates(opCtx(),
collections(),
_cachingMode,
diff --git a/src/mongo/db/query/classic_runtime_planner_for_sbe/sub_planner.cpp b/src/mongo/db/query/classic_runtime_planner_for_sbe/sub_planner.cpp
index 1cd83ff29e1..dad8d35fd62 100644
--- a/src/mongo/db/query/classic_runtime_planner_for_sbe/sub_planner.cpp
+++ b/src/mongo/db/query/classic_runtime_planner_for_sbe/sub_planner.cpp
@@ -69,9 +69,7 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> SubPlanner::makeExecutor(
*cq(), std::move(solution), plannerParams().secondaryCollectionsInfo);
}
- auto sbePlanAndData = stage_builder::buildSlotBasedExecutableTree(
- opCtx(), collections(), *cq(), *solution, sbeYieldPolicy());
-
+ auto sbePlanAndData = prepareSbePlanAndData(*solution);
plan_cache_util::updatePlanCache(opCtx(),
collections(),
*cq(),
diff --git a/src/mongo/db/query/sbe_cached_solution_planner.cpp b/src/mongo/db/query/sbe_cached_solution_planner.cpp
index 15e83d05a29..259fdcd6fdf 100644
--- a/src/mongo/db/query/sbe_cached_solution_planner.cpp
+++ b/src/mongo/db/query/sbe_cached_solution_planner.cpp
@@ -262,6 +262,10 @@ CandidatePlans CachedSolutionPlanner::replan(const QueryPlannerParams& plannerPa
return std::make_pair(std::move(root), std::move(data));
};
+ // The trial run might have allowed DDL commands to be executed during yields. Check if the
+ // provided planner parameters still match the current view of the index catalog.
+ _indexExistenceChecker.check(_opCtx, _collections);
+
// Use the query planning module to plan the whole query.
auto statusWithMultiPlanSolns = QueryPlanner::plan(_cq, plannerParams);
auto solutions = uassertStatusOK(std::move(statusWithMultiPlanSolns));