summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/db/matcher/expression_visitor.h143
-rw-r--r--src/mongo/db/query/bind_input_params.cpp84
-rw-r--r--src/mongo/db/query/bind_input_params.h11
-rw-r--r--src/mongo/db/query/sbe_stage_builder.cpp89
-rw-r--r--src/mongo/db/query/sbe_utils.cpp210
-rw-r--r--src/mongo/db/query/sbe_utils.h13
6 files changed, 378 insertions, 172 deletions
diff --git a/src/mongo/db/matcher/expression_visitor.h b/src/mongo/db/matcher/expression_visitor.h
index 78ba0ce3df3..f31e604f518 100644
--- a/src/mongo/db/matcher/expression_visitor.h
+++ b/src/mongo/db/matcher/expression_visitor.h
@@ -101,90 +101,67 @@ class WhereNoOpMatchExpression;
template <bool IsConst = false>
class MatchExpressionVisitor {
public:
+ template <typename T>
+ using MaybeConstPtr = tree_walker::MaybeConstPtr<IsConst, T>;
+
virtual ~MatchExpressionVisitor() = default;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, AlwaysFalseMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, AlwaysTrueMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, AndMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, BitsAllClearMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, BitsAllSetMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, BitsAnyClearMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, BitsAnySetMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, ElemMatchObjectMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, ElemMatchValueMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, EqualityMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, ExistsMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, ExprMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, GTEMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, GTMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, GeoMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, GeoNearMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, InMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalBucketGeoWithinMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, InternalExprEqMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, InternalExprGTMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalExprGTEMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, InternalExprLTMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalExprLTEMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaAllElemMatchFromIndexMatchExpression>
- expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaAllowedPropertiesMatchExpression>
- expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaBinDataEncryptedTypeExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaBinDataFLE2EncryptedTypeExpression>
- expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaBinDataSubTypeExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaCondMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaEqMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaFmodMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaMatchArrayIndexMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaMaxItemsMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaMaxLengthMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaMaxPropertiesMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaMinItemsMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaMinLengthMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaMinPropertiesMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaObjectMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaRootDocEqMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, InternalSchemaTypeExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaUniqueItemsMatchExpression> expr) = 0;
- virtual void visit(
- tree_walker::MaybeConstPtr<IsConst, InternalSchemaXorMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, LTEMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, LTMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, ModMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, NorMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, NotMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, OrMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, RegexMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, SizeMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, TextMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, TextNoOpMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, TwoDPtInAnnulusExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, TypeMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, WhereMatchExpression> expr) = 0;
- virtual void visit(tree_walker::MaybeConstPtr<IsConst, WhereNoOpMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<AlwaysFalseMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<AlwaysTrueMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<AndMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<BitsAllClearMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<BitsAllSetMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<BitsAnyClearMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<BitsAnySetMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<ElemMatchObjectMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<ElemMatchValueMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<EqualityMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<ExistsMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<ExprMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<GTEMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<GTMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<GeoMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<GeoNearMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalBucketGeoWithinMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalExprEqMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalExprGTMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalExprGTEMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalExprLTMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalExprLTEMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaAllElemMatchFromIndexMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaAllowedPropertiesMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaBinDataEncryptedTypeExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaBinDataFLE2EncryptedTypeExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaBinDataSubTypeExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaCondMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaEqMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaFmodMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaMatchArrayIndexMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaMaxItemsMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaMaxLengthMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaMaxPropertiesMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaMinItemsMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaMinLengthMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaMinPropertiesMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaObjectMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaRootDocEqMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaTypeExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaUniqueItemsMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<InternalSchemaXorMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<LTEMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<LTMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<ModMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<NorMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<NotMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<OrMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<RegexMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<SizeMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<TextMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<TextNoOpMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<TwoDPtInAnnulusExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<TypeMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<WhereMatchExpression> expr) = 0;
+ virtual void visit(MaybeConstPtr<WhereNoOpMatchExpression> expr) = 0;
};
using MatchExpressionMutableVisitor = MatchExpressionVisitor<false>;
diff --git a/src/mongo/db/query/bind_input_params.cpp b/src/mongo/db/query/bind_input_params.cpp
index c6276a5d60b..d0396fcf723 100644
--- a/src/mongo/db/query/bind_input_params.cpp
+++ b/src/mongo/db/query/bind_input_params.cpp
@@ -33,7 +33,9 @@
#include "mongo/db/exec/sbe/values/value.h"
#include "mongo/db/matcher/expression_array.h"
#include "mongo/db/matcher/expression_where.h"
+#include "mongo/db/query/index_bounds_builder.h"
#include "mongo/db/query/sbe_stage_builder_filter.h"
+#include "mongo/db/query/sbe_stage_builder_index_scan.h"
namespace mongo::input_params {
namespace {
@@ -290,9 +292,6 @@ private:
guard->reset();
}
accessor->reset(owned, typeTag, value);
- } else {
- // TODO SERVER-65361: add tassert here if the slotId is missing from
- // _inputParamToSlotMap but not from IETs.
}
}
@@ -318,6 +317,38 @@ public:
private:
MatchExpressionParameterBindingVisitor* const _visitor;
};
+
+/**
+ * Evaluates IndexBounds from the given IntervalEvaluationTrees for the given query.
+ * 'indexBoundsInfo' contains the interval evaluation trees.
+ *
+ * Returns the built index bounds.
+ */
+std::unique_ptr<IndexBounds> makeIndexBounds(
+ const stage_builder::IndexBoundsEvaluationInfo& indexBoundsInfo, const CanonicalQuery& cq) {
+ auto bounds = std::make_unique<IndexBounds>();
+ bounds->fields.reserve(indexBoundsInfo.iets.size());
+
+ tassert(6335200,
+ "IET list size must be equal to the number of fields in the key pattern",
+ static_cast<size_t>(indexBoundsInfo.index.keyPattern.nFields()) ==
+ indexBoundsInfo.iets.size());
+
+ BSONObjIterator it{indexBoundsInfo.index.keyPattern};
+ BSONElement keyElt = it.next();
+ for (auto&& iet : indexBoundsInfo.iets) {
+ auto oil = interval_evaluation_tree::evaluateIntervals(
+ iet, cq.getInputParamIdToMatchExpressionMap(), keyElt, indexBoundsInfo.index);
+ bounds->fields.emplace_back(std::move(oil));
+ keyElt = it.next();
+ }
+
+ IndexBoundsBuilder::alignBounds(bounds.get(),
+ indexBoundsInfo.index.keyPattern,
+ indexBoundsInfo.index.collator != nullptr,
+ indexBoundsInfo.direction);
+ return bounds;
+}
} // namespace
void bind(const CanonicalQuery& canonicalQuery,
@@ -327,4 +358,51 @@ void bind(const CanonicalQuery& canonicalQuery,
MatchExpressionParameterBindingWalker walker{&visitor};
tree_walker::walk<true, MatchExpression>(canonicalQuery.root(), &walker);
}
+
+void bindIndexBounds(const CanonicalQuery& cq,
+ const stage_builder::IndexBoundsEvaluationInfo& indexBoundsInfo,
+ sbe::RuntimeEnvironment* runtimeEnvironment) {
+ auto bounds = makeIndexBounds(indexBoundsInfo, cq);
+ auto intervals = stage_builder::makeIntervalsFromIndexBounds(*bounds,
+ indexBoundsInfo.direction == 1,
+ indexBoundsInfo.keyStringVersion,
+ indexBoundsInfo.ordering);
+ const bool isGenericScan = intervals.empty();
+ runtimeEnvironment->resetSlot(indexBoundsInfo.slots.isGenericScan,
+ sbe::value::TypeTags::Boolean,
+ sbe::value::bitcastFrom<bool>(isGenericScan),
+ /*owned*/ true);
+ if (isGenericScan) {
+ IndexBoundsChecker checker{
+ bounds.get(), indexBoundsInfo.index.keyPattern, indexBoundsInfo.direction};
+ IndexSeekPoint seekPoint;
+ if (checker.getStartSeekPoint(&seekPoint)) {
+ auto startKey = std::make_unique<KeyString::Value>(
+ IndexEntryComparison::makeKeyStringFromSeekPointForSeek(
+ seekPoint,
+ indexBoundsInfo.keyStringVersion,
+ indexBoundsInfo.ordering,
+ indexBoundsInfo.direction == 1));
+ runtimeEnvironment->resetSlot(
+ indexBoundsInfo.slots.initialStartKey,
+ sbe::value::TypeTags::ksValue,
+ sbe::value::bitcastFrom<KeyString::Value*>(startKey.release()),
+ /*owned*/ true);
+ runtimeEnvironment->resetSlot(indexBoundsInfo.slots.indexBounds,
+ sbe::value::TypeTags::indexBounds,
+ sbe::value::bitcastFrom<IndexBounds*>(bounds.release()),
+ /*owned*/ true);
+ } else {
+ runtimeEnvironment->resetSlot(indexBoundsInfo.slots.initialStartKey,
+ sbe::value::TypeTags::Nothing,
+ 0,
+ /*owned*/ true);
+ }
+ } else {
+ auto [boundsTag, boundsVal] =
+ stage_builder::packIndexIntervalsInSbeArray(std::move(intervals));
+ runtimeEnvironment->resetSlot(
+ indexBoundsInfo.slots.lowHighKeyIntervals, boundsTag, boundsVal, /*owned*/ true);
+ }
+}
} // namespace mongo::input_params
diff --git a/src/mongo/db/query/bind_input_params.h b/src/mongo/db/query/bind_input_params.h
index 82092c1ab6f..910ce991878 100644
--- a/src/mongo/db/query/bind_input_params.h
+++ b/src/mongo/db/query/bind_input_params.h
@@ -44,4 +44,15 @@ namespace mongo::input_params {
void bind(const CanonicalQuery&,
const stage_builder::InputParamToSlotMap&,
sbe::RuntimeEnvironment*);
+
+/**
+ * Binds index bounds evaluated from IETs to index bounds slots for the given query.
+ *
+ * - 'cq' is the query
+ * - 'indexBoundsInfo' contains the IETs and the slots
+ * - runtimeEnvironment SBE runtime environment
+ */
+void bindIndexBounds(const CanonicalQuery& cq,
+ const stage_builder::IndexBoundsEvaluationInfo& indexBoundsInfo,
+ sbe::RuntimeEnvironment* runtimeEnvironment);
} // namespace mongo::input_params
diff --git a/src/mongo/db/query/sbe_stage_builder.cpp b/src/mongo/db/query/sbe_stage_builder.cpp
index ac891dd5253..919a7ce6dc8 100644
--- a/src/mongo/db/query/sbe_stage_builder.cpp
+++ b/src/mongo/db/query/sbe_stage_builder.cpp
@@ -73,6 +73,7 @@
#include "mongo/db/query/sbe_stage_builder_filter.h"
#include "mongo/db/query/sbe_stage_builder_index_scan.h"
#include "mongo/db/query/sbe_stage_builder_projection.h"
+#include "mongo/db/query/sbe_utils.h"
#include "mongo/db/query/shard_filterer_factory_impl.h"
#include "mongo/db/query/util/make_data_structure.h"
#include "mongo/db/s/collection_sharding_state.h"
@@ -354,91 +355,6 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> generateEofPlan(
return {std::move(stage), std::move(outputs)};
}
-
-/**
- * Evaluates IndexBounds from the given IntervalEvaluationTrees for the given query.
- * 'indexBoundsInfo' contains the interval evaluation trees.
- *
- * Returns the built index bounds.
- */
-std::unique_ptr<IndexBounds> makeIndexBounds(const IndexBoundsEvaluationInfo& indexBoundsInfo,
- const CanonicalQuery& cq) {
- auto bounds = std::make_unique<IndexBounds>();
- bounds->fields.reserve(indexBoundsInfo.iets.size());
-
- tassert(6335200,
- "IET list size must be equal to the number of fields in the key pattern",
- static_cast<size_t>(indexBoundsInfo.index.keyPattern.nFields()) ==
- indexBoundsInfo.iets.size());
-
- BSONObjIterator it{indexBoundsInfo.index.keyPattern};
- BSONElement keyElt = it.next();
- for (auto&& iet : indexBoundsInfo.iets) {
- auto oil = interval_evaluation_tree::evaluateIntervals(
- iet, cq.getInputParamIdToMatchExpressionMap(), keyElt, indexBoundsInfo.index);
- bounds->fields.emplace_back(std::move(oil));
- keyElt = it.next();
- }
-
- IndexBoundsBuilder::alignBounds(bounds.get(),
- indexBoundsInfo.index.keyPattern,
- indexBoundsInfo.index.collator != nullptr,
- indexBoundsInfo.direction);
- return bounds;
-}
-
-/**
- * Binds index bounds evaluated from IETs to index bounds slots for the given query.
- *
- * - 'cq' is the query
- * - 'indexBoundsInfo' contains the IETs and the slots
- * - runtimeEnvironment SBE runtime environment
- */
-void bindIndexBoundsParams(const CanonicalQuery& cq,
- const IndexBoundsEvaluationInfo& indexBoundsInfo,
- sbe::RuntimeEnvironment* runtimeEnvironment) {
- auto bounds = makeIndexBounds(indexBoundsInfo, cq);
- auto intervals = makeIntervalsFromIndexBounds(*bounds,
- indexBoundsInfo.direction == 1,
- indexBoundsInfo.keyStringVersion,
- indexBoundsInfo.ordering);
- const bool isGenericScan = intervals.empty();
- runtimeEnvironment->resetSlot(indexBoundsInfo.slots.isGenericScan,
- sbe::value::TypeTags::Boolean,
- sbe::value::bitcastFrom<bool>(isGenericScan),
- /*owned*/ true);
- if (isGenericScan) {
- IndexBoundsChecker checker{
- bounds.get(), indexBoundsInfo.index.keyPattern, indexBoundsInfo.direction};
- IndexSeekPoint seekPoint;
- if (checker.getStartSeekPoint(&seekPoint)) {
- auto startKey = std::make_unique<KeyString::Value>(
- IndexEntryComparison::makeKeyStringFromSeekPointForSeek(
- seekPoint,
- indexBoundsInfo.keyStringVersion,
- indexBoundsInfo.ordering,
- indexBoundsInfo.direction == 1));
- runtimeEnvironment->resetSlot(
- indexBoundsInfo.slots.initialStartKey,
- sbe::value::TypeTags::ksValue,
- sbe::value::bitcastFrom<KeyString::Value*>(startKey.release()),
- /*owned*/ true);
- runtimeEnvironment->resetSlot(indexBoundsInfo.slots.indexBounds,
- sbe::value::TypeTags::indexBounds,
- sbe::value::bitcastFrom<IndexBounds*>(bounds.release()),
- /*owned*/ true);
- } else {
- runtimeEnvironment->resetSlot(indexBoundsInfo.slots.initialStartKey,
- sbe::value::TypeTags::Nothing,
- 0,
- /*owned*/ true);
- }
- } else {
- auto [boundsTag, boundsVal] = packIndexIntervalsInSbeArray(std::move(intervals));
- runtimeEnvironment->resetSlot(
- indexBoundsInfo.slots.lowHighKeyIntervals, boundsTag, boundsVal, /*owned*/ true);
- }
-}
} // namespace
std::unique_ptr<sbe::RuntimeEnvironment> makeRuntimeEnvironment(
@@ -543,12 +459,13 @@ void prepareSlotBasedExecutableTree(OperationContext* opCtx,
}
}
+ // TODO SERVER-66039: Add dassert on sbe::validateInputParamsBindings().
// If the cached plan is parameterized, bind new values for the parameters into the runtime
// environment.
input_params::bind(cq, data->inputParamToSlotMap, env);
for (auto&& indexBoundsInfo : data->indexBoundsEvaluationInfos) {
- bindIndexBoundsParams(cq, indexBoundsInfo, env);
+ input_params::bindIndexBounds(cq, indexBoundsInfo, env);
}
}
diff --git a/src/mongo/db/query/sbe_utils.cpp b/src/mongo/db/query/sbe_utils.cpp
index 427fdf9d7e0..19bf5c77bbe 100644
--- a/src/mongo/db/query/sbe_utils.cpp
+++ b/src/mongo/db/query/sbe_utils.cpp
@@ -27,11 +27,205 @@
* it in the license file.
*/
+#define MONGO_LOGV2_DEFAULT_COMPONENT ::mongo::logv2::LogComponent::kQuery
+
#include "mongo/db/query/sbe_utils.h"
+#include "mongo/db/matcher/expression_array.h"
+#include "mongo/db/matcher/expression_where.h"
+#include "mongo/db/matcher/match_expression_walker.h"
#include "mongo/db/query/query_planner_params.h"
+#include "mongo/db/query/sbe_stage_builder.h"
+#include "mongo/logv2/log.h"
namespace mongo::sbe {
+namespace {
+/**
+ * Helper class that collects InputParamIds from IET EvalNodes.
+ */
+class InputParamIdsCollector {
+public:
+ InputParamIdsCollector(stdx::unordered_set<MatchExpression::InputParamId>& inputParamIds)
+ : _inputParamIds{inputParamIds} {}
+
+ template <typename... Args>
+ void transport(Args...) {}
+
+ void transport(const interval_evaluation_tree::EvalNode& node) {
+ _inputParamIds.insert(node.inputParamId());
+ }
+
+private:
+ stdx::unordered_set<MatchExpression::InputParamId>& _inputParamIds;
+};
+
+/**
+ * Collect InputParamsIds from IETs of the given 'indexBoundsEvaluationInfos' for debugging
+ * purposes.
+ */
+stdx::unordered_set<MatchExpression::InputParamId> collectInputParamIdsFromIETs(
+ const std::vector<stage_builder::IndexBoundsEvaluationInfo>& indexBoundsEvaluationInfos) {
+ stdx::unordered_set<MatchExpression::InputParamId> inputParamIds;
+ InputParamIdsCollector transporter{inputParamIds};
+ for (const auto& indexBoundsInfo : indexBoundsEvaluationInfos) {
+ for (const auto& iet : indexBoundsInfo.iets) {
+ optimizer::algebra::transport(iet, transporter);
+ }
+ }
+ return inputParamIds;
+}
+
+struct MatchExpressionInputParamIdsValidatorVisitorContext {
+ size_t numberOfIncorrectlyMissingInputParamIds{0};
+};
+
+class MatchExpressionInputParamIdsValidatorVisitor final : public MatchExpressionConstVisitor {
+public:
+ MatchExpressionInputParamIdsValidatorVisitor(
+ MatchExpressionInputParamIdsValidatorVisitorContext* context,
+ const stdx::unordered_set<MatchExpression::InputParamId>& paramIdsFromIETs,
+ const stage_builder::InputParamToSlotMap& inputParamToSlotMap)
+ : _context{context},
+ _paramIdsFromIETs{paramIdsFromIETs},
+ _inputParamToSlotMap{inputParamToSlotMap} {
+ invariant(_context);
+ }
+
+ void visit(const BitsAllClearMatchExpression* expr) final {
+ visitBitTestExpr(expr);
+ }
+
+ void visit(const BitsAllSetMatchExpression* expr) final {
+ visitBitTestExpr(expr);
+ }
+
+ void visit(const BitsAnyClearMatchExpression* expr) final {
+ visitBitTestExpr(expr);
+ }
+
+ void visit(const BitsAnySetMatchExpression* expr) final {
+ visitBitTestExpr(expr);
+ }
+
+ void visit(const EqualityMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const GTEMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const GTMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const InMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const LTEMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const LTMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const ModMatchExpression* expr) final {
+ validate(expr->getDivisorInputParamId(), expr);
+ validate(expr->getRemainderInputParamId(), expr);
+ }
+
+ void visit(const RegexMatchExpression* expr) final {
+ validate(expr->getCompiledRegexInputParamId(), expr);
+ validate(expr->getSourceRegexInputParamId(), expr);
+ }
+
+ void visit(const SizeMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const TypeMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const WhereMatchExpression* expr) final {
+ visitExpr(expr);
+ }
+
+ void visit(const AlwaysFalseMatchExpression* expr) final {}
+ void visit(const AlwaysTrueMatchExpression* expr) final {}
+ void visit(const AndMatchExpression* expr) final {}
+ void visit(const ElemMatchObjectMatchExpression* matchExpr) final {}
+ void visit(const ElemMatchValueMatchExpression* matchExpr) final {}
+ void visit(const ExistsMatchExpression* expr) final {}
+ void visit(const ExprMatchExpression* expr) final {}
+ void visit(const GeoMatchExpression* expr) final {}
+ void visit(const GeoNearMatchExpression* expr) final {}
+ void visit(const InternalBucketGeoWithinMatchExpression* expr) final {}
+ void visit(const InternalExprEqMatchExpression* expr) final {}
+ void visit(const InternalExprGTMatchExpression* expr) final {}
+ void visit(const InternalExprGTEMatchExpression* expr) final {}
+ void visit(const InternalExprLTMatchExpression* expr) final {}
+ void visit(const InternalExprLTEMatchExpression* expr) final {}
+ void visit(const InternalSchemaAllElemMatchFromIndexMatchExpression* expr) final {}
+ void visit(const InternalSchemaAllowedPropertiesMatchExpression* expr) final {}
+ void visit(const InternalSchemaBinDataEncryptedTypeExpression* expr) final {}
+ void visit(const InternalSchemaBinDataFLE2EncryptedTypeExpression* expr) final {}
+ void visit(const InternalSchemaBinDataSubTypeExpression* expr) final {}
+ void visit(const InternalSchemaCondMatchExpression* expr) final {}
+ void visit(const InternalSchemaEqMatchExpression* expr) final {}
+ void visit(const InternalSchemaFmodMatchExpression* expr) final {}
+ void visit(const InternalSchemaMatchArrayIndexMatchExpression* expr) final {}
+ void visit(const InternalSchemaMaxItemsMatchExpression* expr) final {}
+ void visit(const InternalSchemaMaxLengthMatchExpression* expr) final {}
+ void visit(const InternalSchemaMaxPropertiesMatchExpression* expr) final {}
+ void visit(const InternalSchemaMinItemsMatchExpression* expr) final {}
+ void visit(const InternalSchemaMinLengthMatchExpression* expr) final {}
+ void visit(const InternalSchemaMinPropertiesMatchExpression* expr) final {}
+ void visit(const InternalSchemaObjectMatchExpression* expr) final {}
+ void visit(const InternalSchemaRootDocEqMatchExpression* expr) final {}
+ void visit(const InternalSchemaTypeExpression* expr) final {}
+ void visit(const InternalSchemaUniqueItemsMatchExpression* expr) final {}
+ void visit(const InternalSchemaXorMatchExpression* expr) final {}
+ void visit(const NorMatchExpression* expr) final {}
+ void visit(const NotMatchExpression* expr) final {}
+ void visit(const OrMatchExpression* expr) final {}
+ void visit(const TextMatchExpression* expr) final {}
+ void visit(const TextNoOpMatchExpression* expr) final {}
+ void visit(const TwoDPtInAnnulusExpression* expr) final {}
+ void visit(const WhereNoOpMatchExpression* expr) final {}
+
+private:
+ void visitBitTestExpr(const BitTestMatchExpression* expr) {
+ validate(expr->getBitPositionsParamId(), expr);
+ validate(expr->getBitMaskParamId(), expr);
+ }
+
+ template <typename T>
+ void visitExpr(const T* expr) {
+ validate(expr->getInputParamId(), expr);
+ }
+
+ void validate(const boost::optional<MatchExpression::InputParamId>& inputParamId,
+ const MatchExpression* expr) {
+ if (inputParamId && !_inputParamToSlotMap.contains(*inputParamId) &&
+ !_paramIdsFromIETs.contains(*inputParamId)) {
+ ++_context->numberOfIncorrectlyMissingInputParamIds;
+ LOGV2_WARNING(6536100,
+ "Found mismatched input param",
+ "inputParamID"_attr = *inputParamId,
+ "expr"_attr = expr->debugString());
+ }
+ }
+
+ MatchExpressionInputParamIdsValidatorVisitorContext* _context;
+
+ const stdx::unordered_set<MatchExpression::InputParamId>& _paramIdsFromIETs;
+ const stage_builder::InputParamToSlotMap& _inputParamToSlotMap;
+};
+} // namespace
+
bool isQuerySbeCompatible(const CollectionPtr* collection,
const CanonicalQuery* cq,
size_t plannerOptions) {
@@ -61,4 +255,20 @@ bool isQuerySbeCompatible(const CollectionPtr* collection,
isQueryNotAgainstTimeseriesCollection && isQueryNotAgainstClusteredCollection &&
doesNotSortOnMetaOrPathWithNumericComponents && isNotOplog;
}
+
+bool validateInputParamsBindings(
+ const MatchExpression* root,
+ const std::vector<stage_builder::IndexBoundsEvaluationInfo>& indexBoundsEvaluationInfos,
+ const stage_builder::InputParamToSlotMap& inputParamToSlotMap) {
+ auto inputParamIdsFromIETs = collectInputParamIdsFromIETs(indexBoundsEvaluationInfos);
+ MatchExpressionInputParamIdsValidatorVisitorContext context{};
+ MatchExpressionInputParamIdsValidatorVisitor visitor{
+ &context, inputParamIdsFromIETs, inputParamToSlotMap};
+ MatchExpressionWalker walker{&visitor, nullptr, nullptr};
+ tree_walker::walk<true, MatchExpression>(root, &walker);
+ if (context.numberOfIncorrectlyMissingInputParamIds != 0) {
+ LOGV2_WARNING(6536101, "Found mismatched input params", "expr"_attr = root->debugString());
+ }
+ return context.numberOfIncorrectlyMissingInputParamIds == 0;
+}
} // namespace mongo::sbe
diff --git a/src/mongo/db/query/sbe_utils.h b/src/mongo/db/query/sbe_utils.h
index 7de483b6f5a..5dce1500213 100644
--- a/src/mongo/db/query/sbe_utils.h
+++ b/src/mongo/db/query/sbe_utils.h
@@ -31,6 +31,7 @@
#include "mongo/db/catalog/collection.h"
#include "mongo/db/query/canonical_query.h"
+#include "mongo/db/query/sbe_stage_builder.h"
namespace mongo::sbe {
/**
@@ -39,4 +40,16 @@ namespace mongo::sbe {
bool isQuerySbeCompatible(const CollectionPtr* collection,
const CanonicalQuery* cq,
size_t plannerOptions);
+
+/**
+ * Some of InputParamIds assigned in the MatchExpression tree (parameter 'root') might be missing
+ * from 'inputParamToSlotMap' due to later optimizations on index bound evaluation step. This
+ * function validates that in this case the missing parameters are indeed missing due to the
+ * optimizations mentioned above and, as such, are not represented in Interval Evaluation Tree built
+ * during index bound evaluation and stored in 'inputParamToSlotMap'.
+ */
+bool validateInputParamsBindings(
+ const MatchExpression* root,
+ const std::vector<stage_builder::IndexBoundsEvaluationInfo>& indexBoundsEvaluationInfos,
+ const stage_builder::InputParamToSlotMap& inputParamToSlotMap);
} // namespace mongo::sbe