diff options
author | David Storch <david.storch@mongodb.com> | 2020-09-11 09:51:14 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-09-14 21:10:40 +0000 |
commit | fcad026e0d27016c7f79ee70b5a80029e4f2e89f (patch) | |
tree | 8514ac2a3dbffb31bce7cbc4267fac8110e2b7ab /src | |
parent | 5a407eb9c6c11f6da9778f08d8baf5d485c7d666 (diff) | |
download | mongo-fcad026e0d27016c7f79ee70b5a80029e4f2e89f.tar.gz |
SERVER-50726 Add unique id to QuerySolutionNode
This will be useful later for implementing explain output
for the slot-based execution engine.
Diffstat (limited to 'src')
26 files changed, 159 insertions, 84 deletions
diff --git a/src/mongo/db/exec/sbe/expression_test_base.h b/src/mongo/db/exec/sbe/expression_test_base.h index d09deb4f2a8..9884ebb485b 100644 --- a/src/mongo/db/exec/sbe/expression_test_base.h +++ b/src/mongo/db/exec/sbe/expression_test_base.h @@ -32,7 +32,7 @@ #include "mongo/db/exec/sbe/expressions/expression.h" #include "mongo/db/exec/sbe/stages/co_scan.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/slot.h" #include "mongo/db/exec/sbe/vm/vm.h" namespace mongo::sbe { diff --git a/src/mongo/db/exec/sbe/expressions/expression.h b/src/mongo/db/exec/sbe/expressions/expression.h index 91c55ba9c06..c2a308992fe 100644 --- a/src/mongo/db/exec/sbe/expressions/expression.h +++ b/src/mongo/db/exec/sbe/expressions/expression.h @@ -34,7 +34,7 @@ #include <vector> #include "mongo/db/exec/sbe/util/debug_print.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/slot.h" #include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/exec/sbe/vm/vm.h" #include "mongo/stdx/unordered_map.h" diff --git a/src/mongo/db/exec/sbe/parser/parser.h b/src/mongo/db/exec/sbe/parser/parser.h index 87e5b04be7f..8d8819a39c5 100644 --- a/src/mongo/db/exec/sbe/parser/parser.h +++ b/src/mongo/db/exec/sbe/parser/parser.h @@ -36,7 +36,7 @@ #include "mongo/db/exec/sbe/stages/ix_scan.h" #include "mongo/db/exec/sbe/stages/spool.h" #include "mongo/db/exec/sbe/stages/stages.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/slot.h" #include "mongo/db/query/sbe_stage_builder.h" namespace mongo { diff --git a/src/mongo/db/exec/sbe/sbe_plan_stage_test.h b/src/mongo/db/exec/sbe/sbe_plan_stage_test.h index 6fede2f7672..ce636d4f7ad 100644 --- a/src/mongo/db/exec/sbe/sbe_plan_stage_test.h +++ b/src/mongo/db/exec/sbe/sbe_plan_stage_test.h @@ -38,7 +38,7 @@ #include "mongo/db/exec/sbe/stages/project.h" #include "mongo/db/exec/sbe/stages/unwind.h" #include "mongo/db/exec/sbe/values/bson.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/slot.h" #include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/service_context_test_fixture.h" #include "mongo/unittest/unittest.h" diff --git a/src/mongo/db/exec/sbe/values/slot.h b/src/mongo/db/exec/sbe/values/slot.h index a2336250618..be51cff2215 100644 --- a/src/mongo/db/exec/sbe/values/slot.h +++ b/src/mongo/db/exec/sbe/values/slot.h @@ -29,9 +29,11 @@ #pragma once -#include "mongo/db/exec/sbe/values/value.h" #include <boost/container/small_vector.hpp> +#include "mongo/db/exec/sbe/values/value.h" +#include "mongo/util/id_generator.h" + namespace mongo { class BufReader; class BufBuilder; @@ -582,4 +584,8 @@ using SlotAccessorMap = SlotMap<SlotAccessor*>; using FieldAccessorMap = absl::flat_hash_map<std::string, std::unique_ptr<ViewOfValueAccessor>>; using SlotSet = absl::flat_hash_set<SlotId>; using SlotVector = std::vector<SlotId>; + +using SlotIdGenerator = IdGenerator<value::SlotId>; +using FrameIdGenerator = IdGenerator<FrameId>; +using SpoolIdGenerator = IdGenerator<SpoolId>; } // namespace mongo::sbe::value diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index ea3407b8f6a..bdbf08e404f 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -1535,7 +1535,7 @@ namespace { * Otherwise, returns 'false'. */ bool turnIxscanIntoCount(QuerySolution* soln) { - QuerySolutionNode* root = soln->root.get(); + QuerySolutionNode* root = soln->root(); // Root should be an ixscan or fetch w/o any filters. if (!(STAGE_FETCH == root->getType() || STAGE_IXSCAN == root->getType())) { @@ -1583,13 +1583,13 @@ bool turnIxscanIntoCount(QuerySolution* soln) { } // Make the count node that we replace the fetch + ixscan with. - CountScanNode* csn = new CountScanNode(isn->index); + auto csn = std::make_unique<CountScanNode>(isn->index); csn->startKey = startKey; csn->startKeyInclusive = startKeyInclusive; csn->endKey = endKey; csn->endKeyInclusive = endKeyInclusive; // Takes ownership of 'cn' and deletes the old root. - soln->root.reset(csn); + soln->setRoot(std::move(csn)); return true; } @@ -1759,7 +1759,7 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorCoun bool turnIxscanIntoDistinctIxscan(QuerySolution* soln, const std::string& field, bool strictDistinctOnly) { - QuerySolutionNode* root = soln->root.get(); + auto root = soln->root(); // We can attempt to convert a plan if it follows one of these patterns (starting from the // root): @@ -1898,7 +1898,7 @@ bool turnIxscanIntoDistinctIxscan(QuerySolution* soln, root->children.clear(); // Make the fetch the new root. This destroys the project stage. - soln->root.reset(fetchNode); + soln->setRoot(std::unique_ptr<QuerySolutionNode>(fetchNode)); } // Whenver we have a FETCH node, the IXSCAN is its child. We detach the IXSCAN from the diff --git a/src/mongo/db/query/plan_cache.h b/src/mongo/db/query/plan_cache.h index 464370cac35..52337bac042 100644 --- a/src/mongo/db/query/plan_cache.h +++ b/src/mongo/db/query/plan_cache.h @@ -109,7 +109,7 @@ public: namespace plan_ranker { struct PlanRankingDecision; } -struct QuerySolution; +class QuerySolution; struct QuerySolutionNode; /** diff --git a/src/mongo/db/query/plan_cache_test.cpp b/src/mongo/db/query/plan_cache_test.cpp index fc535b0db54..33381e7788e 100644 --- a/src/mongo/db/query/plan_cache_test.cpp +++ b/src/mongo/db/query/plan_cache_test.cpp @@ -1073,8 +1073,7 @@ protected: BSONObj testSoln = fromjson(solnJson); size_t matches = 0; for (auto&& soln : solns) { - QuerySolutionNode* root = soln->root.get(); - if (QueryPlannerTestLib::solutionMatches(testSoln, root)) { + if (QueryPlannerTestLib::solutionMatches(testSoln, soln->root())) { ++matches; } } @@ -1155,8 +1154,7 @@ protected: QuerySolution* firstMatchingSolution(const string& solnJson) const { BSONObj testSoln = fromjson(solnJson); for (auto&& soln : solns) { - QuerySolutionNode* root = soln->root.get(); - if (QueryPlannerTestLib::solutionMatches(testSoln, root)) { + if (QueryPlannerTestLib::solutionMatches(testSoln, soln->root())) { return soln.get(); } } @@ -1178,7 +1176,7 @@ protected: */ void assertSolutionMatches(QuerySolution* trueSoln, const string& solnJson) const { BSONObj testSoln = fromjson(solnJson); - if (!QueryPlannerTestLib::solutionMatches(testSoln, trueSoln->root.get())) { + if (!QueryPlannerTestLib::solutionMatches(testSoln, trueSoln->root())) { str::stream ss; ss << "Expected solution " << solnJson << " did not match true solution: " << trueSoln->toString() << '\n'; diff --git a/src/mongo/db/query/planner_analysis.cpp b/src/mongo/db/query/planner_analysis.cpp index 7f446b8c757..e3fe12fad4d 100644 --- a/src/mongo/db/query/planner_analysis.cpp +++ b/src/mongo/db/query/planner_analysis.cpp @@ -999,7 +999,7 @@ std::unique_ptr<QuerySolution> QueryPlannerAnalysis::analyzeDataAccess( solnRoot = tryPushdownProjectBeneathSort(std::move(solnRoot)); - soln->root = std::move(solnRoot); + soln->setRoot(std::move(solnRoot)); return soln; } diff --git a/src/mongo/db/query/query_planner.cpp b/src/mongo/db/query/query_planner.cpp index 3f11099d0a4..18d7f3543a7 100644 --- a/src/mongo/db/query/query_planner.cpp +++ b/src/mongo/db/query/query_planner.cpp @@ -1063,7 +1063,7 @@ StatusWith<std::vector<std::unique_ptr<QuerySolution>>> QueryPlanner::plan( QueryPlannerParams paramsForCoveredIxScan; auto soln = buildWholeIXSoln(index, query, paramsForCoveredIxScan); - if (soln && !soln->root->fetched()) { + if (soln && !soln->root()->fetched()) { LOGV2_DEBUG( 20983, 5, "Planner: outputting soln that uses index to provide projection"); PlanCacheIndexTree* indexTree = new PlanCacheIndexTree(); diff --git a/src/mongo/db/query/query_planner_options_test.cpp b/src/mongo/db/query/query_planner_options_test.cpp index 2eb180d2d9a..a82a7f405f9 100644 --- a/src/mongo/db/query/query_planner_options_test.cpp +++ b/src/mongo/db/query/query_planner_options_test.cpp @@ -919,7 +919,7 @@ TEST_F(QueryPlannerTest, DollarResumeAfterFieldPropagatedFromQueryRequestToStage runQueryAsCommand(cmdObj); assertHasOnlyCollscan(); - const auto* node = solns.front()->root.get(); + const auto* node = solns.front()->root(); const CollectionScanNode* csn = static_cast<const CollectionScanNode*>(node); ASSERT_EQUALS(RecordId(42LL), csn->resumeAfterRecordId.get()); } diff --git a/src/mongo/db/query/query_planner_test_fixture.cpp b/src/mongo/db/query/query_planner_test_fixture.cpp index 25189abcc81..0bc0a8c8f77 100644 --- a/src/mongo/db/query/query_planner_test_fixture.cpp +++ b/src/mongo/db/query/query_planner_test_fixture.cpp @@ -501,8 +501,7 @@ size_t QueryPlannerTest::numSolutionMatches(const std::string& solnJson) const { BSONObj testSoln = fromjson(solnJson); size_t matches = 0; for (auto&& soln : solns) { - QuerySolutionNode* root = soln->root.get(); - if (QueryPlannerTestLib::solutionMatches(testSoln, root, relaxBoundsCheck)) { + if (QueryPlannerTestLib::solutionMatches(testSoln, soln->root(), relaxBoundsCheck)) { ++matches; } } diff --git a/src/mongo/db/query/query_solution.cpp b/src/mongo/db/query/query_solution.cpp index 9b571f19de3..d45567d7550 100644 --- a/src/mongo/db/query/query_solution.cpp +++ b/src/mongo/db/query/query_solution.cpp @@ -127,6 +127,8 @@ void QuerySolutionNode::addIndent(str::stream* ss, int level) { void QuerySolutionNode::addCommon(str::stream* ss, int indent) const { addIndent(ss, indent + 1); + *ss << "nodeId = " << _nodeId << '\n'; + addIndent(ss, indent + 1); *ss << "fetched = " << fetched() << '\n'; addIndent(ss, indent + 1); *ss << "sortedByDiskLoc = " << sortedByDiskLoc() << '\n'; @@ -148,6 +150,19 @@ bool QuerySolutionNode::hasNode(StageType type) const { return false; } +void QuerySolution::assignNodeIds(QsnIdGenerator& idGenerator, QuerySolutionNode& node) { + for (auto&& child : node.children) { + assignNodeIds(idGenerator, *child); + } + node._nodeId = idGenerator.generate(); +} + +void QuerySolution::setRoot(std::unique_ptr<QuerySolutionNode> root) { + _root = std::move(root); + QsnIdGenerator idGenerator; + assignNodeIds(idGenerator, *_root); +} + // // TextNode // diff --git a/src/mongo/db/query/query_solution.h b/src/mongo/db/query/query_solution.h index 0020b6f8442..09a9cf91f4c 100644 --- a/src/mongo/db/query/query_solution.h +++ b/src/mongo/db/query/query_solution.h @@ -39,6 +39,7 @@ #include "mongo/db/query/index_bounds.h" #include "mongo/db/query/plan_cache.h" #include "mongo/db/query/stage_types.h" +#include "mongo/util/id_generator.h" namespace mongo { @@ -110,7 +111,16 @@ private: * PlanStages, which can then be handed to a PlanRunner for execution. */ struct QuerySolutionNode { - QuerySolutionNode() {} + /** + * Each node in a 'QuerySolution' tree is assigned a unique identifier of this type. The + * identifiers are unique within the tree, but not across trees. + * + * Ids are assigned as sequential positive integers starting from 1. An id of 0 means that no id + * was explicit assigned during construction of the QuerySolution. + */ + using NodeId = uint32_t; + + QuerySolutionNode() = default; /** * Constructs a QuerySolutionNode with a single child. @@ -238,6 +248,10 @@ struct QuerySolutionNode { */ bool hasNode(StageType type) const; + NodeId nodeId() const { + return _nodeId; + } + // These are owned here. // // TODO SERVER-35512: Make this a vector of unique_ptr. @@ -260,8 +274,13 @@ protected: void addCommon(str::stream* ss, int indent) const; private: + // Allows the QuerySolution constructor to set '_nodeId'. + friend class QuerySolution; + QuerySolutionNode(const QuerySolutionNode&) = delete; QuerySolutionNode& operator=(const QuerySolutionNode&) = delete; + + NodeId _nodeId{0u}; }; struct QuerySolutionNodeWithSortSet : public QuerySolutionNode { @@ -291,11 +310,43 @@ struct QuerySolutionNodeWithSortSet : public QuerySolutionNode { * A tree of stages may be built from a QuerySolution. The QuerySolution must outlive the tree * of stages. */ -struct QuerySolution { - QuerySolution() : hasBlockingStage(false), indexFilterApplied(false) {} +class QuerySolution { +public: + QuerySolution() = default; - // Owned here. - std::unique_ptr<QuerySolutionNode> root; + /** + * Return true if this solution tree contains a node of the given 'type'. + */ + bool hasNode(StageType type) const { + return _root && _root->hasNode(type); + } + + /** + * Output a human-readable std::string representing the plan. + */ + std::string toString() { + if (!_root) { + return "empty query solution"; + } + + str::stream ss; + _root->appendToString(&ss, 0); + return ss; + } + + const QuerySolutionNode* root() const { + return _root.get(); + } + QuerySolutionNode* root() { + return _root.get(); + } + + /** + * Assigns the QuerySolutionNode rooted at 'root' to this QuerySolution. Also assigns a unique + * identifying integer to each node in the tree, which can subsequently be displayed in debug + * output (e.g. explain). + */ + void setRoot(std::unique_ptr<QuerySolutionNode> root); // Any filters in root or below point into this object. Must be owned. BSONObj filterData; @@ -309,38 +360,24 @@ struct QuerySolution { // Hashed AND stage: // The hashed AND stage buffers data from multiple index scans and could block. In that case, // we would want to fall back on an alternate non-blocking solution. - bool hasBlockingStage; + bool hasBlockingStage{false}; // Runner executing this solution might be interested in knowing // if the planning process for this solution was based on filtered indices. - bool indexFilterApplied; + bool indexFilterApplied{false}; // Owned here. Used by the plan cache. std::unique_ptr<SolutionCacheData> cacheData; - /** - * True, of this solution tree contains a node of the given 'type'. - */ - bool hasNode(StageType type) const { - return root && root->hasNode(type); - } - - /** - * Output a human-readable std::string representing the plan. - */ - std::string toString() { - if (nullptr == root) { - return "empty query solution"; - } - - str::stream ss; - root->appendToString(&ss, 0); - return ss; - } - private: + using QsnIdGenerator = IdGenerator<QuerySolutionNode::NodeId>; + QuerySolution(const QuerySolution&) = delete; QuerySolution& operator=(const QuerySolution&) = delete; + + void assignNodeIds(QsnIdGenerator& idGenerator, QuerySolutionNode& node); + + std::unique_ptr<QuerySolutionNode> _root; }; struct TextNode : public QuerySolutionNodeWithSortSet { diff --git a/src/mongo/db/query/query_solution_test.cpp b/src/mongo/db/query/query_solution_test.cpp index bcb4ea7c725..e7546a854c9 100644 --- a/src/mongo/db/query/query_solution_test.cpp +++ b/src/mongo/db/query/query_solution_test.cpp @@ -1045,4 +1045,30 @@ TEST(QuerySolutionTest, SharedPrefixMultikeyNonMinMaxBoundsDoesNotProvideAnySort ASSERT_EQUALS(node.providedSorts().getIgnoredFields().size(), 0U); ASSERT_BSONOBJ_EQ(node.providedSorts().getBaseSortPattern(), BSONObj()); } + +TEST(QuerySolutionTest, NodeIdsAssignedInPostOrderFashionStartingFromOne) { + // Construct a QuerySolution consisting of a root node with two children. + std::vector<std::unique_ptr<QuerySolutionNode>> children; + children.push_back(std::make_unique<IndexScanNode>(buildSimpleIndexEntry(BSON("a" << 1)))); + children.push_back(std::make_unique<IndexScanNode>(buildSimpleIndexEntry(BSON("b" << 1)))); + auto orNode = std::make_unique<OrNode>(); + orNode->addChildren(std::move(children)); + + // Before being added to the QuerySolution, all the nodes should have a nodeId of zero, which + // means that an id has not yet been assigned. + ASSERT_EQ(orNode->nodeId(), 0u); + ASSERT_EQ(orNode->children[0]->nodeId(), 0u); + ASSERT_EQ(orNode->children[1]->nodeId(), 0u); + + auto querySolution = std::make_unique<QuerySolution>(); + querySolution->setRoot(std::move(orNode)); + auto root = querySolution->root(); + + // Since ids are assigned according to a post-order traversal, the root node should have id 3, + // the left child should have id 1, and the right child should have id 2. + ASSERT_EQ(root->nodeId(), 3); + ASSERT_EQ(root->children[0]->nodeId(), 1); + ASSERT_EQ(root->children[1]->nodeId(), 2); +} + } // namespace diff --git a/src/mongo/db/query/sbe_stage_builder.h b/src/mongo/db/query/sbe_stage_builder.h index 3137d12156d..ad3f26625c9 100644 --- a/src/mongo/db/query/sbe_stage_builder.h +++ b/src/mongo/db/query/sbe_stage_builder.h @@ -30,8 +30,8 @@ #pragma once #include "mongo/db/exec/sbe/expressions/expression.h" -#include "mongo/db/exec/sbe/values/id_generators.h" #include "mongo/db/exec/sbe/values/slot.h" +#include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/exec/trial_period_utils.h" #include "mongo/db/exec/trial_run_progress_tracker.h" #include "mongo/db/query/plan_yield_policy_sbe.h" diff --git a/src/mongo/db/query/sbe_stage_builder_coll_scan.h b/src/mongo/db/query/sbe_stage_builder_coll_scan.h index f6ed8671739..345f2a411c0 100644 --- a/src/mongo/db/query/sbe_stage_builder_coll_scan.h +++ b/src/mongo/db/query/sbe_stage_builder_coll_scan.h @@ -31,7 +31,7 @@ #include "mongo/db/exec/sbe/expressions/expression.h" #include "mongo/db/exec/sbe/stages/stages.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/exec/trial_run_progress_tracker.h" #include "mongo/db/query/query_solution.h" diff --git a/src/mongo/db/query/sbe_stage_builder_expression.h b/src/mongo/db/query/sbe_stage_builder_expression.h index 4193abfd847..221552b94b0 100644 --- a/src/mongo/db/query/sbe_stage_builder_expression.h +++ b/src/mongo/db/query/sbe_stage_builder_expression.h @@ -31,7 +31,7 @@ #include "mongo/db/exec/sbe/expressions/expression.h" #include "mongo/db/exec/sbe/stages/stages.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/operation_context.h" #include "mongo/db/pipeline/expression.h" diff --git a/src/mongo/db/query/sbe_stage_builder_filter.h b/src/mongo/db/query/sbe_stage_builder_filter.h index 4d1df429a35..5678d31dcf2 100644 --- a/src/mongo/db/query/sbe_stage_builder_filter.h +++ b/src/mongo/db/query/sbe_stage_builder_filter.h @@ -30,7 +30,7 @@ #pragma once #include "mongo/db/exec/sbe/stages/stages.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/matcher/expression.h" namespace mongo::stage_builder { diff --git a/src/mongo/db/query/sbe_stage_builder_index_scan.h b/src/mongo/db/query/sbe_stage_builder_index_scan.h index 63389a33ba6..748e8647439 100644 --- a/src/mongo/db/query/sbe_stage_builder_index_scan.h +++ b/src/mongo/db/query/sbe_stage_builder_index_scan.h @@ -30,7 +30,7 @@ #pragma once #include "mongo/db/exec/sbe/stages/stages.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/exec/trial_run_progress_tracker.h" #include "mongo/db/query/query_solution.h" diff --git a/src/mongo/db/query/sbe_stage_builder_projection.h b/src/mongo/db/query/sbe_stage_builder_projection.h index 00190b4ccd7..dac4c99d7e9 100644 --- a/src/mongo/db/query/sbe_stage_builder_projection.h +++ b/src/mongo/db/query/sbe_stage_builder_projection.h @@ -31,7 +31,7 @@ #include "mongo/db/exec/sbe/expressions/expression.h" #include "mongo/db/exec/sbe/stages/stages.h" -#include "mongo/db/exec/sbe/values/id_generators.h" +#include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/operation_context.h" #include "mongo/db/query/projection.h" diff --git a/src/mongo/db/query/stage_builder_util.cpp b/src/mongo/db/query/stage_builder_util.cpp index 733675aa0b7..9af708df67b 100644 --- a/src/mongo/db/query/stage_builder_util.cpp +++ b/src/mongo/db/query/stage_builder_util.cpp @@ -46,10 +46,10 @@ std::unique_ptr<PlanStage> buildClassicExecutableTree(OperationContext* opCtx, // $text/$where context (and $text/$where are allowed), then no attempt should be made to // execute the query. invariant(!cq.canHaveNoopMatchNodes()); - invariant(solution.root); + invariant(solution.root()); invariant(ws); auto builder = std::make_unique<ClassicStageBuilder>(opCtx, collection, cq, solution, ws); - return builder->build(solution.root.get()); + return builder->build(solution.root()); } std::pair<std::unique_ptr<sbe::PlanStage>, stage_builder::PlanStageData> @@ -64,14 +64,14 @@ buildSlotBasedExecutableTree(OperationContext* opCtx, // $text/$where context (and $text/$where are allowed), then no attempt should be made to // execute the query. invariant(!cq.canHaveNoopMatchNodes()); - invariant(solution.root); + invariant(solution.root()); auto sbeYieldPolicy = dynamic_cast<PlanYieldPolicySBE*>(yieldPolicy); invariant(sbeYieldPolicy); auto builder = std::make_unique<SlotBasedStageBuilder>( opCtx, collection, cq, solution, sbeYieldPolicy, needsTrialRunProgressTracker); - auto root = builder->build(solution.root.get()); + auto root = builder->build(solution.root()); auto data = builder->getPlanStageData(); // Register this plan to yield according to the configured policy. diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp index 0457a67d829..ddd7a9c51cf 100644 --- a/src/mongo/dbtests/plan_ranking.cpp +++ b/src/mongo/dbtests/plan_ranking.cpp @@ -243,7 +243,7 @@ public: ASSERT( QueryPlannerTestLib::solutionMatches("{fetch: {filter: {a:1}, node: " "{ixscan: {filter: null, pattern: {d:1}}}}}", - soln->root.get())); + soln->root())); AutoGetCollectionForReadCommand ctx(&_opCtx, nss); const Collection* collection = ctx.getCollection(); @@ -296,7 +296,7 @@ public: // {a:100} is super selective so choose that. auto soln = pickBestPlan(cq.get()); ASSERT(QueryPlannerTestLib::solutionMatches( - "{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root.get())); + "{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root())); // Turn on the "force intersect" option. // This will be reverted by PlanRankingTestBase's destructor when the test completes. @@ -319,7 +319,7 @@ public: QueryPlannerTestLib::solutionMatches("{fetch: {node: {andSorted: {nodes: [" "{ixscan: {filter: null, pattern: {a:1}}}," "{ixscan: {filter: null, pattern: {b:1}}}]}}}}", - soln->root.get())); + soln->root())); } }; @@ -355,7 +355,7 @@ public: QueryPlannerTestLib::solutionMatches("{fetch: {node: {andHash: {nodes: [" "{ixscan: {filter: null, pattern: {a:1}}}," "{ixscan: {filter: null, pattern: {b:1}}}]}}}}", - soln->root.get())); + soln->root())); // Confirm that a backup plan is available. ASSERT(hasBackupPlan()); @@ -392,7 +392,7 @@ public: // Prefer the fully covered plan. ASSERT(QueryPlannerTestLib::solutionMatches( "{proj: {spec: {_id:0, a:1, b:1}, node: {ixscan: {pattern: {a: 1, b:1}}}}}", - soln->root.get())); + soln->root())); } }; @@ -425,9 +425,9 @@ public: // Anti-prefer the intersection plan. bool bestIsScanOverA = QueryPlannerTestLib::solutionMatches( - "{fetch: {node: {ixscan: {pattern: {a: 1}}}}}", soln->root.get()); + "{fetch: {node: {ixscan: {pattern: {a: 1}}}}}", soln->root()); bool bestIsScanOverB = QueryPlannerTestLib::solutionMatches( - "{fetch: {node: {ixscan: {pattern: {b: 1}}}}}", soln->root.get()); + "{fetch: {node: {ixscan: {pattern: {b: 1}}}}}", soln->root()); ASSERT(bestIsScanOverA || bestIsScanOverB); } }; @@ -464,7 +464,7 @@ public: // Prefer the fully covered plan. ASSERT(QueryPlannerTestLib::solutionMatches( "{proj: {spec: {_id:0, a:1, b:1}, node: {ixscan: {pattern: {a: 1, b:1}}}}}", - soln->root.get())); + soln->root())); } }; @@ -496,7 +496,7 @@ public: // {a: 100} is super selective so choose that. auto soln = pickBestPlan(cq.get()); ASSERT(QueryPlannerTestLib::solutionMatches( - "{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root.get())); + "{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root())); } }; @@ -532,7 +532,7 @@ public: // {a: 100} is super selective so choose that. auto soln = pickBestPlan(cq.get()); ASSERT(QueryPlannerTestLib::solutionMatches( - "{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root.get())); + "{fetch: {filter: {b:1}, node: {ixscan: {pattern: {a: 1}}}}}", soln->root())); } }; @@ -565,7 +565,7 @@ public: "{sort: {pattern: {c: 1}, limit: 0, type:'simple', node:" "{fetch: {filter: null, node: " "{ixscan: {filter: null, pattern: {_id: 1}}}}}}}", - soln->root.get())); + soln->root())); } }; @@ -592,7 +592,7 @@ public: // The best must be a collscan. ASSERT(QueryPlannerTestLib::solutionMatches("{cscan: {dir: 1, filter: {foo: 2001}}}", - soln->root.get())); + soln->root())); } }; @@ -629,7 +629,7 @@ public: ASSERT( QueryPlannerTestLib::solutionMatches("{fetch: {filter: {a:1}, node: " "{ixscan: {filter: null, pattern: {d:1,e:1}}}}}", - soln->root.get())); + soln->root())); } }; @@ -662,7 +662,7 @@ public: // Use index on 'b'. auto soln = pickBestPlan(cq.get()); ASSERT(QueryPlannerTestLib::solutionMatches("{fetch: {node: {ixscan: {pattern: {b: 1}}}}}", - soln->root.get())); + soln->root())); } }; @@ -694,7 +694,7 @@ public: // Expect to use index {a: 1, b: 1}. auto soln = pickBestPlan(cq.get()); ASSERT(QueryPlannerTestLib::solutionMatches("{fetch: {node: {ixscan: {pattern: {a: 1}}}}}", - soln->root.get())); + soln->root())); } }; diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp index 4729de695ea..3d77785ac5c 100644 --- a/src/mongo/dbtests/query_stage_multiplan.cpp +++ b/src/mongo/dbtests/query_stage_multiplan.cpp @@ -422,7 +422,7 @@ TEST_F(QueryStageMultiPlanTest, MPSBackupPlan) { "{fetch: {node: {andSorted: {nodes: [" "{ixscan: {filter: null, pattern: {a:1}}}," "{ixscan: {filter: null, pattern: {b:1}}}]}}}}}}", - soln->root.get())); + soln->root())); // Get the resulting document. PlanStage::StageState state = PlanStage::NEED_TIME; @@ -446,7 +446,7 @@ TEST_F(QueryStageMultiPlanTest, MPSBackupPlan) { "{fetch: {node: {andSorted: {nodes: [" "{ixscan: {filter: null, pattern: {a:1}}}," "{ixscan: {filter: null, pattern: {b:1}}}]}}}}}}", - soln->root.get())); + soln->root())); // Restore index intersection force parameter. internalQueryForceIntersectionPlans.store(forceIxisectOldValue); diff --git a/src/mongo/s/chunk_manager.cpp b/src/mongo/s/chunk_manager.cpp index 9ded562066c..24d0fcf715c 100644 --- a/src/mongo/s/chunk_manager.cpp +++ b/src/mongo/s/chunk_manager.cpp @@ -576,7 +576,7 @@ IndexBounds ChunkManager::getIndexBoundsForQuery(const BSONObj& key, // Pick any solution that has non-trivial IndexBounds. bounds.size() == 0 represents a // trivial IndexBounds where none of the fields' values are bounded. for (auto&& soln : solutions) { - IndexBounds bounds = collapseQuerySolution(soln->root.get()); + IndexBounds bounds = collapseQuerySolution(soln->root()); if (bounds.size() > 0) { return bounds; } diff --git a/src/mongo/db/exec/sbe/values/id_generators.h b/src/mongo/util/id_generator.h index 4b3fae32cca..6f9dfb2b9ab 100644 --- a/src/mongo/db/exec/sbe/values/id_generators.h +++ b/src/mongo/util/id_generator.h @@ -29,9 +29,7 @@ #pragma once -#include "mongo/db/exec/sbe/values/slot.h" - -namespace mongo::sbe::value { +namespace mongo { /** * A reusable id generator suitable for use with integer ids that generates each new id by adding an * increment to the previously generated id. This generator is not thread safe; calls to @@ -76,8 +74,4 @@ public: return idVector; } }; - -using SlotIdGenerator = IdGenerator<value::SlotId>; -using FrameIdGenerator = IdGenerator<FrameId>; -using SpoolIdGenerator = IdGenerator<SpoolId>; -} // namespace mongo::sbe::value +} // namespace mongo |