summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/pipeline/abt/algebrizer_context.h2
-rw-r--r--src/mongo/db/pipeline/abt/expr_algebrizer_context.h3
-rw-r--r--src/mongo/db/query/ce/sampling_estimator.cpp26
-rw-r--r--src/mongo/db/query/optimizer/cascades/implementers.cpp175
-rw-r--r--src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp9
-rw-r--r--src/mongo/db/query/optimizer/utils/physical_plan_builder.h61
-rw-r--r--src/mongo/db/query/optimizer/utils/utils.cpp466
-rw-r--r--src/mongo/db/query/optimizer/utils/utils.h108
8 files changed, 446 insertions, 404 deletions
diff --git a/src/mongo/db/pipeline/abt/algebrizer_context.h b/src/mongo/db/pipeline/abt/algebrizer_context.h
index 278beb40314..dcff47a0ad5 100644
--- a/src/mongo/db/pipeline/abt/algebrizer_context.h
+++ b/src/mongo/db/pipeline/abt/algebrizer_context.h
@@ -56,7 +56,7 @@ public:
}
template <typename T, typename... Args>
- inline auto setNode(ProjectionName rootProjection, Args&&... args) {
+ void setNode(ProjectionName rootProjection, Args&&... args) {
setNode(std::move(rootProjection), std::move(ABT::make<T>(std::forward<Args>(args)...)));
}
diff --git a/src/mongo/db/pipeline/abt/expr_algebrizer_context.h b/src/mongo/db/pipeline/abt/expr_algebrizer_context.h
index a1f3bedd6de..0c8d82ce0c8 100644
--- a/src/mongo/db/pipeline/abt/expr_algebrizer_context.h
+++ b/src/mongo/db/pipeline/abt/expr_algebrizer_context.h
@@ -49,9 +49,10 @@ public:
* 'assertExprSort' and 'assertPathSort'
*/
template <typename T, typename... Args>
- inline auto push(Args&&... args) {
+ void push(Args&&... args) {
push(ABT::make<T>(std::forward<Args>(args)...));
}
+
void push(ABT node);
/*
diff --git a/src/mongo/db/query/ce/sampling_estimator.cpp b/src/mongo/db/query/ce/sampling_estimator.cpp
index 63cfa58b527..5573f67e3ca 100644
--- a/src/mongo/db/query/ce/sampling_estimator.cpp
+++ b/src/mongo/db/query/ce/sampling_estimator.cpp
@@ -73,7 +73,11 @@ public:
}
void transport(ABT& n, const SargableNode& node, ABT& childResult, ABT& refs, ABT& binds) {
- ABT result = childResult;
+ // We don't need to estimate cardinality of the sampling query itself, so the NodeCEMap part
+ // is ignored here. We use a builder only because lowerPartialSchemaRequirement requires
+ // one.
+ PhysPlanBuilder result{childResult};
+
// Retain only output bindings without applying filters.
for (const auto& [key, req] : node.getReqMap().conjuncts()) {
if (const auto& boundProjName = req.getBoundProjectionName()) {
@@ -81,11 +85,12 @@ public:
key,
PartialSchemaRequirement{
boundProjName, IntervalReqExpr::makeSingularDNF(), req.getIsPerfOnly()},
- result,
- _phaseManager.getPathToInterval());
+ _phaseManager.getPathToInterval(),
+ boost::none /*residualCE*/,
+ result);
}
}
- std::swap(n, result);
+ std::swap(n, result._node);
}
void transport(ABT& n, const CollationNode& /*node*/, ABT& childResult, ABT& refs) {
@@ -168,18 +173,19 @@ public:
}
if (!isIntervalReqFullyOpenDNF(req.getIntervals())) {
- ABT lowered = extracted;
+ PhysPlanBuilder lowered{extracted};
// Lower requirement without an output binding.
lowerPartialSchemaRequirement(
key,
PartialSchemaRequirement{boost::none /*boundProjectionName*/,
req.getIntervals(),
req.getIsPerfOnly()},
- lowered,
- _phaseManager.getPathToInterval());
- uassert(6624243, "Expected a filter node", lowered.is<FilterNode>());
- result =
- estimateFilterCE(metadata, memo, logicalProps, n, std::move(lowered), result);
+ _phaseManager.getPathToInterval(),
+ boost::none /*residualCE*/,
+ lowered);
+ uassert(6624243, "Expected a filter node", lowered._node.is<FilterNode>());
+ result = estimateFilterCE(
+ metadata, memo, logicalProps, n, std::move(lowered._node), result);
}
}
diff --git a/src/mongo/db/query/optimizer/cascades/implementers.cpp b/src/mongo/db/query/optimizer/cascades/implementers.cpp
index c14aa724564..05f6326301b 100644
--- a/src/mongo/db/query/optimizer/cascades/implementers.cpp
+++ b/src/mongo/db/query/optimizer/cascades/implementers.cpp
@@ -134,23 +134,19 @@ public:
}
if (indexReqTarget == IndexReqTarget::Seek) {
- NodeCEMap nodeCEMap;
-
- ABT physicalSeek =
- make<SeekNode>(ridProjName, std::move(fieldProjectionMap), node.getScanDefName());
+ PhysPlanBuilder builder;
// If optimizing a Seek, override CE to 1.0.
- nodeCEMap.emplace(physicalSeek.cast<Node>(), CEType{1.0});
-
- ABT limitSkip =
- make<LimitSkipNode>(LimitSkipRequirement{1, 0}, std::move(physicalSeek));
- nodeCEMap.emplace(limitSkip.cast<Node>(), CEType{1.0});
+ builder.make<SeekNode>(
+ CEType{1.0}, ridProjName, std::move(fieldProjectionMap), node.getScanDefName());
+ builder.make<LimitSkipNode>(
+ CEType{1.0}, LimitSkipRequirement{1, 0}, std::move(builder._node));
optimizeChildrenNoAssert(_queue,
kDefaultPriority,
PhysicalRewriteType::Seek,
- std::move(limitSkip),
+ std::move(builder._node),
{},
- std::move(nodeCEMap));
+ std::move(builder._nodeCEMap));
} else {
ABT physicalScan = make<PhysicalScanNode>(
std::move(fieldProjectionMap), node.getScanDefName(), canUseParallelScan);
@@ -184,44 +180,40 @@ public:
return;
}
- NodeCEMap nodeCEMap;
- ABT physNode = make<CoScanNode>();
+ PhysPlanBuilder builder;
if (node.getArraySize() == 0) {
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{0.0});
-
- physNode = make<LimitSkipNode>(LimitSkipRequirement{0, 0}, std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{0.0});
+ builder.make<CoScanNode>(CEType{0.0});
+ builder.make<LimitSkipNode>(
+ CEType{0.0}, LimitSkipRequirement{0, 0}, std::move(builder._node));
for (const ProjectionName& boundProjName : node.binder().names()) {
if (requiredProjections.find(boundProjName)) {
- physNode = make<EvaluationNode>(
- boundProjName, Constant::nothing(), std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{0.0});
+ builder.make<EvaluationNode>(
+ CEType{0.0}, boundProjName, Constant::nothing(), std::move(builder._node));
}
}
if (needsRID) {
- physNode = make<EvaluationNode>(
- std::move(*ridProjName), Constant::nothing(), std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{0.0});
+ builder.make<EvaluationNode>(CEType{0.0},
+ std::move(*ridProjName),
+ Constant::nothing(),
+ std::move(builder._node));
}
} else {
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{1.0});
-
- physNode = make<LimitSkipNode>(LimitSkipRequirement{1, 0}, std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{1.0});
+ builder.make<CoScanNode>(CEType{1.0});
+ builder.make<LimitSkipNode>(
+ CEType{1.0}, LimitSkipRequirement{1, 0}, std::move(builder._node));
const ProjectionName valueScanProj{_prefixId.getNextId("valueScan")};
- physNode =
- make<EvaluationNode>(valueScanProj, node.getValueArray(), std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{1.0});
+ builder.make<EvaluationNode>(
+ CEType{1.0}, valueScanProj, node.getValueArray(), std::move(builder._node));
// Unwind the combined array constant and pick an element for each required projection
// in sequence.
- physNode = make<UnwindNode>(valueScanProj,
- _prefixId.getNextId("valueScanPid"),
- false /*retainNonArrays*/,
- std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), CEType{1.0});
+ builder.make<UnwindNode>(CEType{1.0},
+ valueScanProj,
+ _prefixId.getNextId("valueScanPid"),
+ false /*retainNonArrays*/,
+ std::move(builder._node));
const auto getElementFn = [&valueScanProj](const size_t index) {
return make<FunctionCall>(
@@ -232,32 +224,30 @@ public:
// the array elements are ordered accordingly. Skip over the first element (this is the
// row id).
const ProjectionNameVector& boundProjNames = node.binder().names();
+ const CEType arraySize{static_cast<double>(node.getArraySize())};
for (size_t i = 0; i < boundProjNames.size(); i++) {
const ProjectionName& boundProjName = boundProjNames.at(i);
if (requiredProjections.find(boundProjName)) {
- physNode = make<EvaluationNode>(boundProjName,
- getElementFn(i + (node.getHasRID() ? 1 : 0)),
- std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(),
- CEType{static_cast<double>(node.getArraySize())});
+ builder.make<EvaluationNode>(arraySize,
+ boundProjName,
+ getElementFn(i + (node.getHasRID() ? 1 : 0)),
+ std::move(builder._node));
}
}
if (needsRID) {
// Obtain row id from first element of the array.
- physNode = make<EvaluationNode>(
- std::move(*ridProjName), getElementFn(0), std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(),
- CEType{static_cast<double>(node.getArraySize())});
+ builder.make<EvaluationNode>(
+ arraySize, std::move(*ridProjName), getElementFn(0), std::move(builder._node));
}
}
optimizeChildrenNoAssert(_queue,
kDefaultPriority,
PhysicalRewriteType::ValueScan,
- std::move(physNode),
+ std::move(builder._node),
{},
- std::move(nodeCEMap));
+ std::move(builder._nodeCEMap));
}
void operator()(const ABT& /*n*/, const MemoLogicalDelegatorNode& /*node*/) {
@@ -590,8 +580,7 @@ public:
}
invariant(eqPrefixes.size() == reverseOrder.size());
- NodeCEMap nodeCEMap;
- ABT physNode = lowerEqPrefixes(_prefixId,
+ auto builder = lowerEqPrefixes(_prefixId,
ridProjName,
std::move(indexProjectionMap),
scanDefName,
@@ -604,29 +593,27 @@ public:
candidateIndexEntry._correlatedProjNames.getVector(),
std::move(indexPredSelMap),
currentGroupCE,
- scanGroupCE,
- nodeCEMap);
+ scanGroupCE);
lowerPartialSchemaRequirements(scanGroupCE,
std::move(indexPredSels),
residualReqsWithCE,
- physNode,
_pathToInterval,
- nodeCEMap);
+ builder);
if (needsUniqueStage) {
// Insert unique stage if we need to, after the residual requirements.
- physNode =
- make<UniqueNode>(ProjectionNameVector{ridProjName}, std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), currentGroupCE);
+ builder.make<UniqueNode>(currentGroupCE,
+ ProjectionNameVector{ridProjName},
+ std::move(builder._node));
}
optimizeChildrenNoAssert(_queue,
kDefaultPriority,
PhysicalRewriteType::SargableToIndex,
- std::move(physNode),
+ std::move(builder._node),
{},
- std::move(nodeCEMap));
+ std::move(builder._nodeCEMap));
}
} else {
const auto& scanParams = node.getScanParams();
@@ -654,8 +641,7 @@ public:
fieldProjectionMap._rootProjection = scanProjectionName;
}
- NodeCEMap nodeCEMap;
- ABT physNode = make<Blackhole>();
+ PhysPlanBuilder builder;
CEType baseCE{0.0};
PhysicalRewriteType rule = PhysicalRewriteType::Uninitialized;
@@ -663,19 +649,18 @@ public:
baseCE = scanGroupCE;
// Return a physical scan with field map.
- physNode = make<PhysicalScanNode>(
- std::move(fieldProjectionMap), scanDefName, canUseParallelScan);
- nodeCEMap.emplace(physNode.cast<Node>(), baseCE);
+ builder.make<PhysicalScanNode>(
+ baseCE, std::move(fieldProjectionMap), scanDefName, canUseParallelScan);
rule = PhysicalRewriteType::SargableToPhysicalScan;
} else {
baseCE = {1.0};
// Try Seek with Limit 1.
- physNode = make<SeekNode>(ridProjName, std::move(fieldProjectionMap), scanDefName);
- nodeCEMap.emplace(physNode.cast<Node>(), baseCE);
+ builder.make<SeekNode>(
+ baseCE, ridProjName, std::move(fieldProjectionMap), scanDefName);
- physNode = make<LimitSkipNode>(LimitSkipRequirement{1, 0}, std::move(physNode));
- nodeCEMap.emplace(physNode.cast<Node>(), baseCE);
+ builder.make<LimitSkipNode>(
+ baseCE, LimitSkipRequirement{1, 0}, std::move(builder._node));
rule = PhysicalRewriteType::SargableToSeek;
}
@@ -685,14 +670,14 @@ public:
residualKey, residualReq, partialSchemaKeyCE.at(entryIndex).second);
}
- lowerPartialSchemaRequirements(baseCE,
- {} /*indexPredSels*/,
- residualReqsWithCE,
- physNode,
- _pathToInterval,
- nodeCEMap);
- optimizeChildrenNoAssert(
- _queue, kDefaultPriority, rule, std::move(physNode), {}, std::move(nodeCEMap));
+ lowerPartialSchemaRequirements(
+ baseCE, {} /*indexPredSels*/, residualReqsWithCE, _pathToInterval, builder);
+ optimizeChildrenNoAssert(_queue,
+ kDefaultPriority,
+ rule,
+ std::move(builder._node),
+ {},
+ std::move(builder._nodeCEMap));
}
}
@@ -1558,8 +1543,6 @@ private:
// Try a merge join on RID since both of our children only have equality
// predicates.
- NodeCEMap nodeCEMap;
- ChildPropsType childProps;
PhysProps leftPhysPropsLocal = leftPhysProps;
PhysProps rightPhysPropsLocal = rightPhysProps;
@@ -1582,30 +1565,28 @@ private:
.setDedupRID(true /*dedupRID*/);
}
- ABT physNode = lowerRIDIntersectMergeJoin(_prefixId,
+ ChildPropsType childProps;
+ auto builder = lowerRIDIntersectMergeJoin(_prefixId,
ridProjectionName,
intersectedCE,
leftCE,
rightCE,
leftPhysPropsLocal,
rightPhysPropsLocal,
- leftChild,
- rightChild,
- nodeCEMap,
+ {leftChild},
+ {rightChild},
childProps);
optimizeChildrenNoAssert(_queue,
kDefaultPriority,
PhysicalRewriteType::RIDIntersectMergeJoin,
- std::move(physNode),
+ std::move(builder._node),
std::move(childProps),
- std::move(nodeCEMap));
+ std::move(builder._nodeCEMap));
} else {
if (!_hints._disableHashJoinRIDIntersect) {
// Try a HashJoin. Propagate dedupRID on left and right indexing
// requirements.
- NodeCEMap nodeCEMap;
- ChildPropsType childProps;
PhysProps leftPhysPropsLocal = leftPhysProps;
PhysProps rightPhysPropsLocal = rightPhysProps;
@@ -1618,23 +1599,23 @@ private:
.setDedupRID(true /*dedupRID*/);
}
- ABT physNode = lowerRIDIntersectHashJoin(_prefixId,
+ ChildPropsType childProps;
+ auto builder = lowerRIDIntersectHashJoin(_prefixId,
ridProjectionName,
intersectedCE,
leftCE,
rightCE,
leftPhysPropsLocal,
rightPhysPropsLocal,
- leftChild,
- rightChild,
- nodeCEMap,
+ {leftChild},
+ {rightChild},
childProps);
optimizeChildrenNoAssert(_queue,
kDefaultPriority,
PhysicalRewriteType::RIDIntersectHashJoin,
- std::move(physNode),
+ std::move(builder._node),
std::move(childProps),
- std::move(nodeCEMap));
+ std::move(builder._nodeCEMap));
}
// We can only attempt this strategy if we have no collation requirements.
@@ -1644,15 +1625,14 @@ private:
// Try a Union+GroupBy. left and right indexing requirements are already
// initialized to not dedup.
- NodeCEMap nodeCEMap;
- ChildPropsType childProps;
PhysProps leftPhysPropsLocal = leftPhysProps;
PhysProps rightPhysPropsLocal = rightPhysProps;
setCollationForRIDIntersect(
collationLeftRightSplit, leftPhysPropsLocal, rightPhysPropsLocal);
- ABT physNode = lowerRIDIntersectGroupBy(_prefixId,
+ ChildPropsType childProps;
+ auto builder = lowerRIDIntersectGroupBy(_prefixId,
ridProjectionName,
intersectedCE,
leftCE,
@@ -1660,16 +1640,15 @@ private:
_physProps,
leftPhysPropsLocal,
rightPhysPropsLocal,
- leftChild,
- rightChild,
- nodeCEMap,
+ {leftChild},
+ {rightChild},
childProps);
optimizeChildrenNoAssert(_queue,
kDefaultPriority,
PhysicalRewriteType::RIDIntersectGroupBy,
- std::move(physNode),
+ std::move(builder._node),
std::move(childProps),
- std::move(nodeCEMap));
+ std::move(builder._nodeCEMap));
}
}
} else {
diff --git a/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp b/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
index a13ae81cdc5..93625e831d8 100644
--- a/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
+++ b/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
@@ -1168,12 +1168,13 @@ struct SubstituteConvert<EvaluationNode> {
};
static void lowerSargableNode(const SargableNode& node, RewriteContext& ctx) {
- ABT n = node.getChild();
- const auto reqMap = node.getReqMap();
+ PhysPlanBuilder builder{node.getChild()};
+ const auto& reqMap = node.getReqMap();
for (const auto& [key, req] : reqMap.conjuncts()) {
- lowerPartialSchemaRequirement(key, req, n, ctx.getPathToInterval());
+ lowerPartialSchemaRequirement(
+ key, req, ctx.getPathToInterval(), boost::none /*residualCE*/, builder);
}
- ctx.addNode(n, true /*clear*/);
+ ctx.addNode(builder._node, true /*clear*/);
}
template <class Type>
diff --git a/src/mongo/db/query/optimizer/utils/physical_plan_builder.h b/src/mongo/db/query/optimizer/utils/physical_plan_builder.h
new file mode 100644
index 00000000000..37df17e37da
--- /dev/null
+++ b/src/mongo/db/query/optimizer/utils/physical_plan_builder.h
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2023-present MongoDB, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the Server Side Public License, version 1,
+ * as published by MongoDB, Inc.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Server Side Public License for more details.
+ *
+ * You should have received a copy of the Server Side Public License
+ * along with this program. If not, see
+ * <http://www.mongodb.com/licensing/server-side-public-license>.
+ *
+ * As a special exception, the copyright holders give permission to link the
+ * code of portions of this program with the OpenSSL library under certain
+ * conditions as described in each individual source file and distribute
+ * linked combinations including the program with the OpenSSL library. You
+ * must comply with the Server Side Public License in all respects for
+ * all of the code used other than as permitted herein. If you modify file(s)
+ * with this exception, you may extend this exception to your version of the
+ * file(s), but you are not obligated to do so. If you do not wish to do so,
+ * delete this exception statement from your version. If you delete this
+ * exception statement from all source files in the program, then also delete
+ * it in the license file.
+ */
+
+#pragma once
+
+namespace mongo::optimizer {
+
+/**
+ * Used to construct physical plans bottom-up, and keep track of per-node cardinality estimation.
+ */
+struct PhysPlanBuilder {
+ /**
+ * Construct a new root node for the plan.
+ */
+ template <typename T, typename... Args>
+ void make(const boost::optional<CEType> ce, Args&&... args) {
+ static_assert(canBePhysicalNode<T>(), "Only physical nodes allowed here.");
+ _node = ABT::make<T>(std::forward<Args>(args)...);
+ if (ce) {
+ _nodeCEMap.emplace(_node.cast<Node>(), *ce);
+ }
+ }
+
+ /**
+ * Merge cardinality estimate maps from another builder.
+ */
+ void merge(PhysPlanBuilder& other) {
+ _nodeCEMap.merge(other._nodeCEMap);
+ }
+
+ ABT _node = ::mongo::optimizer::make<Blackhole>();
+ NodeCEMap _nodeCEMap;
+};
+
+} // namespace mongo::optimizer
diff --git a/src/mongo/db/query/optimizer/utils/utils.cpp b/src/mongo/db/query/optimizer/utils/utils.cpp
index 660ee538fcf..24ab7aeddd4 100644
--- a/src/mongo/db/query/optimizer/utils/utils.cpp
+++ b/src/mongo/db/query/optimizer/utils/utils.cpp
@@ -142,8 +142,8 @@ ProjectionNameSet extractReferencedColumns(const properties::PhysProps& properti
return PropertiesAffectedColumnsExtractor::extract(properties);
}
-void restrictProjections(ProjectionNameVector projNames, ABT& input) {
- input = make<UnionNode>(std::move(projNames), makeSeq(std::move(input)));
+void restrictProjections(ProjectionNameVector projNames, const CEType ce, PhysPlanBuilder& input) {
+ input.make<UnionNode>(ce, std::move(projNames), makeSeq(std::move(input._node)));
}
CollationSplitResult splitCollationSpec(const boost::optional<ProjectionName>& ridProjName,
@@ -1731,24 +1731,26 @@ private:
void lowerPartialSchemaRequirement(const PartialSchemaKey& key,
const PartialSchemaRequirement& req,
- ABT& node,
const PathToIntervalFn& pathToInterval,
- const std::function<void(const ABT& node)>& visitor) {
+ const boost::optional<CEType> residualCE,
+ PhysPlanBuilder& builder) {
PartialSchemaReqLowerTransport transport(req.getBoundProjectionName().has_value(),
pathToInterval);
ABT path = transport.lower(req.getIntervals());
const bool pathIsId = path.is<PathIdentity>();
if (const auto& boundProjName = req.getBoundProjectionName()) {
- node = make<EvaluationNode>(*boundProjName,
- make<EvalPath>(key._path, make<Variable>(*key._projectionName)),
- std::move(node));
- visitor(node);
+ builder.make<EvaluationNode>(
+ residualCE,
+ *boundProjName,
+ make<EvalPath>(key._path, make<Variable>(*key._projectionName)),
+ std::move(builder._node));
if (!pathIsId) {
- node = make<FilterNode>(
- make<EvalFilter>(std::move(path), make<Variable>(*boundProjName)), std::move(node));
- visitor(node);
+ builder.make<FilterNode>(
+ residualCE,
+ make<EvalFilter>(std::move(path), make<Variable>(*boundProjName)),
+ std::move(builder._node));
}
} else {
uassert(
@@ -1756,19 +1758,18 @@ void lowerPartialSchemaRequirement(const PartialSchemaKey& key,
path = PathAppender::append(key._path, std::move(path));
- node = make<FilterNode>(
+ builder.make<FilterNode>(
+ residualCE,
make<EvalFilter>(std::move(path), make<Variable>(*key._projectionName)),
- std::move(node));
- visitor(node);
+ std::move(builder._node));
}
}
void lowerPartialSchemaRequirements(const CEType scanGroupCE,
std::vector<SelectivityType> indexPredSels,
ResidualRequirementsWithCE& requirements,
- ABT& physNode,
const PathToIntervalFn& pathToInterval,
- NodeCEMap& nodeCEMap) {
+ PhysPlanBuilder& builder) {
sortResidualRequirements(requirements);
for (const auto& [residualKey, residualReq, ce] : requirements) {
@@ -1784,9 +1785,7 @@ void lowerPartialSchemaRequirements(const CEType scanGroupCE,
}
lowerPartialSchemaRequirement(
- residualKey, residualReq, physNode, pathToInterval, [&](const ABT& node) {
- nodeCEMap.emplace(node.cast<Node>(), residualCE);
- });
+ residualKey, residualReq, pathToInterval, residualCE, builder);
}
}
@@ -1869,18 +1868,17 @@ void removeRedundantResidualPredicates(const ProjectionNameOrderPreservingSet& r
}
}
-ABT lowerRIDIntersectGroupBy(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- const CEType intersectedCE,
- const CEType leftCE,
- const CEType rightCE,
- const properties::PhysProps& physProps,
- const properties::PhysProps& leftPhysProps,
- const properties::PhysProps& rightPhysProps,
- ABT leftChild,
- ABT rightChild,
- NodeCEMap& nodeCEMap,
- ChildPropsType& childProps) {
+PhysPlanBuilder lowerRIDIntersectGroupBy(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ const CEType intersectedCE,
+ const CEType leftCE,
+ const CEType rightCE,
+ const properties::PhysProps& physProps,
+ const properties::PhysProps& leftPhysProps,
+ const properties::PhysProps& rightPhysProps,
+ PhysPlanBuilder leftChild,
+ PhysPlanBuilder rightChild,
+ ChildPropsType& childProps) {
using namespace properties;
const auto& leftProjections =
@@ -1896,15 +1894,13 @@ ABT lowerRIDIntersectGroupBy(PrefixId& prefixId,
make<FunctionCall>("$addToSet", makeSeq(make<Variable>(sideIdProjectionName))));
aggProjectionNames.push_back(sideSetProjectionName);
- leftChild =
- make<EvaluationNode>(sideIdProjectionName, Constant::int64(0), std::move(leftChild));
- childProps.emplace_back(&leftChild.cast<EvaluationNode>()->getChild(), leftPhysProps);
- nodeCEMap.emplace(leftChild.cast<Node>(), leftCE);
+ leftChild.make<EvaluationNode>(
+ leftCE, sideIdProjectionName, Constant::int64(0), std::move(leftChild._node));
+ childProps.emplace_back(&leftChild._node.cast<EvaluationNode>()->getChild(), leftPhysProps);
- rightChild =
- make<EvaluationNode>(sideIdProjectionName, Constant::int64(1), std::move(rightChild));
- childProps.emplace_back(&rightChild.cast<EvaluationNode>()->getChild(), rightPhysProps);
- nodeCEMap.emplace(rightChild.cast<Node>(), rightCE);
+ rightChild.make<EvaluationNode>(
+ rightCE, sideIdProjectionName, Constant::int64(1), std::move(rightChild._node));
+ childProps.emplace_back(&rightChild._node.cast<EvaluationNode>()->getChild(), rightPhysProps);
ProjectionNameVector sortedProjections =
getPropertyConst<ProjectionRequirement>(physProps).getProjections().getVector();
@@ -1920,21 +1916,19 @@ ABT lowerRIDIntersectGroupBy(PrefixId& prefixId,
unionProjections.push_back(tempProjectionName);
if (leftProjections.find(projectionName)) {
- leftChild = make<EvaluationNode>(
- tempProjectionName, make<Variable>(projectionName), std::move(leftChild));
- nodeCEMap.emplace(leftChild.cast<Node>(), leftCE);
-
- rightChild = make<EvaluationNode>(
- tempProjectionName, Constant::nothing(), std::move(rightChild));
- nodeCEMap.emplace(rightChild.cast<Node>(), rightCE);
+ leftChild.make<EvaluationNode>(leftCE,
+ tempProjectionName,
+ make<Variable>(projectionName),
+ std::move(leftChild._node));
+ rightChild.make<EvaluationNode>(
+ rightCE, tempProjectionName, Constant::nothing(), std::move(rightChild._node));
} else {
- leftChild =
- make<EvaluationNode>(tempProjectionName, Constant::nothing(), std::move(leftChild));
- nodeCEMap.emplace(leftChild.cast<Node>(), leftCE);
-
- rightChild = make<EvaluationNode>(
- tempProjectionName, make<Variable>(projectionName), std::move(rightChild));
- nodeCEMap.emplace(rightChild.cast<Node>(), rightCE);
+ leftChild.make<EvaluationNode>(
+ leftCE, tempProjectionName, Constant::nothing(), std::move(leftChild._node));
+ rightChild.make<EvaluationNode>(rightCE,
+ tempProjectionName,
+ make<Variable>(projectionName),
+ std::move(rightChild._node));
}
aggExpressions.emplace_back(
@@ -1942,44 +1936,45 @@ ABT lowerRIDIntersectGroupBy(PrefixId& prefixId,
aggProjectionNames.push_back(projectionName);
}
- ABT result = make<UnionNode>(std::move(unionProjections),
- makeSeq(std::move(leftChild), std::move(rightChild)));
- nodeCEMap.emplace(result.cast<Node>(), leftCE + rightCE);
+ PhysPlanBuilder result;
+ result.make<UnionNode>(leftCE + rightCE,
+ std::move(unionProjections),
+ makeSeq(std::move(leftChild._node), std::move(rightChild._node)));
+ result.merge(leftChild);
+ result.merge(rightChild);
- result = make<GroupByNode>(ProjectionNameVector{ridProjName},
- std::move(aggProjectionNames),
- std::move(aggExpressions),
- std::move(result));
- nodeCEMap.emplace(result.cast<Node>(), intersectedCE);
+ result.make<GroupByNode>(intersectedCE,
+ ProjectionNameVector{ridProjName},
+ std::move(aggProjectionNames),
+ std::move(aggExpressions),
+ std::move(result._node));
- result = make<FilterNode>(
+ result.make<FilterNode>(
+ intersectedCE,
make<EvalFilter>(
make<PathCompare>(Operations::Eq, Constant::int64(2)),
make<FunctionCall>("getArraySize", makeSeq(make<Variable>(sideSetProjectionName)))),
- std::move(result));
- nodeCEMap.emplace(result.cast<Node>(), intersectedCE);
+ std::move(result._node));
return result;
}
-ABT lowerRIDIntersectHashJoin(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- const CEType intersectedCE,
- const CEType leftCE,
- const CEType rightCE,
- const properties::PhysProps& leftPhysProps,
- const properties::PhysProps& rightPhysProps,
- ABT leftChild,
- ABT rightChild,
- NodeCEMap& nodeCEMap,
- ChildPropsType& childProps) {
+PhysPlanBuilder lowerRIDIntersectHashJoin(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ const CEType intersectedCE,
+ const CEType leftCE,
+ const CEType rightCE,
+ const properties::PhysProps& leftPhysProps,
+ const properties::PhysProps& rightPhysProps,
+ PhysPlanBuilder leftChild,
+ PhysPlanBuilder rightChild,
+ ChildPropsType& childProps) {
using namespace properties;
ProjectionName rightRIDProjName = prefixId.getNextId("rid");
- rightChild =
- make<EvaluationNode>(rightRIDProjName, make<Variable>(ridProjName), std::move(rightChild));
- ABT* rightChildPtr = &rightChild.cast<EvaluationNode>()->getChild();
- nodeCEMap.emplace(rightChild.cast<Node>(), rightCE);
+ rightChild.make<EvaluationNode>(
+ rightCE, rightRIDProjName, make<Variable>(ridProjName), std::move(rightChild._node));
+ ABT* rightChildPtr = &rightChild._node.cast<EvaluationNode>()->getChild();
auto rightProjections =
getPropertyConst<ProjectionRequirement>(rightPhysProps).getProjections();
@@ -1991,40 +1986,40 @@ ABT lowerRIDIntersectHashJoin(PrefixId& prefixId,
// Use a union node to restrict the rid projection name coming from the right child in order
// to ensure we do not have the same rid from both children. This node is optimized away
// during lowering.
- restrictProjections(std::move(sortedProjections), rightChild);
- nodeCEMap.emplace(rightChild.cast<Node>(), rightCE);
-
- ABT result = make<HashJoinNode>(JoinType::Inner,
- ProjectionNameVector{ridProjName},
- ProjectionNameVector{std::move(rightRIDProjName)},
- std::move(leftChild),
- std::move(rightChild));
- nodeCEMap.emplace(result.cast<Node>(), intersectedCE);
-
- childProps.emplace_back(&result.cast<HashJoinNode>()->getLeftChild(), leftPhysProps);
+ restrictProjections(std::move(sortedProjections), rightCE, rightChild);
+
+ PhysPlanBuilder result;
+ result.make<HashJoinNode>(intersectedCE,
+ JoinType::Inner,
+ ProjectionNameVector{ridProjName},
+ ProjectionNameVector{std::move(rightRIDProjName)},
+ std::move(leftChild._node),
+ std::move(rightChild._node));
+ result.merge(leftChild);
+ result.merge(rightChild);
+
+ childProps.emplace_back(&result._node.cast<HashJoinNode>()->getLeftChild(), leftPhysProps);
childProps.emplace_back(rightChildPtr, rightPhysProps);
return result;
}
-ABT lowerRIDIntersectMergeJoin(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- const CEType intersectedCE,
- const CEType leftCE,
- const CEType rightCE,
- const properties::PhysProps& leftPhysProps,
- const properties::PhysProps& rightPhysProps,
- ABT leftChild,
- ABT rightChild,
- NodeCEMap& nodeCEMap,
- ChildPropsType& childProps) {
+PhysPlanBuilder lowerRIDIntersectMergeJoin(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ const CEType intersectedCE,
+ const CEType leftCE,
+ const CEType rightCE,
+ const properties::PhysProps& leftPhysProps,
+ const properties::PhysProps& rightPhysProps,
+ PhysPlanBuilder leftChild,
+ PhysPlanBuilder rightChild,
+ ChildPropsType& childProps) {
using namespace properties;
ProjectionName rightRIDProjName = prefixId.getNextId("rid");
- rightChild =
- make<EvaluationNode>(rightRIDProjName, make<Variable>(ridProjName), std::move(rightChild));
- ABT* rightChildPtr = &rightChild.cast<EvaluationNode>()->getChild();
- nodeCEMap.emplace(rightChild.cast<Node>(), rightCE);
+ rightChild.make<EvaluationNode>(
+ rightCE, rightRIDProjName, make<Variable>(ridProjName), std::move(rightChild._node));
+ ABT* rightChildPtr = &rightChild._node.cast<EvaluationNode>()->getChild();
auto rightProjections =
getPropertyConst<ProjectionRequirement>(rightPhysProps).getProjections();
@@ -2036,17 +2031,19 @@ ABT lowerRIDIntersectMergeJoin(PrefixId& prefixId,
// Use a union node to restrict the rid projection name coming from the right child in order
// to ensure we do not have the same rid from both children. This node is optimized away
// during lowering.
- restrictProjections(std::move(sortedProjections), rightChild);
- nodeCEMap.emplace(rightChild.cast<Node>(), rightCE);
-
- ABT result = make<MergeJoinNode>(ProjectionNameVector{ridProjName},
- ProjectionNameVector{std::move(rightRIDProjName)},
- std::vector<CollationOp>{CollationOp::Ascending},
- std::move(leftChild),
- std::move(rightChild));
- nodeCEMap.emplace(result.cast<Node>(), intersectedCE);
-
- childProps.emplace_back(&result.cast<MergeJoinNode>()->getLeftChild(), leftPhysProps);
+ restrictProjections(std::move(sortedProjections), rightCE, rightChild);
+
+ PhysPlanBuilder result;
+ result.make<MergeJoinNode>(intersectedCE,
+ ProjectionNameVector{ridProjName},
+ ProjectionNameVector{std::move(rightRIDProjName)},
+ std::vector<CollationOp>{CollationOp::Ascending},
+ std::move(leftChild._node),
+ std::move(rightChild._node));
+ result.merge(leftChild);
+ result.merge(rightChild);
+
+ childProps.emplace_back(&result._node.cast<MergeJoinNode>()->getLeftChild(), leftPhysProps);
childProps.emplace_back(rightChildPtr, rightPhysProps);
return result;
@@ -2072,65 +2069,63 @@ ABT lowerRIDIntersectMergeJoin(PrefixId& prefixId,
* index scan and associated parameters. Then we iterate in the recursive case where we re-open the
* inner index scan on every new combination of values we receive from the spool.
*/
-static ABT generateDistinctScan(const std::string& scanDefName,
- const std::string& indexDefName,
- const bool reverse,
- const CEType ce,
- const int spoolId,
- ProjectionNameVector outerProjNames,
- FieldProjectionMap outerFPM,
- CompoundIntervalRequirement outerInterval,
- ProjectionNameVector innerProjNames,
- FieldProjectionMap innerFPM,
- CompoundIntervalRequirement innerInterval,
- NodeCEMap& nodeCEMap) {
+static PhysPlanBuilder generateDistinctScan(const std::string& scanDefName,
+ const std::string& indexDefName,
+ const bool reverse,
+ const CEType ce,
+ const int spoolId,
+ ProjectionNameVector outerProjNames,
+ FieldProjectionMap outerFPM,
+ CompoundIntervalRequirement outerInterval,
+ ProjectionNameVector innerProjNames,
+ FieldProjectionMap innerFPM,
+ CompoundIntervalRequirement innerInterval) {
ProjectionNameSet innerProjNameSet;
for (const auto& projName : innerProjNames) {
innerProjNameSet.insert(projName);
}
- ABT innerIndexScan = make<IndexScanNode>(
- std::move(innerFPM), scanDefName, indexDefName, std::move(innerInterval), reverse);
- nodeCEMap.emplace(innerIndexScan.cast<Node>(), ce);
+ PhysPlanBuilder result;
+ result.make<IndexScanNode>(
+ ce, std::move(innerFPM), scanDefName, indexDefName, std::move(innerInterval), reverse);
// Advance to the next unique key.
- innerIndexScan =
- make<LimitSkipNode>(properties::LimitSkipRequirement{1, 0}, std::move(innerIndexScan));
- nodeCEMap.emplace(innerIndexScan.cast<Node>(), ce);
+ result.make<LimitSkipNode>(ce, properties::LimitSkipRequirement{1, 0}, std::move(result._node));
- ABT spoolCons =
- make<SpoolConsumerNode>(SpoolConsumerType::Stack, spoolId, std::move(innerProjNames));
- nodeCEMap.emplace(spoolCons.cast<Node>(), ce);
+ PhysPlanBuilder spoolCons;
+ spoolCons.make<SpoolConsumerNode>(
+ ce, SpoolConsumerType::Stack, spoolId, std::move(innerProjNames));
- ABT innerCorrelatedJoin = make<NestedLoopJoinNode>(JoinType::Inner,
- std::move(innerProjNameSet),
- Constant::boolean(true),
- std::move(spoolCons),
- std::move(innerIndexScan));
- nodeCEMap.emplace(innerCorrelatedJoin.cast<Node>(), ce);
+ // Inner correlated join.
+ result.make<NestedLoopJoinNode>(ce,
+ JoinType::Inner,
+ std::move(innerProjNameSet),
+ Constant::boolean(true),
+ std::move(spoolCons._node),
+ std::move(result._node));
+ result.merge(spoolCons);
// Outer index scan node.
- ABT outerIndexScan = make<IndexScanNode>(
- std::move(outerFPM), scanDefName, indexDefName, std::move(outerInterval), reverse);
- nodeCEMap.emplace(outerIndexScan.cast<Node>(), ce);
+ PhysPlanBuilder outerIndexScan;
+ outerIndexScan.make<IndexScanNode>(
+ ce, std::move(outerFPM), scanDefName, indexDefName, std::move(outerInterval), reverse);
// Limit to one result to seed the distinct scan.
- outerIndexScan =
- make<LimitSkipNode>(properties::LimitSkipRequirement{1, 0}, std::move(outerIndexScan));
- nodeCEMap.emplace(outerIndexScan.cast<Node>(), ce);
-
- ABT unionNode = make<UnionNode>(
- outerProjNames, makeSeq(std::move(outerIndexScan), std::move(innerCorrelatedJoin)));
- nodeCEMap.emplace(unionNode.cast<Node>(), ce);
-
- ABT spoolProd = make<SpoolProducerNode>(SpoolProducerType::Lazy,
- spoolId,
- std::move(outerProjNames),
- Constant::boolean(true),
- std::move(unionNode));
- nodeCEMap.emplace(spoolProd.cast<Node>(), ce);
-
- return spoolProd;
+ outerIndexScan.make<LimitSkipNode>(
+ ce, properties::LimitSkipRequirement{1, 0}, std::move(outerIndexScan._node));
+
+ result.make<UnionNode>(
+ ce, outerProjNames, makeSeq(std::move(outerIndexScan._node), std::move(result._node)));
+ result.merge(outerIndexScan);
+
+ result.make<SpoolProducerNode>(ce,
+ SpoolProducerType::Lazy,
+ spoolId,
+ std::move(outerProjNames),
+ Constant::boolean(true),
+ std::move(result._node));
+
+ return result;
}
/**
@@ -2207,8 +2202,7 @@ public:
ProjectionNameVector correlatedProjNames,
const std::map<size_t, SelectivityType>& indexPredSelMap,
const CEType currentGroupCE,
- const CEType scanGroupCE,
- NodeCEMap& nodeCEMap)
+ const CEType scanGroupCE)
: _prefixId(prefixId),
_ridProjName(ridProjName),
_scanDefName(scanDefName),
@@ -2220,8 +2214,7 @@ public:
_currentEqPrefix(_eqPrefixes.at(_currentEqPrefixIndex)),
_reverseOrder(reverseOrder),
_indexPredSelMap(indexPredSelMap),
- _scanGroupCE(scanGroupCE),
- _nodeCEMap(nodeCEMap) {
+ _scanGroupCE(scanGroupCE) {
// Collect estimates for predicates satisfied with the current equality prefix.
// TODO: rationalize cardinality estimates: estimate number of unique groups.
CEType indexCE = currentGroupCE;
@@ -2244,7 +2237,7 @@ public:
{indexSel, std::move(indexProjectionMap), std::move(correlatedProjNames)});
};
- ABT transport(const CompoundIntervalReqExpr::Atom& node) {
+ PhysPlanBuilder transport(const CompoundIntervalReqExpr::Atom& node) {
const auto& params = _paramStack.back();
const auto& currentFPM = params._fpm;
const CEType currentCE = _scanGroupCE * params._estimate;
@@ -2262,10 +2255,10 @@ public:
if (_currentEqPrefixIndex + 1 == _eqPrefixes.size()) {
// If this is the last equality prefix, use the input field projection map.
- ABT result = make<IndexScanNode>(
- currentFPM, _scanDefName, _indexDefName, std::move(interval), reverse);
- _nodeCEMap.emplace(result.cast<Node>(), currentCE);
- return result;
+ PhysPlanBuilder builder;
+ builder.make<IndexScanNode>(
+ currentCE, currentFPM, _scanDefName, _indexDefName, std::move(interval), reverse);
+ return builder;
}
FieldProjectionMap nextFPM = currentFPM;
@@ -2330,7 +2323,7 @@ public:
}
// Recursively generate a plan to encode the intervals of the subsequent prefixes.
- ABT nextPrefix = lowerEqPrefixes(_prefixId,
+ auto remaining = lowerEqPrefixes(_prefixId,
_ridProjName,
std::move(nextFPM),
_scanDefName,
@@ -2343,30 +2336,29 @@ public:
currentCorrelatedProjNames,
_indexPredSelMap,
currentCE,
- _scanGroupCE,
- _nodeCEMap);
-
- ABT distinctScan = generateDistinctScan(_scanDefName,
- _indexDefName,
- reverse,
- currentCE,
- _spoolId.getNextId(),
- std::move(outerProjNames),
- std::move(outerFPM),
- std::move(interval),
- std::move(innerProjNames),
- std::move(innerFPM),
- std::move(innerInterval),
- _nodeCEMap);
-
- ABT outerCorrelatedJoin = make<NestedLoopJoinNode>(JoinType::Inner,
- std::move(correlationSet),
- Constant::boolean(true),
- std::move(distinctScan),
- std::move(nextPrefix));
- _nodeCEMap.emplace(outerCorrelatedJoin.cast<Node>(), currentCE);
-
- return outerCorrelatedJoin;
+ _scanGroupCE);
+
+ auto result = generateDistinctScan(_scanDefName,
+ _indexDefName,
+ reverse,
+ currentCE,
+ _spoolId.getNextId(),
+ std::move(outerProjNames),
+ std::move(outerFPM),
+ std::move(interval),
+ std::move(innerProjNames),
+ std::move(innerFPM),
+ std::move(innerInterval));
+
+ result.make<NestedLoopJoinNode>(currentCE,
+ JoinType::Inner,
+ std::move(correlationSet),
+ Constant::boolean(true),
+ std::move(result._node),
+ std::move(remaining._node));
+ result.merge(remaining);
+
+ return result;
}
template <bool isConjunction>
@@ -2420,7 +2412,7 @@ public:
}
template <bool isIntersect>
- ABT implement(ABTVector inputs) {
+ PhysPlanBuilder implement(std::vector<PhysPlanBuilder> inputs) {
auto params = std::move(_paramStack.back());
_paramStack.pop_back();
auto& prevParams = _paramStack.back();
@@ -2459,11 +2451,12 @@ public:
sideSetProjectionName = _prefixId.getNextId("sides");
for (size_t index = 0; index < inputSize; index++) {
- ABT& input = inputs.at(index);
- input = make<EvaluationNode>(
- sideIdProjectionName, Constant::int64(index), std::move(input));
+ PhysPlanBuilder& input = inputs.at(index);
// Not relevant for cost.
- _nodeCEMap.emplace(input.cast<Node>(), CEType{0.0});
+ input.make<EvaluationNode>(CEType{0.0},
+ sideIdProjectionName,
+ Constant::int64(index),
+ std::move(input._node));
}
aggExpressions.emplace_back(
@@ -2471,34 +2464,41 @@ public:
aggProjectionNames.push_back(*sideSetProjectionName);
}
- ABT result = make<UnionNode>(std::move(unionProjectionNames), std::move(inputs));
- _nodeCEMap.emplace(result.cast<Node>(), ce);
+ PhysPlanBuilder result;
+ {
+ ABTVector inputABTs;
+ for (auto& input : inputs) {
+ inputABTs.push_back(std::move(input._node));
+ result.merge(input);
+ }
+ result.make<UnionNode>(ce, std::move(unionProjectionNames), std::move(inputABTs));
+ }
- result = make<GroupByNode>(ProjectionNameVector{_ridProjName},
- std::move(aggProjectionNames),
- std::move(aggExpressions),
- std::move(result));
- _nodeCEMap.emplace(result.cast<Node>(), ce);
+ result.make<GroupByNode>(ce,
+ ProjectionNameVector{_ridProjName},
+ std::move(aggProjectionNames),
+ std::move(aggExpressions),
+ std::move(result._node));
if constexpr (isIntersect) {
- result = make<FilterNode>(
+ result.make<FilterNode>(
+ ce,
make<EvalFilter>(
make<PathCompare>(Operations::Eq, Constant::int64(inputSize)),
make<FunctionCall>("getArraySize",
makeSeq(make<Variable>(*sideSetProjectionName)))),
- std::move(result));
- _nodeCEMap.emplace(result.cast<Node>(), ce);
+ std::move(result._node));
} else if (!outerMap._ridProjection && !outerProjNames.empty()) {
// Prevent rid projection from leaking out if we do not require it, and also auxiliary
// left and right side projections.
- restrictProjections(std::move(outerProjNames), result);
- _nodeCEMap.emplace(result.cast<Node>(), ce);
+ restrictProjections(std::move(outerProjNames), ce, result);
}
return result;
}
- ABT transport(const CompoundIntervalReqExpr::Conjunction& node, ABTVector childResults) {
+ PhysPlanBuilder transport(const CompoundIntervalReqExpr::Conjunction& node,
+ std::vector<PhysPlanBuilder> childResults) {
return implement<true /*isIntersect*/>(std::move(childResults));
}
@@ -2506,11 +2506,12 @@ public:
prepare<false /*isConjunction*/>(node.nodes().size());
}
- ABT transport(const CompoundIntervalReqExpr::Disjunction& node, ABTVector childResults) {
+ PhysPlanBuilder transport(const CompoundIntervalReqExpr::Disjunction& node,
+ std::vector<PhysPlanBuilder> childResults) {
return implement<false /*isIntersect*/>(std::move(childResults));
}
- ABT lower(const CompoundIntervalReqExpr::Node& intervals) {
+ PhysPlanBuilder lower(const CompoundIntervalReqExpr::Node& intervals) {
return algebra::transport<false>(intervals, *this);
}
@@ -2530,7 +2531,6 @@ private:
const std::map<size_t, SelectivityType>& _indexPredSelMap;
const CEType _scanGroupCE;
- NodeCEMap& _nodeCEMap;
// Stack which is used to support carrying and updating parameters across Conjunction and
// Disjunction nodes.
@@ -2542,21 +2542,20 @@ private:
std::vector<StackEntry> _paramStack;
};
-ABT lowerEqPrefixes(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- FieldProjectionMap indexProjectionMap,
- const std::string& scanDefName,
- const std::string& indexDefName,
- SpoolId& spoolId,
- const size_t indexFieldCount,
- const std::vector<EqualityPrefixEntry>& eqPrefixes,
- const size_t eqPrefixIndex,
- const std::vector<bool>& reverseOrder,
- ProjectionNameVector correlatedProjNames,
- const std::map<size_t, SelectivityType>& indexPredSelMap,
- const CEType indexCE,
- const CEType scanGroupCE,
- NodeCEMap& nodeCEMap) {
+PhysPlanBuilder lowerEqPrefixes(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ FieldProjectionMap indexProjectionMap,
+ const std::string& scanDefName,
+ const std::string& indexDefName,
+ SpoolId& spoolId,
+ const size_t indexFieldCount,
+ const std::vector<EqualityPrefixEntry>& eqPrefixes,
+ const size_t eqPrefixIndex,
+ const std::vector<bool>& reverseOrder,
+ ProjectionNameVector correlatedProjNames,
+ const std::map<size_t, SelectivityType>& indexPredSelMap,
+ const CEType indexCE,
+ const CEType scanGroupCE) {
IntervalLowerTransport lowerTransport(prefixId,
ridProjName,
std::move(indexProjectionMap),
@@ -2570,8 +2569,7 @@ ABT lowerEqPrefixes(PrefixId& prefixId,
correlatedProjNames,
indexPredSelMap,
indexCE,
- scanGroupCE,
- nodeCEMap);
+ scanGroupCE);
return lowerTransport.lower(eqPrefixes.at(eqPrefixIndex)._interval);
}
diff --git a/src/mongo/db/query/optimizer/utils/utils.h b/src/mongo/db/query/optimizer/utils/utils.h
index 853d71a415f..a9c84b2d74b 100644
--- a/src/mongo/db/query/optimizer/utils/utils.h
+++ b/src/mongo/db/query/optimizer/utils/utils.h
@@ -33,6 +33,8 @@
#include "mongo/db/query/optimizer/node.h"
#include "mongo/db/query/optimizer/node_defs.h"
#include "mongo/db/query/optimizer/props.h"
+#include "mongo/db/query/optimizer/utils/physical_plan_builder.h"
+
namespace mongo::optimizer {
@@ -246,7 +248,7 @@ ProjectionNameSet extractReferencedColumns(const properties::PhysProps& properti
// Use a union node to restrict the set of projections we expose up the tree. The union node is
// optimized away during lowering.
-void restrictProjections(ProjectionNameVector projNames, ABT& input);
+void restrictProjections(ProjectionNameVector projNames, CEType ce, PhysPlanBuilder& input);
struct CollationSplitResult {
bool _validSplit = false;
@@ -440,17 +442,15 @@ bool checkMaybeHasNull(const IntervalReqExpr::Node& intervals, const ConstFoldFn
*/
void lowerPartialSchemaRequirement(const PartialSchemaKey& key,
const PartialSchemaRequirement& req,
- ABT& node,
const PathToIntervalFn& pathToInterval,
- const std::function<void(const ABT& node)>& visitor =
- [](const ABT&) {});
+ boost::optional<CEType> residualCE,
+ PhysPlanBuilder& builder);
void lowerPartialSchemaRequirements(CEType scanGroupCE,
std::vector<SelectivityType> indexPredSels,
ResidualRequirementsWithCE& requirements,
- ABT& physNode,
const PathToIntervalFn& pathToInterval,
- NodeCEMap& nodeCEMap);
+ PhysPlanBuilder& builder);
void sortResidualRequirements(ResidualRequirementsWithCE& residualReq);
@@ -466,45 +466,42 @@ void removeRedundantResidualPredicates(const ProjectionNameOrderPreservingSet& r
/**
* Implements an RID Intersect node using Union and GroupBy.
*/
-ABT lowerRIDIntersectGroupBy(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- CEType intersectedCE,
- CEType leftCE,
- CEType rightCE,
- const properties::PhysProps& physProps,
- const properties::PhysProps& leftPhysProps,
- const properties::PhysProps& rightPhysProps,
- ABT leftChild,
- ABT rightChild,
- NodeCEMap& nodeCEMap,
- ChildPropsType& childProps);
+PhysPlanBuilder lowerRIDIntersectGroupBy(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ CEType intersectedCE,
+ CEType leftCE,
+ CEType rightCE,
+ const properties::PhysProps& physProps,
+ const properties::PhysProps& leftPhysProps,
+ const properties::PhysProps& rightPhysProps,
+ PhysPlanBuilder leftChild,
+ PhysPlanBuilder rightChild,
+ ChildPropsType& childProps);
/**
* Implements an RID Intersect node using a HashJoin.
*/
-ABT lowerRIDIntersectHashJoin(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- CEType intersectedCE,
- CEType leftCE,
- CEType rightCE,
- const properties::PhysProps& leftPhysProps,
- const properties::PhysProps& rightPhysProps,
- ABT leftChild,
- ABT rightChild,
- NodeCEMap& nodeCEMap,
- ChildPropsType& childProps);
-
-ABT lowerRIDIntersectMergeJoin(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- CEType intersectedCE,
- CEType leftCE,
- CEType rightCE,
- const properties::PhysProps& leftPhysProps,
- const properties::PhysProps& rightPhysProps,
- ABT leftChild,
- ABT rightChild,
- NodeCEMap& nodeCEMap,
- ChildPropsType& childProps);
+PhysPlanBuilder lowerRIDIntersectHashJoin(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ CEType intersectedCE,
+ CEType leftCE,
+ CEType rightCE,
+ const properties::PhysProps& leftPhysProps,
+ const properties::PhysProps& rightPhysProps,
+ PhysPlanBuilder leftChild,
+ PhysPlanBuilder rightChild,
+ ChildPropsType& childProps);
+
+PhysPlanBuilder lowerRIDIntersectMergeJoin(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ CEType intersectedCE,
+ CEType leftCE,
+ CEType rightCE,
+ const properties::PhysProps& leftPhysProps,
+ const properties::PhysProps& rightPhysProps,
+ PhysPlanBuilder leftChild,
+ PhysPlanBuilder rightChild,
+ ChildPropsType& childProps);
/**
* Lowers a plan consisting of one or several equality prefixes. The sub-plans for each equality
@@ -512,21 +509,20 @@ ABT lowerRIDIntersectMergeJoin(PrefixId& prefixId,
* implemented as one or more index scans which are unioned or intersected depending on the shape of
* the interval expression (e.g. conjunction or disjunction).
*/
-ABT lowerEqPrefixes(PrefixId& prefixId,
- const ProjectionName& ridProjName,
- FieldProjectionMap indexProjectionMap,
- const std::string& scanDefName,
- const std::string& indexDefName,
- SpoolId& spoolId,
- size_t indexFieldCount,
- const std::vector<EqualityPrefixEntry>& eqPrefixes,
- size_t eqPrefixIndex,
- const std::vector<bool>& reverseOrder,
- ProjectionNameVector correlatedProjNames,
- const std::map<size_t, SelectivityType>& indexPredSelMap,
- CEType indexCE,
- CEType scanGroupCE,
- NodeCEMap& nodeCEMap);
+PhysPlanBuilder lowerEqPrefixes(PrefixId& prefixId,
+ const ProjectionName& ridProjName,
+ FieldProjectionMap indexProjectionMap,
+ const std::string& scanDefName,
+ const std::string& indexDefName,
+ SpoolId& spoolId,
+ size_t indexFieldCount,
+ const std::vector<EqualityPrefixEntry>& eqPrefixes,
+ size_t eqPrefixIndex,
+ const std::vector<bool>& reverseOrder,
+ ProjectionNameVector correlatedProjNames,
+ const std::map<size_t, SelectivityType>& indexPredSelMap,
+ CEType indexCE,
+ CEType scanGroupCE);
/**
* This helper checks to see if we have a PathTraverse + PathId at the end of the path.