summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMatt Boros <matt.boros@mongodb.com>2022-10-31 20:56:19 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-10-31 22:17:01 +0000
commit201497d405225041f1806d25dfed475f3ec3f7ae (patch)
tree9338ef7e07b24fdac88784e777f1d86848eeedf9 /src
parent54aa1224e35847da94648f1e9f520af6c1606b99 (diff)
downloadmongo-201497d405225041f1806d25dfed475f3ec3f7ae.tar.gz
SERVER-70696 Determine presence of left and right intervals as a logical property
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/query/optimizer/cascades/implementers.cpp34
-rw-r--r--src/mongo/db/query/optimizer/cascades/logical_props_derivation.cpp5
-rw-r--r--src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp42
-rw-r--r--src/mongo/db/query/optimizer/explain.cpp3
-rw-r--r--src/mongo/db/query/optimizer/logical_rewriter_optimizer_test.cpp6
-rw-r--r--src/mongo/db/query/optimizer/node.cpp22
-rw-r--r--src/mongo/db/query/optimizer/node.h13
-rw-r--r--src/mongo/db/query/optimizer/physical_rewriter_optimizer_test.cpp18
-rw-r--r--src/mongo/db/query/optimizer/props.cpp15
-rw-r--r--src/mongo/db/query/optimizer/props.h7
-rw-r--r--src/mongo/db/query/optimizer/utils/abt_hash.cpp2
-rw-r--r--src/mongo/db/query/optimizer/utils/utils.cpp11
-rw-r--r--src/mongo/db/query/optimizer/utils/utils.h1
13 files changed, 95 insertions, 84 deletions
diff --git a/src/mongo/db/query/optimizer/cascades/implementers.cpp b/src/mongo/db/query/optimizer/cascades/implementers.cpp
index 6039ac3cb43..835045a2611 100644
--- a/src/mongo/db/query/optimizer/cascades/implementers.cpp
+++ b/src/mongo/db/query/optimizer/cascades/implementers.cpp
@@ -189,8 +189,7 @@ public:
if (node.getArraySize() == 0) {
nodeCEMap.emplace(physNode.cast<Node>(), 0.0);
- physNode =
- make<LimitSkipNode>(properties::LimitSkipRequirement{0, 0}, std::move(physNode));
+ physNode = make<LimitSkipNode>(LimitSkipRequirement{0, 0}, std::move(physNode));
nodeCEMap.emplace(physNode.cast<Node>(), 0.0);
for (const ProjectionName& boundProjName : node.binder().names()) {
@@ -208,8 +207,7 @@ public:
} else {
nodeCEMap.emplace(physNode.cast<Node>(), 1.0);
- physNode =
- make<LimitSkipNode>(properties::LimitSkipRequirement{1, 0}, std::move(physNode));
+ physNode = make<LimitSkipNode>(LimitSkipRequirement{1, 0}, std::move(physNode));
nodeCEMap.emplace(physNode.cast<Node>(), 1.0);
const ProjectionName valueScanProj = _prefixId.getNextId("valueScan");
@@ -710,7 +708,21 @@ public:
return;
}
const bool isIndex = indexReqTarget == IndexReqTarget::Index;
- if (isIndex && (!node.hasLeftIntervals() || !node.hasRightIntervals())) {
+
+ const GroupIdType leftGroupId =
+ node.getLeftChild().cast<MemoLogicalDelegatorNode>()->getGroupId();
+ const GroupIdType rightGroupId =
+ node.getRightChild().cast<MemoLogicalDelegatorNode>()->getGroupId();
+
+ const LogicalProps& leftLogicalProps = _memo.getLogicalProps(leftGroupId);
+ const LogicalProps& rightLogicalProps = _memo.getLogicalProps(rightGroupId);
+
+ const bool hasProperIntervalLeft =
+ getPropertyConst<IndexingAvailability>(leftLogicalProps).hasProperInterval();
+ const bool hasProperIntervalRight =
+ getPropertyConst<IndexingAvailability>(rightLogicalProps).hasProperInterval();
+
+ if (isIndex && (!hasProperIntervalLeft || !hasProperIntervalRight)) {
// We need to have proper intervals on both sides.
return;
}
@@ -729,14 +741,6 @@ public:
}
}
- const GroupIdType leftGroupId =
- node.getLeftChild().cast<MemoLogicalDelegatorNode>()->getGroupId();
- const GroupIdType rightGroupId =
- node.getRightChild().cast<MemoLogicalDelegatorNode>()->getGroupId();
-
- const LogicalProps& leftLogicalProps = _memo.getLogicalProps(leftGroupId);
- const LogicalProps& rightLogicalProps = _memo.getLogicalProps(rightGroupId);
-
const CEType intersectedCE =
getPropertyConst<CardinalityEstimate>(_logicalProps).getEstimate();
const CEType leftCE = getPropertyConst<CardinalityEstimate>(leftLogicalProps).getEstimate();
@@ -1660,9 +1664,9 @@ void addImplementers(const Metadata& metadata,
const QueryHints& hints,
const RIDProjectionsMap& ridProjections,
PrefixId& prefixId,
- const properties::PhysProps& physProps,
+ const PhysProps& physProps,
PhysQueueAndImplPos& queue,
- const properties::LogicalProps& logicalProps,
+ const LogicalProps& logicalProps,
const OrderPreservingABTSet& logicalNodes,
const PathToIntervalFn& pathToInterval) {
ImplementationVisitor visitor(metadata,
diff --git a/src/mongo/db/query/optimizer/cascades/logical_props_derivation.cpp b/src/mongo/db/query/optimizer/cascades/logical_props_derivation.cpp
index c2ef5529e79..29d4ccc22ec 100644
--- a/src/mongo/db/query/optimizer/cascades/logical_props_derivation.cpp
+++ b/src/mongo/db/query/optimizer/cascades/logical_props_derivation.cpp
@@ -222,8 +222,7 @@ public:
indexingAvailability.setEqPredsOnly(computeEqPredsOnly(node.getReqMap()));
}
- auto& satisfiedPartialIndexes =
- getProperty<IndexingAvailability>(result).getSatisfiedPartialIndexes();
+ auto& satisfiedPartialIndexes = indexingAvailability.getSatisfiedPartialIndexes();
for (const auto& [indexDefName, indexDef] : scanDef.getIndexDefs()) {
if (!indexDef.getPartialReqMap().empty()) {
auto intersection = node.getReqMap();
@@ -237,6 +236,8 @@ public:
}
}
+ indexingAvailability.setHasProperInterval(hasProperIntervals(node.getReqMap()));
+
return maybeUpdateNodePropsMap(node, std::move(result));
}
diff --git a/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp b/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
index 421d03f73a1..0c9a923b2ed 100644
--- a/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
+++ b/src/mongo/db/query/optimizer/cascades/logical_rewriter.cpp
@@ -941,8 +941,6 @@ struct SplitRequirementsResult {
PartialSchemaRequirements _rightReqs;
bool _hasFieldCoverage = true;
- bool _hasLeftIntervals = false;
- bool _hasRightIntervals = false;
};
/**
@@ -981,7 +979,6 @@ static SplitRequirementsResult splitRequirements(
size_t index = 0;
for (const auto& [key, req] : reqMap) {
- const bool fullyOpenInterval = isFullyOpen.at(index);
if (((1ull << index) & mask) != 0) {
bool addedToLeft = false;
@@ -1005,7 +1002,7 @@ static SplitRequirementsResult splitRequirements(
// We cannot return index values if our interval can possibly contain Null. Instead,
// we remove the output binding for the left side, and return the value from the
// right (seek) side.
- if (!fullyOpenInterval) {
+ if (!isFullyOpen.at(index)) {
addRequirement(
leftReqs, key, boost::none /*boundProjectionName*/, req.getIntervals());
addedToLeft = true;
@@ -1018,9 +1015,6 @@ static SplitRequirementsResult splitRequirements(
}
if (addedToLeft) {
- if (!fullyOpenInterval) {
- result._hasLeftIntervals = true;
- }
if (indexFieldPrefixMapForScanDef) {
if (auto pathPtr = key._path.cast<PathGet>(); pathPtr != nullptr &&
indexFieldPrefixMapForScanDef->count(pathPtr->name()) == 0) {
@@ -1033,9 +1027,6 @@ static SplitRequirementsResult splitRequirements(
}
} else if (isIndex || !req.getIsPerfOnly()) {
addRequirement(rightReqs, key, req.getBoundProjectionName(), req.getIntervals());
- if (!fullyOpenInterval) {
- result._hasRightIntervals = true;
- }
}
index++;
}
@@ -1141,10 +1132,13 @@ struct ExploreConvert<SargableNode> {
continue;
}
- if (isIndex && (!splitResult._hasLeftIntervals || !splitResult._hasRightIntervals)) {
- // Reject. Must have at least one proper interval on either side.
+ // Reject. Must have at least one proper interval on either side.
+ if (isIndex &&
+ (!hasProperIntervals(splitResult._leftReqs) ||
+ !hasProperIntervals(splitResult._rightReqs))) {
continue;
}
+
if (!splitResult._hasFieldCoverage) {
// Reject rewrite. No suitable indexes.
continue;
@@ -1196,11 +1190,8 @@ struct ExploreConvert<SargableNode> {
isIndex ? IndexReqTarget::Index : IndexReqTarget::Seek,
scanDelegator);
- ABT newRoot = make<RIDIntersectNode>(scanProjectionName,
- splitResult._hasLeftIntervals,
- splitResult._hasRightIntervals,
- std::move(leftChild),
- std::move(rightChild));
+ ABT newRoot = make<RIDIntersectNode>(
+ scanProjectionName, std::move(leftChild), std::move(rightChild));
const auto& result = ctx.addNode(newRoot, false /*substitute*/);
for (const MemoLogicalNodeId nodeId : result.second) {
@@ -1290,14 +1281,27 @@ void reorderAgainstRIDIntersectNode(ABT::reference_type aboveNode,
}
const RIDIntersectNode& node = *belowNode.cast<RIDIntersectNode>();
- if (node.hasLeftIntervals() && hasLeftRef) {
+ const GroupIdType groupIdLeft =
+ node.getLeftChild().cast<MemoLogicalDelegatorNode>()->getGroupId();
+ const bool hasProperIntervalLeft =
+ properties::getPropertyConst<properties::IndexingAvailability>(
+ ctx.getMemo().getLogicalProps(groupIdLeft))
+ .hasProperInterval();
+ if (hasProperIntervalLeft && hasLeftRef) {
defaultReorder<AboveNode,
RIDIntersectNode,
DefaultChildAccessor,
LeftChildAccessor,
false /*substitute*/>(aboveNode, belowNode, ctx);
}
- if (node.hasRightIntervals() && hasRightRef) {
+
+ const GroupIdType groupIdRight =
+ node.getRightChild().cast<MemoLogicalDelegatorNode>()->getGroupId();
+ const bool hasProperIntervalRight =
+ properties::getPropertyConst<properties::IndexingAvailability>(
+ ctx.getMemo().getLogicalProps(groupIdRight))
+ .hasProperInterval();
+ if (hasProperIntervalRight && hasRightRef) {
defaultReorder<AboveNode,
RIDIntersectNode,
DefaultChildAccessor,
diff --git a/src/mongo/db/query/optimizer/explain.cpp b/src/mongo/db/query/optimizer/explain.cpp
index 5c49f3ad74f..b1bb27568d5 100644
--- a/src/mongo/db/query/optimizer/explain.cpp
+++ b/src/mongo/db/query/optimizer/explain.cpp
@@ -1277,8 +1277,6 @@ public:
printer.separator(" [")
.fieldName("scanProjectionName", ExplainVersion::V3)
.print(node.getScanProjectionName());
- printBooleanFlag(printer, "hasLeftIntervals", node.hasLeftIntervals());
- printBooleanFlag(printer, "hasRightIntervals", node.hasRightIntervals());
printer.separator("]");
nodeCEPropsPrint(printer, n, node);
@@ -1767,6 +1765,7 @@ public:
.fieldName("scanDefName")
.print(prop.getScanDefName());
printBooleanFlag(printer, "eqPredsOnly", prop.getEqPredsOnly());
+ printBooleanFlag(printer, "hasProperInterval", prop.hasProperInterval());
printer.separator("]");
if (!prop.getSatisfiedPartialIndexes().empty()) {
diff --git a/src/mongo/db/query/optimizer/logical_rewriter_optimizer_test.cpp b/src/mongo/db/query/optimizer/logical_rewriter_optimizer_test.cpp
index 056a048658b..03980eb5db4 100644
--- a/src/mongo/db/query/optimizer/logical_rewriter_optimizer_test.cpp
+++ b/src/mongo/db/query/optimizer/logical_rewriter_optimizer_test.cpp
@@ -1476,7 +1476,8 @@ TEST(LogicalRewriter, SargableCE) {
" | | projections: \n"
" | | ptest\n"
" | | indexingAvailability: \n"
- " | | [groupId: 0, scanProjection: ptest, scanDefName: test, eqPredsOnly]\n"
+ " | | [groupId: 0, scanProjection: ptest, scanDefName: test, eqPredsOnly, "
+ "hasProperInterval]\n"
" | | collectionAvailability: \n"
" | | test\n"
" | | distributionAvailability: \n"
@@ -1510,7 +1511,8 @@ TEST(LogicalRewriter, SargableCE) {
" | | projections: \n"
" | | ptest\n"
" | | indexingAvailability: \n"
- " | | [groupId: 0, scanProjection: ptest, scanDefName: test, eqPredsOnly]\n"
+ " | | [groupId: 0, scanProjection: ptest, scanDefName: test, eqPredsOnly, "
+ "hasProperInterval]\n"
" | | collectionAvailability: \n"
" | | test\n"
" | | distributionAvailability: \n"
diff --git a/src/mongo/db/query/optimizer/node.cpp b/src/mongo/db/query/optimizer/node.cpp
index d9b0086fb1e..1eed39980b1 100644
--- a/src/mongo/db/query/optimizer/node.cpp
+++ b/src/mongo/db/query/optimizer/node.cpp
@@ -290,15 +290,9 @@ bool EvaluationNode::operator==(const EvaluationNode& other) const {
getChild() == other.getChild();
}
-RIDIntersectNode::RIDIntersectNode(ProjectionName scanProjectionName,
- const bool hasLeftIntervals,
- const bool hasRightIntervals,
- ABT leftChild,
- ABT rightChild)
+RIDIntersectNode::RIDIntersectNode(ProjectionName scanProjectionName, ABT leftChild, ABT rightChild)
: Base(std::move(leftChild), std::move(rightChild)),
- _scanProjectionName(std::move(scanProjectionName)),
- _hasLeftIntervals(hasLeftIntervals),
- _hasRightIntervals(hasRightIntervals) {
+ _scanProjectionName(std::move(scanProjectionName)) {
assertNodeSort(getLeftChild());
assertNodeSort(getRightChild());
}
@@ -321,23 +315,13 @@ ABT& RIDIntersectNode::getRightChild() {
bool RIDIntersectNode::operator==(const RIDIntersectNode& other) const {
return _scanProjectionName == other._scanProjectionName &&
- _hasLeftIntervals == other._hasLeftIntervals &&
- _hasRightIntervals == other._hasRightIntervals && getLeftChild() == other.getLeftChild() &&
- getRightChild() == other.getRightChild();
+ getLeftChild() == other.getLeftChild() && getRightChild() == other.getRightChild();
}
const ProjectionName& RIDIntersectNode::getScanProjectionName() const {
return _scanProjectionName;
}
-bool RIDIntersectNode::hasLeftIntervals() const {
- return _hasLeftIntervals;
-}
-
-bool RIDIntersectNode::hasRightIntervals() const {
- return _hasRightIntervals;
-}
-
static ProjectionNameVector createSargableBindings(const PartialSchemaRequirements& reqMap) {
ProjectionNameVector result;
for (const auto& entry : reqMap) {
diff --git a/src/mongo/db/query/optimizer/node.h b/src/mongo/db/query/optimizer/node.h
index 155f1d69f29..880d2fd5480 100644
--- a/src/mongo/db/query/optimizer/node.h
+++ b/src/mongo/db/query/optimizer/node.h
@@ -389,11 +389,7 @@ class RIDIntersectNode final : public Operator<2>, public ExclusivelyLogicalNode
using Base = Operator<2>;
public:
- RIDIntersectNode(ProjectionName scanProjectionName,
- bool hasLeftIntervals,
- bool hasRightIntervals,
- ABT leftChild,
- ABT rightChild);
+ RIDIntersectNode(ProjectionName scanProjectionName, ABT leftChild, ABT rightChild);
bool operator==(const RIDIntersectNode& other) const;
@@ -405,15 +401,8 @@ public:
const ProjectionName& getScanProjectionName() const;
- bool hasLeftIntervals() const;
- bool hasRightIntervals() const;
-
private:
const ProjectionName _scanProjectionName;
-
- // If true left and right children have at least one proper interval (not fully open).
- const bool _hasLeftIntervals;
- const bool _hasRightIntervals;
};
/**
diff --git a/src/mongo/db/query/optimizer/physical_rewriter_optimizer_test.cpp b/src/mongo/db/query/optimizer/physical_rewriter_optimizer_test.cpp
index 0d21c897dd8..789bcdeea81 100644
--- a/src/mongo/db/query/optimizer/physical_rewriter_optimizer_test.cpp
+++ b/src/mongo/db/query/optimizer/physical_rewriter_optimizer_test.cpp
@@ -120,7 +120,7 @@ TEST(PhysRewriter, PhysicalRewriterBasic) {
"| | p1\n"
"| | p2\n"
"| | indexingAvailability: \n"
- "| | [groupId: 0, scanProjection: p1, scanDefName: test]\n"
+ "| | [groupId: 0, scanProjection: p1, scanDefName: test, hasProperInterval]\n"
"| | collectionAvailability: \n"
"| | test\n"
"| | distributionAvailability: \n"
@@ -146,7 +146,7 @@ TEST(PhysRewriter, PhysicalRewriterBasic) {
"| | p1\n"
"| | p2\n"
"| | indexingAvailability: \n"
- "| | [groupId: 0, scanProjection: p1, scanDefName: test]\n"
+ "| | [groupId: 0, scanProjection: p1, scanDefName: test, hasProperInterval]\n"
"| | collectionAvailability: \n"
"| | test\n"
"| | distributionAvailability: \n"
@@ -738,7 +738,7 @@ TEST(PhysRewriter, FilterIndexing) {
"| | root\n"
"| RefBlock: \n"
"| Variable [root]\n"
- "RIDIntersect [root, hasLeftIntervals]\n"
+ "RIDIntersect [root]\n"
"| Scan [c1]\n"
"| BindBlock:\n"
"| [root]\n"
@@ -3212,7 +3212,7 @@ TEST(PhysRewriter, IndexResidualReq) {
"| | pa\n"
"| | root\n"
"| | indexingAvailability: \n"
- "| | [groupId: 0, scanProjection: root, scanDefName: c1]\n"
+ "| | [groupId: 0, scanProjection: root, scanDefName: c1, hasProperInterval]\n"
"| | collectionAvailability: \n"
"| | c1\n"
"| | distributionAvailability: \n"
@@ -3240,7 +3240,7 @@ TEST(PhysRewriter, IndexResidualReq) {
"| | pa\n"
"| | root\n"
"| | indexingAvailability: \n"
- "| | [groupId: 0, scanProjection: root, scanDefName: c1]\n"
+ "| | [groupId: 0, scanProjection: root, scanDefName: c1, hasProperInterval]\n"
"| | collectionAvailability: \n"
"| | c1\n"
"| | distributionAvailability: \n"
@@ -5930,7 +5930,7 @@ TEST(PhysRewriter, PerfOnlyPreds2) {
ABT optimized = rootNode;
phaseManager.getHints()._disableYieldingTolerantPlans = false;
phaseManager.optimize(optimized);
- ASSERT_BETWEEN(10, 15, phaseManager.getMemo().getStats()._physPlanExplorationCount);
+ ASSERT_BETWEEN(10, 17, phaseManager.getMemo().getStats()._physPlanExplorationCount);
// Demonstrate an intersection plan, with predicates repeated on the Seek side.
ASSERT_EXPLAIN_V2Compact(
@@ -5963,16 +5963,16 @@ TEST(PhysRewriter, PerfOnlyPreds2) {
"| Variable [rid_0]\n"
"MergeJoin []\n"
"| | | Condition\n"
- "| | | rid_0 = rid_3\n"
+ "| | | rid_0 = rid_5\n"
"| | Collation\n"
"| | Ascending\n"
"| Union []\n"
"| | BindBlock:\n"
- "| | [rid_3]\n"
+ "| | [rid_5]\n"
"| | Source []\n"
"| Evaluation []\n"
"| | BindBlock:\n"
- "| | [rid_3]\n"
+ "| | [rid_5]\n"
"| | Variable [rid_0]\n"
"| IndexScan [{'<rid>': rid_0}, scanDefName: c1, indexDefName: index2, interval: {[Const "
"[2], Const [2]]}]\n"
diff --git a/src/mongo/db/query/optimizer/props.cpp b/src/mongo/db/query/optimizer/props.cpp
index 854882292be..c0079a78ed2 100644
--- a/src/mongo/db/query/optimizer/props.cpp
+++ b/src/mongo/db/query/optimizer/props.cpp
@@ -282,17 +282,20 @@ IndexingAvailability::IndexingAvailability(GroupIdType scanGroupId,
ProjectionName scanProjection,
std::string scanDefName,
const bool eqPredsOnly,
+ const bool hasProperInterval,
opt::unordered_set<std::string> satisfiedPartialIndexes)
: _scanGroupId(scanGroupId),
_scanProjection(std::move(scanProjection)),
_scanDefName(std::move(scanDefName)),
_eqPredsOnly(eqPredsOnly),
- _satisfiedPartialIndexes(std::move(satisfiedPartialIndexes)) {}
+ _satisfiedPartialIndexes(std::move(satisfiedPartialIndexes)),
+ _hasProperInterval(hasProperInterval) {}
bool IndexingAvailability::operator==(const IndexingAvailability& other) const {
return _scanGroupId == other._scanGroupId && _scanProjection == other._scanProjection &&
_scanDefName == other._scanDefName && _eqPredsOnly == other._eqPredsOnly &&
- _satisfiedPartialIndexes == other._satisfiedPartialIndexes;
+ _satisfiedPartialIndexes == other._satisfiedPartialIndexes &&
+ _hasProperInterval == other._hasProperInterval;
}
GroupIdType IndexingAvailability::getScanGroupId() const {
@@ -327,6 +330,14 @@ void IndexingAvailability::setEqPredsOnly(const bool value) {
_eqPredsOnly = value;
}
+bool IndexingAvailability::hasProperInterval() const {
+ return _hasProperInterval;
+}
+
+void IndexingAvailability::setHasProperInterval(const bool hasProperInterval) {
+ _hasProperInterval = hasProperInterval;
+}
+
CollectionAvailability::CollectionAvailability(opt::unordered_set<std::string> scanDefSet)
: _scanDefSet(std::move(scanDefSet)) {}
diff --git a/src/mongo/db/query/optimizer/props.h b/src/mongo/db/query/optimizer/props.h
index adfb0f82847..e7ac16f227d 100644
--- a/src/mongo/db/query/optimizer/props.h
+++ b/src/mongo/db/query/optimizer/props.h
@@ -399,6 +399,7 @@ public:
ProjectionName scanProjection,
std::string scanDefName,
bool eqPredsOnly,
+ bool hasProperInterval,
opt::unordered_set<std::string> satisfiedPartialIndexes);
bool operator==(const IndexingAvailability& other) const;
@@ -415,6 +416,9 @@ public:
bool getEqPredsOnly() const;
void setEqPredsOnly(bool value);
+ bool hasProperInterval() const;
+ void setHasProperInterval(bool hasProperInterval);
+
private:
GroupIdType _scanGroupId;
const ProjectionName _scanProjection;
@@ -427,6 +431,9 @@ private:
// Set of indexes with partial indexes whose partial filters are satisfied for the current
// group.
opt::unordered_set<std::string> _satisfiedPartialIndexes;
+
+ // True if there is at least one proper interval in a sargable node in this group.
+ bool _hasProperInterval;
};
diff --git a/src/mongo/db/query/optimizer/utils/abt_hash.cpp b/src/mongo/db/query/optimizer/utils/abt_hash.cpp
index 90585939882..b9f8d5a2517 100644
--- a/src/mongo/db/query/optimizer/utils/abt_hash.cpp
+++ b/src/mongo/db/query/optimizer/utils/abt_hash.cpp
@@ -195,8 +195,6 @@ public:
size_t rightChildResult) {
// Specifically always including children.
return computeHashSeq<45>(std::hash<ProjectionName>()(node.getScanProjectionName()),
- std::hash<bool>()(node.hasLeftIntervals()),
- std::hash<bool>()(node.hasRightIntervals()),
leftChildResult,
rightChildResult);
}
diff --git a/src/mongo/db/query/optimizer/utils/utils.cpp b/src/mongo/db/query/optimizer/utils/utils.cpp
index 6c2dac94c96..a676e28179b 100644
--- a/src/mongo/db/query/optimizer/utils/utils.cpp
+++ b/src/mongo/db/query/optimizer/utils/utils.cpp
@@ -102,6 +102,7 @@ properties::LogicalProps createInitialScanProps(const ProjectionName& projection
projectionName,
scanDefName,
true /*eqPredsOnly*/,
+ false /*hasProperInterval*/,
{} /*satisfiedPartialIndexes*/),
properties::CollectionAvailability({scanDefName}),
properties::DistributionAvailability(std::move(distributions)));
@@ -1928,4 +1929,14 @@ bool pathEndsInTraverse(const optimizer::ABT& path) {
return optimizer::algebra::transport<false>(path, t);
}
+bool hasProperIntervals(const PartialSchemaRequirements& reqMap) {
+ // Compute if this node has any proper (not fully open) intervals.
+ for (const auto& [key, req] : reqMap) {
+ if (!isIntervalReqFullyOpenDNF(req.getIntervals())) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace mongo::optimizer
diff --git a/src/mongo/db/query/optimizer/utils/utils.h b/src/mongo/db/query/optimizer/utils/utils.h
index e4a2b2367a6..48589995a14 100644
--- a/src/mongo/db/query/optimizer/utils/utils.h
+++ b/src/mongo/db/query/optimizer/utils/utils.h
@@ -347,4 +347,5 @@ ABT lowerIntervals(PrefixId& prefixId,
*/
bool pathEndsInTraverse(const optimizer::ABT& path);
+bool hasProperIntervals(const PartialSchemaRequirements& reqMap);
} // namespace mongo::optimizer