summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorauto-revert-processor <dev-prod-dag@mongodb.com>2022-12-14 02:38:42 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-12-14 03:12:23 +0000
commit67603a852563fcc445c25ba9e8d0a47796c1b078 (patch)
tree7fea77591c8c063ed138228262d7c5c8a4ba2fca /src
parentc528dba0e3079c744773b5b9357d8c57bbbb6c55 (diff)
downloadmongo-67603a852563fcc445c25ba9e8d0a47796c1b078.tar.gz
Revert "SERVER-69508 Generate SBE Expressions by means of constant-folded ABT trees"
This reverts commit 6d6ccec09a77c8b7a02ec8dfb90924509d3ec87d.
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/SConscript4
-rw-r--r--src/mongo/db/exec/sbe/SConscript2
-rw-r--r--src/mongo/db/query/SConscript16
-rw-r--r--src/mongo/db/query/sbe_expression_bm.cpp2
-rw-r--r--src/mongo/db/query/sbe_stage_builder.cpp93
-rw-r--r--src/mongo/db/query/sbe_stage_builder_eval_frame.cpp68
-rw-r--r--src/mongo/db/query/sbe_stage_builder_eval_frame.h76
-rw-r--r--src/mongo/db/query/sbe_stage_builder_expression.cpp246
-rw-r--r--src/mongo/db/query/sbe_stage_builder_filter.cpp71
-rw-r--r--src/mongo/db/query/sbe_stage_builder_helpers.cpp126
-rw-r--r--src/mongo/db/query/sbe_stage_builder_helpers.h83
-rw-r--r--src/mongo/db/query/sbe_stage_builder_projection.cpp37
12 files changed, 173 insertions, 651 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 9caaa5f0961..eaadb2bc861 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -1457,10 +1457,8 @@ env.Library(
'query/sbe_stage_builder.cpp',
'query/sbe_stage_builder_accumulator.cpp',
'query/sbe_stage_builder_coll_scan.cpp',
- 'query/sbe_stage_builder_eval_frame.cpp',
'query/sbe_stage_builder_expression.cpp',
'query/sbe_stage_builder_filter.cpp',
- 'query/sbe_stage_builder_helpers.cpp',
'query/sbe_stage_builder_index_scan.cpp',
'query/sbe_stage_builder_lookup.cpp',
'query/sbe_stage_builder_projection.cpp',
@@ -1491,7 +1489,6 @@ env.Library(
'cursor_server_params',
'dbdirectclient',
'exec/projection_executor',
- 'exec/sbe/query_sbe_stages',
'exec/sbe/query_sbe_storage',
'exec/scoped_timer',
'exec/sort_executor',
@@ -1507,6 +1504,7 @@ env.Library(
'query/query_common',
'query/query_plan_cache',
'query/query_planner',
+ 'query/sbe_stage_builder_helpers',
'repl/repl_coordinator_interface',
's/sharding_api_d',
'session/logical_session_cache',
diff --git a/src/mongo/db/exec/sbe/SConscript b/src/mongo/db/exec/sbe/SConscript
index 8e2d1762d1e..9be25c996cd 100644
--- a/src/mongo/db/exec/sbe/SConscript
+++ b/src/mongo/db/exec/sbe/SConscript
@@ -151,7 +151,7 @@ env.Library(
],
LIBDEPS=[
'$BUILD_DIR/mongo/db/catalog/catalog_test_fixture',
- '$BUILD_DIR/mongo/db/query_exec',
+ '$BUILD_DIR/mongo/db/query/sbe_stage_builder_helpers',
'$BUILD_DIR/mongo/unittest/unittest',
'query_sbe',
'query_sbe_stages',
diff --git a/src/mongo/db/query/SConscript b/src/mongo/db/query/SConscript
index 305bff56717..1d3e11ccc13 100644
--- a/src/mongo/db/query/SConscript
+++ b/src/mongo/db/query/SConscript
@@ -116,6 +116,22 @@ env.Library(
)
env.Library(
+ target='sbe_stage_builder_helpers',
+ source=[
+ 'sbe_stage_builder_helpers.cpp',
+ ],
+ LIBDEPS=[
+ '$BUILD_DIR/mongo/base',
+ '$BUILD_DIR/mongo/db/exec/sbe/query_sbe',
+ '$BUILD_DIR/mongo/db/exec/sbe/query_sbe_stages',
+ '$BUILD_DIR/mongo/db/exec/sbe/query_sbe_storage',
+ '$BUILD_DIR/mongo/db/index/index_access_method',
+ '$BUILD_DIR/mongo/db/query_expressions',
+ '$BUILD_DIR/mongo/db/storage/execution_context',
+ ],
+)
+
+env.Library(
target='projection_ast',
source=[
'projection.cpp',
diff --git a/src/mongo/db/query/sbe_expression_bm.cpp b/src/mongo/db/query/sbe_expression_bm.cpp
index 15093a8af6b..4ebee3f4e6d 100644
--- a/src/mongo/db/query/sbe_expression_bm.cpp
+++ b/src/mongo/db/query/sbe_expression_bm.cpp
@@ -113,7 +113,7 @@ public:
"sbe expression benchmark PlanStage",
"stage"_attr = debugPrint(stage.get()));
- auto expr = evalExpr.extractExpr(state.slotVarMap);
+ auto expr = evalExpr.extractExpr();
LOGV2_DEBUG(6979802,
1,
"sbe expression benchmark EExpression",
diff --git a/src/mongo/db/query/sbe_stage_builder.cpp b/src/mongo/db/query/sbe_stage_builder.cpp
index 525b88e0913..08898b861a1 100644
--- a/src/mongo/db/query/sbe_stage_builder.cpp
+++ b/src/mongo/db/query/sbe_stage_builder.cpp
@@ -594,6 +594,25 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> SlotBasedStageBuilder
}
namespace {
+std::unique_ptr<sbe::EExpression> abtToExpr(optimizer::ABT& abt, optimizer::SlotVarMap& slotMap) {
+ auto env = optimizer::VariableEnvironment::build(abt);
+
+ // Do not use descriptive names here.
+ auto prefixId = optimizer::PrefixId::create(false /*useDescriptiveNames*/);
+ // Convert paths into ABT expressions.
+ optimizer::EvalPathLowering pathLower{prefixId, env};
+ pathLower.optimize(abt);
+
+ // Run the constant folding to eliminate lambda applications as they are not directly
+ // supported by the SBE VM.
+ optimizer::ConstEval constEval{env};
+ constEval.optimize(abt);
+
+ // And finally convert to the SBE expression.
+ optimizer::SBEExpressionLowering exprLower{env, slotMap};
+ return exprLower.optimize(abt);
+}
+
std::unique_ptr<sbe::EExpression> generatePerColumnPredicate(StageBuilderState& state,
const MatchExpression* me,
const sbe::EVariable& inputVar) {
@@ -602,34 +621,34 @@ std::unique_ptr<sbe::EExpression> generatePerColumnPredicate(StageBuilderState&
// the element is an object or array.
case MatchExpression::REGEX:
return generateRegexExpr(state, checked_cast<const RegexMatchExpression*>(me), inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::MOD:
return generateModExpr(state, checked_cast<const ModMatchExpression*>(me), inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::BITS_ALL_SET:
return generateBitTestExpr(state,
checked_cast<const BitTestMatchExpression*>(me),
sbe::BitTestBehavior::AllSet,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::BITS_ALL_CLEAR:
return generateBitTestExpr(state,
checked_cast<const BitTestMatchExpression*>(me),
sbe::BitTestBehavior::AllClear,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::BITS_ANY_SET:
return generateBitTestExpr(state,
checked_cast<const BitTestMatchExpression*>(me),
sbe::BitTestBehavior::AnySet,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::BITS_ANY_CLEAR:
return generateBitTestExpr(state,
checked_cast<const BitTestMatchExpression*>(me),
sbe::BitTestBehavior::AnyClear,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::EXISTS:
return makeConstant(sbe::value::TypeTags::Boolean, true);
case MatchExpression::LT:
@@ -637,37 +656,37 @@ std::unique_ptr<sbe::EExpression> generatePerColumnPredicate(StageBuilderState&
checked_cast<const ComparisonMatchExpression*>(me),
sbe::EPrimBinary::less,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::GT:
return generateComparisonExpr(state,
checked_cast<const ComparisonMatchExpression*>(me),
sbe::EPrimBinary::greater,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::EQ:
return generateComparisonExpr(state,
checked_cast<const ComparisonMatchExpression*>(me),
sbe::EPrimBinary::eq,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::LTE:
return generateComparisonExpr(state,
checked_cast<const ComparisonMatchExpression*>(me),
sbe::EPrimBinary::lessEq,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::GTE:
return generateComparisonExpr(state,
checked_cast<const ComparisonMatchExpression*>(me),
sbe::EPrimBinary::greaterEq,
inputVar)
- .extractExpr(state.slotVarMap);
+ .extractExpr();
case MatchExpression::MATCH_IN: {
auto expr = checked_cast<const InMatchExpression*>(me);
tassert(6988583,
"Push-down of non-scalar values in $in is not supported.",
!expr->hasNonScalarOrNonEmptyValues());
- return generateInExpr(state, expr, inputVar).extractExpr(state.slotVarMap);
+ return generateInExpr(state, expr, inputVar).extractExpr();
}
case MatchExpression::TYPE_OPERATOR: {
const auto& expr = checked_cast<const TypeMatchExpression*>(me);
@@ -990,12 +1009,8 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> SlotBasedStageBuilder
auto sortKeysSet = StringSet{sortKeys.begin(), sortKeys.end()};
auto fieldsAndSortKeys = appendVectorUnique(std::move(fields), std::move(sortKeys));
- auto [outStage, outSlots] = projectFieldsToSlots(std::move(stage),
- fieldsAndSortKeys,
- resultSlot,
- root->nodeId(),
- &_slotIdGenerator,
- _state.slotVarMap);
+ auto [outStage, outSlots] = projectFieldsToSlots(
+ std::move(stage), fieldsAndSortKeys, resultSlot, root->nodeId(), &_slotIdGenerator);
stage = std::move(outStage);
auto collatorSlot = _data.env->getSlotIfExists("collator"_sd);
@@ -1736,8 +1751,7 @@ SlotBasedStageBuilder::buildProjectionDefault(const QuerySolutionNode* root,
auto [resultSlot, resultStage] = projectEvalExpr(std::move(projectionExpr),
EvalStage{std::move(stage), {}},
root->nodeId(),
- &_slotIdGenerator,
- _state.slotVarMap);
+ &_slotIdGenerator);
stage = resultStage.extractStage(root->nodeId());
outputs.set(kResult, resultSlot);
@@ -2277,8 +2291,8 @@ EvalStage optimizeFieldPaths(StageBuilderState& state,
auto rootExpr = rootSlot.has_value() ? EvalExpr{*rootSlot} : EvalExpr{};
auto expr = generateExpression(state, fieldExpr, std::move(rootExpr), &outputs);
- auto [slot, projectStage] = projectEvalExpr(
- std::move(expr), std::move(stage), nodeId, state.slotIdGenerator, state.slotVarMap);
+ auto [slot, projectStage] =
+ projectEvalExpr(std::move(expr), std::move(stage), nodeId, state.slotIdGenerator);
state.preGeneratedExprs.emplace(fieldPathStr, slot);
stage = std::move(projectStage);
@@ -2321,18 +2335,15 @@ std::tuple<sbe::value::SlotVector, EvalStage, std::unique_ptr<sbe::EExpression>>
auto [groupByEvalExpr, groupByEvalStage] = generateGroupByKeyImpl(
state, fieldExpr, outputs, rootSlot, std::move(stage), nodeId, slotIdGenerator);
- auto [slot, projectStage] = projectEvalExpr(std::move(groupByEvalExpr),
- std::move(groupByEvalStage),
- nodeId,
- slotIdGenerator,
- state.slotVarMap);
+ auto [slot, projectStage] = projectEvalExpr(
+ std::move(groupByEvalExpr), std::move(groupByEvalStage), nodeId, slotIdGenerator);
slots.push_back(slot);
groupByEvalExpr = slot;
stage = std::move(projectStage);
exprs.emplace_back(makeConstant(fieldName));
- exprs.emplace_back(groupByEvalExpr.extractExpr(state.slotVarMap));
+ exprs.emplace_back(groupByEvalExpr.extractExpr());
}
// When there's only one field in the document _id expression, 'Nothing' is converted to
@@ -2342,11 +2353,8 @@ std::tuple<sbe::value::SlotVector, EvalStage, std::unique_ptr<sbe::EExpression>>
// SERVER-21992 issue goes away and the distinct scan should be able to return 'Nothing' and
// 'Null' separately.
if (slots.size() == 1) {
- auto [slot, projectStage] = projectEvalExpr(makeFillEmptyNull(std::move(exprs[1])),
- std::move(stage),
- nodeId,
- slotIdGenerator,
- state.slotVarMap);
+ auto [slot, projectStage] = projectEvalExpr(
+ makeFillEmptyNull(std::move(exprs[1])), std::move(stage), nodeId, slotIdGenerator);
slots[0] = slot;
exprs[1] = makeVariable(slots[0]);
stage = std::move(projectStage);
@@ -2363,12 +2371,9 @@ std::tuple<sbe::value::SlotVector, EvalStage, std::unique_ptr<sbe::EExpression>>
// The group-by field may end up being 'Nothing' and in that case _id: null will be
// returned. Calling 'makeFillEmptyNull' for the group-by field takes care of that.
- auto fillEmptyNullExpr = makeFillEmptyNull(groupByEvalExpr.extractExpr(state.slotVarMap));
- auto [slot, projectStage] = projectEvalExpr(std::move(fillEmptyNullExpr),
- std::move(groupByEvalStage),
- nodeId,
- slotIdGenerator,
- state.slotVarMap);
+ auto fillEmptyNullExpr = makeFillEmptyNull(groupByEvalExpr.extractExpr());
+ auto [slot, projectStage] = projectEvalExpr(
+ std::move(fillEmptyNullExpr), std::move(groupByEvalStage), nodeId, slotIdGenerator);
stage = std::move(projectStage);
return {sbe::value::SlotVector{slot}, std::move(stage), nullptr};
@@ -2395,7 +2400,7 @@ std::tuple<sbe::value::SlotVector, EvalStage> generateAccumulator(
// as sum(1).
auto collatorSlot = state.data->env->getSlotIfExists("collator"_sd);
auto accExprs = stage_builder::buildAccumulator(
- accStmt, argExpr.extractExpr(state.slotVarMap), collatorSlot, *state.frameIdGenerator);
+ accStmt, argExpr.extractExpr(), collatorSlot, *state.frameIdGenerator);
sbe::value::SlotVector aggSlots;
for (auto& accExpr : accExprs) {
@@ -3045,12 +3050,8 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> SlotBasedStageBuilder
outputs.has(PlanStageSlots::kResult));
auto resultSlot = outputs.get(PlanStageSlots::kResult);
- auto [outStage, outSlots] = projectFieldsToSlots(std::move(stage),
- fields,
- resultSlot,
- root->nodeId(),
- &_slotIdGenerator,
- _state.slotVarMap);
+ auto [outStage, outSlots] = projectFieldsToSlots(
+ std::move(stage), fields, resultSlot, root->nodeId(), &_slotIdGenerator);
stage = std::move(outStage);
for (size_t i = 0; i < fields.size(); ++i) {
diff --git a/src/mongo/db/query/sbe_stage_builder_eval_frame.cpp b/src/mongo/db/query/sbe_stage_builder_eval_frame.cpp
deleted file mode 100644
index dd6ed6a56dd..00000000000
--- a/src/mongo/db/query/sbe_stage_builder_eval_frame.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * Copyright (C) 2022-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.
- */
-
-#include "mongo/platform/basic.h"
-
-#include "mongo/db/query/sbe_stage_builder_eval_frame.h"
-#include "mongo/db/query/sbe_stage_builder_helpers.h"
-
-namespace mongo::stage_builder {
-
-std::unique_ptr<sbe::EExpression> EvalExpr::extractExpr(optimizer::SlotVarMap& varMap) {
- if (hasSlot()) {
- return sbe::makeE<sbe::EVariable>(stdx::get<sbe::value::SlotId>(_storage));
- }
-
- if (hasABT()) {
- return abtToExpr(stdx::get<optimizer::ABT>(_storage), varMap);
- }
-
- tassert(6950800,
- "Unexpected: extractExpr() method invoked on an empty object",
- stdx::holds_alternative<std::unique_ptr<sbe::EExpression>>(_storage));
-
- return std::move(stdx::get<std::unique_ptr<sbe::EExpression>>(_storage));
-}
-
-optimizer::ABT EvalExpr::extractABT(optimizer::SlotVarMap& varMap) {
- if (hasSlot()) {
- auto slotId = stdx::get<sbe::value::SlotId>(_storage);
- auto varName = makeVariableName(slotId);
- varMap.emplace(varName, slotId);
- return optimizer::make<optimizer::Variable>(varName);
- }
-
- tassert(6950801,
- "Unexpected: extractABT() method invoked on an EExpression object",
- stdx::holds_alternative<optimizer::ABT>(_storage));
-
- return std::move(stdx::get<optimizer::ABT>(_storage));
-}
-
-} // namespace mongo::stage_builder
diff --git a/src/mongo/db/query/sbe_stage_builder_eval_frame.h b/src/mongo/db/query/sbe_stage_builder_eval_frame.h
index 592f563ee3b..40645b98cea 100644
--- a/src/mongo/db/query/sbe_stage_builder_eval_frame.h
+++ b/src/mongo/db/query/sbe_stage_builder_eval_frame.h
@@ -31,12 +31,9 @@
#include <stack>
-#include "mongo/db/exec/sbe/abt/abt_lower.h"
#include "mongo/db/exec/sbe/expressions/expression.h"
#include "mongo/db/exec/sbe/stages/co_scan.h"
#include "mongo/db/exec/sbe/stages/limit_skip.h"
-#include "mongo/db/query/optimizer/node.h"
-#include "mongo/db/query/optimizer/syntax/syntax.h"
#include "mongo/stdx/variant.h"
namespace mongo::stage_builder {
@@ -48,77 +45,52 @@ namespace mongo::stage_builder {
*/
class EvalExpr {
public:
- EvalExpr() : _storage{false} {}
+ EvalExpr() : _exprOrSlot{std::unique_ptr<sbe::EExpression>{}} {}
- EvalExpr(EvalExpr&& e) : _storage(std::move(e._storage)) {
+ EvalExpr(EvalExpr&& e) : _exprOrSlot(std::move(e._exprOrSlot)) {
e.reset();
}
- EvalExpr(std::unique_ptr<sbe::EExpression>&& e) : _storage(std::move(e)) {}
+ EvalExpr(std::unique_ptr<sbe::EExpression>&& e) : _exprOrSlot(std::move(e)) {}
- EvalExpr(sbe::value::SlotId s) : _storage(s) {}
-
- EvalExpr(const optimizer::ABT& a) : _storage(a) {}
-
- EvalExpr(optimizer::ABT&& a) : _storage(std::move(a)) {}
+ EvalExpr(sbe::value::SlotId s) : _exprOrSlot(s) {}
EvalExpr& operator=(EvalExpr&& e) {
if (this == &e) {
return *this;
}
- _storage = std::move(e._storage);
+ _exprOrSlot = std::move(e._exprOrSlot);
e.reset();
return *this;
}
EvalExpr& operator=(std::unique_ptr<sbe::EExpression>&& e) {
- _storage = std::move(e);
+ _exprOrSlot = std::move(e);
e.reset();
return *this;
}
EvalExpr& operator=(sbe::value::SlotId s) {
- _storage = s;
- return *this;
- }
-
- EvalExpr& operator=(optimizer::ABT&& a) {
- _storage = std::move(a);
+ _exprOrSlot = s;
return *this;
}
boost::optional<sbe::value::SlotId> getSlot() const {
- return hasSlot() ? boost::make_optional(stdx::get<sbe::value::SlotId>(_storage))
+ return hasSlot() ? boost::make_optional(stdx::get<sbe::value::SlotId>(_exprOrSlot))
: boost::none;
}
bool hasSlot() const {
- return stdx::holds_alternative<sbe::value::SlotId>(_storage);
- }
-
- bool hasExpr() const {
- return stdx::holds_alternative<std::unique_ptr<sbe::EExpression>>(_storage);
- }
-
- bool hasABT() const {
- return stdx::holds_alternative<optimizer::ABT>(_storage);
+ return stdx::holds_alternative<sbe::value::SlotId>(_exprOrSlot);
}
EvalExpr clone() const {
if (hasSlot()) {
- return stdx::get<sbe::value::SlotId>(_storage);
- }
-
- if (hasABT()) {
- return stdx::get<optimizer::ABT>(_storage);
- }
-
- if (stdx::holds_alternative<bool>(_storage)) {
- return EvalExpr{};
+ return stdx::get<sbe::value::SlotId>(_exprOrSlot);
}
- const auto& expr = stdx::get<std::unique_ptr<sbe::EExpression>>(_storage);
+ const auto& expr = stdx::get<std::unique_ptr<sbe::EExpression>>(_exprOrSlot);
if (expr) {
return expr->clone();
}
@@ -127,7 +99,7 @@ public:
}
bool isNull() const {
- return stdx::holds_alternative<bool>(_storage);
+ return !hasSlot() && !stdx::get<std::unique_ptr<sbe::EExpression>>(_exprOrSlot);
}
explicit operator bool() const {
@@ -135,27 +107,19 @@ public:
}
void reset() {
- _storage = false;
+ _exprOrSlot = std::unique_ptr<sbe::EExpression>{};
}
- /**
- * Extract the expression on top of the stack as an SBE EExpression node. If the expression is
- * stored as an ABT node, it is lowered into an SBE expression, using the provided map to
- * convert variable names into slot ids.
- */
- std::unique_ptr<sbe::EExpression> extractExpr(optimizer::SlotVarMap& varMap);
+ std::unique_ptr<sbe::EExpression> extractExpr() {
+ if (hasSlot()) {
+ return sbe::makeE<sbe::EVariable>(stdx::get<sbe::value::SlotId>(_exprOrSlot));
+ }
- /**
- * Extract the expression on top of the stack as an ABT node. If the expression is stored as a
- * slot id, the mapping between the generated ABT node and the slot id is recorded in the map.
- * Throws an exception if the expression is stored as an SBE EExpression.
- */
- optimizer::ABT extractABT(optimizer::SlotVarMap& varMap);
+ return std::move(stdx::get<std::unique_ptr<sbe::EExpression>>(_exprOrSlot));
+ }
private:
- // The bool type as the first option is used to represent the empty storage.
- stdx::variant<bool, std::unique_ptr<sbe::EExpression>, sbe::value::SlotId, optimizer::ABT>
- _storage;
+ stdx::variant<std::unique_ptr<sbe::EExpression>, sbe::value::SlotId> _exprOrSlot;
};
/**
diff --git a/src/mongo/db/query/sbe_stage_builder_expression.cpp b/src/mongo/db/query/sbe_stage_builder_expression.cpp
index a3076c3bebd..4779d78c991 100644
--- a/src/mongo/db/query/sbe_stage_builder_expression.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_expression.cpp
@@ -92,55 +92,29 @@ struct ExpressionVisitorContext {
invariant(exprStack.size() >= arity);
}
- /**
- * Return whether the last @arity items in the stack are not holding EExpression objects.
- */
- bool hasAllAbtEligibleEntries(size_t arity) {
- bool allAbt = true;
- auto it = exprStack.crbegin();
- for (size_t i = 0; it != exprStack.crend() && i < arity; i++, it++) {
- allAbt &= it->hasABT() || it->hasSlot();
- }
- return allAbt;
- }
-
std::unique_ptr<sbe::EExpression> popExpr() {
tassert(6987500, "tried to pop from empty EvalExpr stack", !exprStack.empty());
- auto expr = std::move(exprStack.back());
- exprStack.pop_back();
- return expr.extractExpr(state.slotVarMap);
+ auto expr = std::move(exprStack.top());
+ exprStack.pop();
+ return expr.extractExpr();
}
void pushExpr(EvalExpr expr) {
- exprStack.emplace_back(std::move(expr));
- }
-
- optimizer::ABT popABTExpr() {
- tassert(6987504, "tried to pop from empty EvalExpr stack", !exprStack.empty());
-
- auto expr = std::move(exprStack.back());
- exprStack.pop_back();
- return expr.extractABT(state.slotVarMap);
+ exprStack.push(std::move(expr));
}
EvalExpr done() {
tassert(6987501, "expected exactly one EvalExpr on the stack", exprStack.size() == 1);
- auto expr = std::move(exprStack.back());
- exprStack.pop_back();
+ auto expr = std::move(exprStack.top());
+ exprStack.pop();
return expr;
}
- optimizer::ProjectionName registerVariable(sbe::value::SlotId slotId) {
- auto varName = stage_builder::makeVariableName(slotId);
- state.slotVarMap.emplace(varName, slotId);
- return varName;
- }
-
StageBuilderState& state;
- std::vector<EvalExpr> exprStack;
+ std::stack<EvalExpr> exprStack;
EvalExpr rootExpr;
@@ -237,89 +211,6 @@ std::unique_ptr<sbe::EExpression> generateTraverse(
}
/**
- * Version of the generateTraverse helper functions that process ABT trees instead of EExpression
- * ones.
- */
-optimizer::ABT generateTraverseHelper(
- ExpressionVisitorContext* context,
- boost::optional<optimizer::ABT>&& inputExpr,
- const FieldPath& fp,
- size_t level,
- sbe::value::FrameIdGenerator* frameIdGenerator,
- boost::optional<sbe::value::SlotId> topLevelFieldSlot = boost::none) {
- using namespace std::literals;
-
- invariant(level < fp.getPathLength());
- tassert(6950802,
- "Expected an input expression or top level field",
- inputExpr.has_value() || topLevelFieldSlot.has_value());
-
- // Generate an expression to read a sub-field at the current nested level.
- auto fieldName = makeABTConstant(fp.getFieldName(level));
- auto fieldExpr = topLevelFieldSlot
- ? optimizer::make<optimizer::Variable>(context->registerVariable(*topLevelFieldSlot))
- : makeABTFunction("getField"_sd, std::move(*inputExpr), std::move(fieldName));
-
- if (level == fp.getPathLength() - 1) {
- // For the last level, we can just return the field slot without the need for a
- // traverse stage.
- return fieldExpr;
- }
-
- // Generate nested traversal.
- auto lambdaFrameId = frameIdGenerator->generate();
- auto lambdaParamName = makeLocalVariableName(lambdaFrameId, 0);
- boost::optional<optimizer::ABT> lambdaParam =
- optimizer::make<optimizer::Variable>(lambdaParamName);
-
- auto resultExpr =
- generateTraverseHelper(context, std::move(lambdaParam), fp, level + 1, frameIdGenerator);
-
- auto lambdaExpr =
- optimizer::make<optimizer::LambdaAbstraction>(lambdaParamName, std::move(resultExpr));
-
- // Generate the traverse stage for the current nested level.
- return makeABTFunction(
- "traverseP"_sd, std::move(fieldExpr), std::move(lambdaExpr), optimizer::Constant::int32(1));
-}
-
-optimizer::ABT generateTraverse(
- ExpressionVisitorContext* context,
- boost::optional<optimizer::ABT>&& inputExpr,
- bool expectsDocumentInputOnly,
- const FieldPath& fp,
- sbe::value::FrameIdGenerator* frameIdGenerator,
- boost::optional<sbe::value::SlotId> topLevelFieldSlot = boost::none) {
- size_t level = 0;
-
- if (expectsDocumentInputOnly) {
- // When we know for sure that 'inputExpr' will be a document and _not_ an array (such as
- // when accessing a field on the root document), we can generate a simpler expression.
- return generateTraverseHelper(
- context, std::move(inputExpr), fp, level, frameIdGenerator, topLevelFieldSlot);
- } else {
- tassert(6950803, "Expected an input expression", inputExpr.has_value());
- // The general case: the value in the 'inputExpr' may be an array that will require
- // traversal.
- auto lambdaFrameId = frameIdGenerator->generate();
- auto lambdaParamName = makeLocalVariableName(lambdaFrameId, 0);
- boost::optional<optimizer::ABT> lambdaParam =
- optimizer::make<optimizer::Variable>(lambdaParamName);
-
- auto resultExpr =
- generateTraverseHelper(context, std::move(lambdaParam), fp, level, frameIdGenerator);
-
- auto lambdaExpr =
- optimizer::make<optimizer::LambdaAbstraction>(lambdaParamName, std::move(resultExpr));
-
- return makeABTFunction("traverseP"_sd,
- std::move(*inputExpr),
- std::move(lambdaExpr),
- optimizer::Constant::int32(1));
- }
-}
-
-/**
* Generates an EExpression that converts the input to upper or lower case.
*/
void generateStringCaseConversionExpression(ExpressionVisitorContext* _context,
@@ -781,7 +672,7 @@ public:
void visit(const ExpressionConstant* expr) final {
auto [tag, val] = makeValue(expr->getValue());
- _context->pushExpr(makeABTConstant(tag, val));
+ _context->pushExpr(sbe::makeE<sbe::EConstant>(tag, val));
}
void visit(const ExpressionAbs* expr) final {
@@ -989,77 +880,6 @@ public:
}
void visit(const ExpressionCompare* expr) final {
_context->ensureArity(2);
- // Build an ABT node if both operands are stored as either a slot or an ABT expression, and
- // the comparison doesn't involve a collation, because binary operations in ABT don't
- // support it yet.
- if (!_context->state.data->env->getSlotIfExists("collator"_sd) &&
- _context->hasAllAbtEligibleEntries(2)) {
- auto rhs = _context->popABTExpr();
- auto lhs = _context->popABTExpr();
- auto lhsRef = makeLocalVariableName(_context->state.frameIdGenerator->generate(), 0);
- auto rhsRef = makeLocalVariableName(_context->state.frameIdGenerator->generate(), 0);
-
- auto comparisonOperator = [expr]() {
- switch (expr->getOp()) {
- case ExpressionCompare::CmpOp::EQ:
- return optimizer::Operations::Eq;
- case ExpressionCompare::CmpOp::NE:
- return optimizer::Operations::Neq;
- case ExpressionCompare::CmpOp::GT:
- return optimizer::Operations::Gt;
- case ExpressionCompare::CmpOp::GTE:
- return optimizer::Operations::Gte;
- case ExpressionCompare::CmpOp::LT:
- return optimizer::Operations::Lt;
- case ExpressionCompare::CmpOp::LTE:
- return optimizer::Operations::Lte;
- case ExpressionCompare::CmpOp::CMP:
- return optimizer::Operations::Cmp3w;
- }
- MONGO_UNREACHABLE;
- }();
-
- // We use the "cmp3w" primitive for every comparison, because it "type brackets" its
- // comparisons (for example, a number will always compare as less than a string). The
- // other comparison primitives are designed for comparing values of the same type.
- auto cmp3w =
- optimizer::make<optimizer::BinaryOp>(optimizer::Operations::Cmp3w,
- optimizer::make<optimizer::Variable>(lhsRef),
- optimizer::make<optimizer::Variable>(rhsRef));
- auto cmp = (comparisonOperator == optimizer::Operations::Cmp3w)
- ? std::move(cmp3w)
- : optimizer::make<optimizer::BinaryOp>(
- comparisonOperator, std::move(cmp3w), optimizer::Constant::int32(0));
-
- // If either operand evaluates to "Nothing", then the entire operation expressed by
- // 'cmp' will also evaluate to "Nothing". MQL comparisons, however, treat "Nothing" as
- // if it is a value that is less than everything other than MinKey. (Notably, two
- // expressions that evaluate to "Nothing" are considered equal to each other.) We also
- // need to explicitly check for 'bsonUndefined' type because it is considered equal to
- // "Nothing" according to MQL semantics.
- auto generateExists = [&](const optimizer::ProjectionName& var) {
- auto undefinedTypeMask = static_cast<int32_t>(getBSONTypeMask(BSONType::Undefined));
- return optimizer::make<optimizer::BinaryOp>(
- optimizer::Operations::And,
- makeABTFunction("exists"_sd, optimizer::make<optimizer::Variable>(var)),
- makeABTFunction("typeMatch"_sd,
- optimizer::make<optimizer::Variable>(var),
- optimizer::Constant::int32(~undefinedTypeMask)));
- };
-
- auto nothingFallbackCmp = optimizer::make<optimizer::BinaryOp>(
- comparisonOperator, generateExists(lhsRef), generateExists(rhsRef));
-
- auto cmpWithFallback = optimizer::make<optimizer::BinaryOp>(
- optimizer::Operations::FillEmpty, std::move(cmp), std::move(nothingFallbackCmp));
-
- _context->pushExpr(optimizer::make<optimizer::Let>(
- lhsRef, lhs, optimizer::make<optimizer::Let>(rhsRef, rhs, cmpWithFallback)));
-
- return;
- }
- // Fallback to generate an SBE EExpression node.
-
sbe::EExpression::Vector operands(2);
for (auto it = operands.rbegin(); it != operands.rend(); ++it) {
*it = _context->popExpr();
@@ -2024,10 +1844,8 @@ public:
expr->getFieldPath().getPathLength() != 1 && !expr->isVariableReference());
if (auto optionalSlot = it->second.getSlot(); optionalSlot) {
_context->pushExpr(*optionalSlot);
- } else if (it->second.hasABT()) {
- _context->pushExpr(it->second.extractABT(_context->state.slotVarMap));
} else {
- auto preGeneratedExpr = it->second.extractExpr(_context->state.slotVarMap);
+ auto preGeneratedExpr = it->second.extractExpr();
_context->pushExpr(preGeneratedExpr->clone());
it->second = std::move(preGeneratedExpr);
}
@@ -2055,7 +1873,7 @@ public:
} else if (expr->getVariableId() == Variables::kRemoveId) {
// For the field paths that begin with "$$REMOVE", we always produce Nothing,
// so no traversal is necessary.
- _context->pushExpr(optimizer::Constant::nothing());
+ _context->pushExpr(sbe::makeE<sbe::EConstant>(sbe::value::TypeTags::Nothing, 0));
return;
} else {
auto it = Variables::kIdToBuiltinVarName.find(expr->getVariableId());
@@ -2094,24 +1912,13 @@ public:
!inputExpr.isNull() || topLevelFieldSlot.has_value());
// Dereference a dotted path, which may contain arrays requiring implicit traversal.
- if (inputExpr.hasExpr()) {
- auto resultExpr = generateTraverse(inputExpr.extractExpr(_context->state.slotVarMap),
- expectsDocumentInputOnly,
- *fp,
- _context->state.frameIdGenerator,
- topLevelFieldSlot);
-
- _context->pushExpr(std::move(resultExpr));
- } else {
- auto resultExpr = generateTraverse(_context,
- inputExpr.extractABT(_context->state.slotVarMap),
- expectsDocumentInputOnly,
- *fp,
- _context->state.frameIdGenerator,
- topLevelFieldSlot);
-
- _context->pushExpr(std::move(resultExpr));
- }
+ auto resultExpr = generateTraverse(inputExpr.extractExpr(),
+ expectsDocumentInputOnly,
+ *fp,
+ _context->state.frameIdGenerator,
+ topLevelFieldSlot);
+
+ _context->pushExpr(std::move(resultExpr));
}
void visit(const ExpressionFilter* expr) final {
// Remove index tracking current child of $filter expression, since it is not used anymore.
@@ -3121,25 +2928,10 @@ private:
// Empty $and and $or always evaluate to their logical operator's identity value: true
// and false, respectively.
auto logicIdentityVal = (logicOp == sbe::EPrimBinary::logicAnd);
- _context->pushExpr(optimizer::Constant::boolean(logicIdentityVal));
- return;
- }
-
- if (_context->hasAllAbtEligibleEntries(numChildren)) {
- std::vector<optimizer::ABT> exprs;
- for (size_t i = 0; i < numChildren; ++i) {
- exprs.emplace_back(
- makeFillEmptyFalse(makeABTFunction("coerceToBool", _context->popABTExpr())));
- }
- std::reverse(exprs.begin(), exprs.end());
-
- _context->pushExpr(makeBalancedBooleanOpTree(logicOp == sbe::EPrimBinary::logicAnd
- ? optimizer::Operations::And
- : optimizer::Operations::Or,
- std::move(exprs)));
+ _context->pushExpr(sbe::makeE<sbe::EConstant>(
+ sbe::value::TypeTags::Boolean, sbe::value::bitcastFrom<bool>(logicIdentityVal)));
return;
}
- // Fallback to generate an SBE EExpression node.
std::vector<std::unique_ptr<sbe::EExpression>> exprs;
for (size_t i = 0; i < numChildren; ++i) {
diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp
index 396c3d5b903..ca050bc5fb6 100644
--- a/src/mongo/db/query/sbe_stage_builder_filter.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp
@@ -160,10 +160,9 @@ struct MatchExpressionVisitorContext {
projectCurrentExprToOutputSlot(this);
}
invariant(frame.exprsCount() == 1);
- frame.setStage(makeFilter<false>(
- frame.extractStage(),
- stateHelper.getBool(frame.popExpr().extractExpr(state.slotVarMap)),
- planNodeId));
+ frame.setStage(makeFilter<false>(frame.extractStage(),
+ stateHelper.getBool(frame.popExpr().extractExpr()),
+ planNodeId));
}
if (outputSlot && stateHelper.stateContainsValue()) {
@@ -226,11 +225,8 @@ struct MatchExpressionVisitorContext {
void projectCurrentExprToOutputSlot(MatchExpressionVisitorContext* context) {
tassert(5291405, "Output slot is not empty", !context->outputSlot);
auto& frame = context->evalStack.topFrame();
- auto [projectedExprSlot, stage] = projectEvalExpr(frame.popExpr(),
- frame.extractStage(),
- context->planNodeId,
- context->state.slotIdGenerator,
- context->state.slotVarMap);
+ auto [projectedExprSlot, stage] = projectEvalExpr(
+ frame.popExpr(), frame.extractStage(), context->planNodeId, context->state.slotIdGenerator);
context->outputSlot = projectedExprSlot;
frame.pushExpr(projectedExprSlot);
frame.setStage(std::move(stage));
@@ -411,7 +407,6 @@ EvalExprStagePair generatePathTraversal(EvalStage inputStage,
PlanNodeId planNodeId,
sbe::value::SlotIdGenerator* slotIdGenerator,
sbe::value::FrameIdGenerator* frameIdGenerator,
- optimizer::SlotVarMap& varSlotMap,
const MakePredicateFn& makePredicate,
LeafTraversalMode mode,
const FilterStateHelper& stateHelper) {
@@ -557,8 +552,7 @@ EvalExprStagePair generatePathTraversal(EvalStage inputStage,
std::tie(innerExpr, innerBranch) = isLeafField
// Base case: Evaluate the predicate. Predicate returns boolean value, we need to convert it
// to state using 'stateHelper.makePredicateCombinator'.
- ? stateHelper.makePredicateCombinator(makePredicate(innerInputSlot, std::move(innerBranch)),
- varSlotMap)
+ ? stateHelper.makePredicateCombinator(makePredicate(innerInputSlot, std::move(innerBranch)))
// Recursive case.
: generatePathTraversal(std::move(innerBranch),
innerInputSlot,
@@ -568,7 +562,6 @@ EvalExprStagePair generatePathTraversal(EvalStage inputStage,
planNodeId,
slotIdGenerator,
frameIdGenerator,
- varSlotMap,
makePredicate,
mode,
stateHelper);
@@ -589,7 +582,7 @@ EvalExprStagePair generatePathTraversal(EvalStage inputStage,
stateHelper.makeInitialState(stateHelper.getBool(state.clone())),
state.clone());
},
- innerExpr.extractExpr(varSlotMap));
+ innerExpr.extractExpr());
}
sbe::value::SlotId innerResultSlot;
@@ -597,8 +590,7 @@ EvalExprStagePair generatePathTraversal(EvalStage inputStage,
projectEvalExpr(std::move(innerExpr),
std::move(innerBranch), // NOLINT(bugprone-use-after-move)
planNodeId,
- slotIdGenerator,
- varSlotMap);
+ slotIdGenerator);
// Generate the traverse stage for the current nested level. There are several cases covered
// during this phase:
@@ -709,8 +701,7 @@ void generatePredicateImpl(MatchExpressionVisitorContext* context,
// slot" that holds the value of the ElemMatchValueMatchExpression's field path.
auto result = makePredicate(*frame.data().inputSlot, frame.extractStage());
if (useCombinator) {
- return context->stateHelper.makePredicateCombinator(std::move(result),
- context->state.slotVarMap);
+ return context->stateHelper.makePredicateCombinator(std::move(result));
}
return result;
}
@@ -729,8 +720,7 @@ void generatePredicateImpl(MatchExpressionVisitorContext* context,
// we can just evaluate the predicate on the slot directly and return.
auto result = makePredicate(*slot, frame.extractStage());
if (useCombinator) {
- return context->stateHelper.makePredicateCombinator(
- std::move(result), context->state.slotVarMap);
+ return context->stateHelper.makePredicateCombinator(std::move(result));
}
return result;
}
@@ -772,7 +762,6 @@ void generatePredicateImpl(MatchExpressionVisitorContext* context,
context->planNodeId,
context->state.slotIdGenerator,
context->state.frameIdGenerator,
- context->state.slotVarMap,
makePredicate,
mode,
context->stateHelper);
@@ -857,8 +846,7 @@ void generateComparison(MatchExpressionVisitorContext* context,
sbe::EPrimBinary::Op binaryOp) {
auto makePredicateExpr =
[context, expr, binaryOp](const sbe::EVariable& var) -> std::unique_ptr<sbe::EExpression> {
- return generateComparisonExpr(context->state, expr, binaryOp, var)
- .extractExpr(context->state.slotVarMap);
+ return generateComparisonExpr(context->state, expr, binaryOp, var).extractExpr();
};
// A 'kArrayAndItsElements' traversal mode matches the following semantics: when the path we are
@@ -899,8 +887,7 @@ void generateBitTest(MatchExpressionVisitorContext* context,
const sbe::BitTestBehavior& bitOp) {
auto makePredicateExpr =
[context, expr, bitOp](const sbe::EVariable& var) -> std::unique_ptr<sbe::EExpression> {
- return generateBitTestExpr(context->state, expr, bitOp, var)
- .extractExpr(context->state.slotVarMap);
+ return generateBitTestExpr(context->state, expr, bitOp, var).extractExpr();
};
generatePredicateExpr(
@@ -950,7 +937,6 @@ void buildLogicalExpression(sbe::EPrimBinary::Op op,
std::move(branches),
context->planNodeId,
context->state.slotIdGenerator,
- context->state.slotVarMap,
context->stateHelper);
frame.pushExpr(std::move(expr));
@@ -1262,8 +1248,7 @@ public:
invariant(frame.exprsCount() > 0);
frame.setStage(
makeFilter<false>(frame.extractStage(),
- _context->stateHelper.getBool(
- frame.popExpr().extractExpr(_context->state.slotVarMap)),
+ _context->stateHelper.getBool(frame.popExpr().extractExpr()),
_context->planNodeId));
}
return;
@@ -1304,8 +1289,7 @@ public:
auto [predicateSlot, predicateStage] = projectEvalExpr(std::move(expr),
std::move(stage),
_context->planNodeId,
- _context->state.slotIdGenerator,
- _context->state.slotVarMap);
+ _context->state.slotIdGenerator);
auto isObjectOrArrayExpr =
makeBinaryOp(sbe::EPrimBinary::logicOr,
@@ -1363,14 +1347,12 @@ public:
std::move(childStages),
_context->planNodeId,
_context->state.slotIdGenerator,
- _context->state.slotVarMap,
_context->stateHelper);
auto filterPair = projectEvalExpr(std::move(filterExpr),
std::move(filterStage),
_context->planNodeId,
- _context->state.slotIdGenerator,
- _context->state.slotVarMap);
+ _context->state.slotIdGenerator);
// We're using 'kDoNotTraverseLeaf' traverse mode, so we're guaranteed that 'makePredcate'
// will only be called once, so it's safe to bind the reference to 'filterStage' subtree
@@ -1440,8 +1422,7 @@ public:
_context->slots);
// We need to convert the result of the '{$expr: ..}' expression to a boolean value.
- auto logicExpr = makeFillEmptyFalse(
- makeFunction("coerceToBool", expr.extractExpr(_context->state.slotVarMap)));
+ auto logicExpr = makeFillEmptyFalse(makeFunction("coerceToBool", expr.extractExpr()));
frame.pushExpr(_context->stateHelper.makeState(std::move(logicExpr)));
}
@@ -1609,8 +1590,7 @@ public:
auto makePredicateExpr =
[context = _context,
expr](const sbe::EVariable& var) -> std::unique_ptr<sbe::EExpression> {
- return generateModExpr(context->state, expr, var)
- .extractExpr(context->state.slotVarMap);
+ return generateModExpr(context->state, expr, var).extractExpr();
};
generatePredicateExpr(
@@ -1627,8 +1607,8 @@ public:
// This matches the behaviour of classic engine, which does not pass 'MatchDetails' object
// to children of NOR and thus does not get any information on 'elemMatchKey' from them.
auto& frame = _context->evalStack.topFrame();
- frame.pushExpr(_context->stateHelper.makeState(makeNot(_context->stateHelper.getBool(
- frame.popExpr().extractExpr(_context->state.slotVarMap)))));
+ frame.pushExpr(_context->stateHelper.makeState(
+ makeNot(_context->stateHelper.getBool(frame.popExpr().extractExpr()))));
}
void visit(const NotMatchExpression* expr) final {
@@ -1638,8 +1618,8 @@ public:
// Here we discard the index value of the state even if it was set by expressions below NOT.
// This matches the behaviour of classic engine, which does not pass 'MatchDetails' object
// to children of NOT and thus does not get any information on 'elemMatchKey' from them.
- frame.pushExpr(_context->stateHelper.makeState(makeNot(_context->stateHelper.getBool(
- frame.popExpr().extractExpr(_context->state.slotVarMap)))));
+ frame.pushExpr(_context->stateHelper.makeState(
+ makeNot(_context->stateHelper.getBool(frame.popExpr().extractExpr()))));
}
void visit(const OrMatchExpression* expr) final {
@@ -1650,8 +1630,7 @@ public:
auto makePredicateExpr =
[context = _context,
expr](const sbe::EVariable& var) -> std::unique_ptr<sbe::EExpression> {
- return generateRegexExpr(context->state, expr, var)
- .extractExpr(context->state.slotVarMap);
+ return generateRegexExpr(context->state, expr, var).extractExpr();
};
generatePredicateExpr(
@@ -1719,8 +1698,7 @@ public:
auto& frame = _context->evalStack.topFrame();
auto resultExpr =
generateWhereExpr(_context->state, expr, sbe::EVariable{*frame.data().inputSlot});
- frame.pushExpr(
- _context->stateHelper.makeState(resultExpr.extractExpr(_context->state.slotVarMap)));
+ frame.pushExpr(_context->stateHelper.makeState(resultExpr.extractExpr()));
}
void visit(const WhereNoOpMatchExpression* expr) final {}
@@ -1747,8 +1725,7 @@ public:
invariant(frame.exprsCount() > 0);
frame.setStage(
makeFilter<false>(frame.extractStage(),
- _context->stateHelper.getBool(
- frame.popExpr().extractExpr(_context->state.slotVarMap)),
+ _context->stateHelper.getBool(frame.popExpr().extractExpr()),
_context->planNodeId));
return;
}
diff --git a/src/mongo/db/query/sbe_stage_builder_helpers.cpp b/src/mongo/db/query/sbe_stage_builder_helpers.cpp
index 68652223cf1..188ab751c1e 100644
--- a/src/mongo/db/query/sbe_stage_builder_helpers.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_helpers.cpp
@@ -49,8 +49,6 @@
#include "mongo/db/exec/sbe/values/bson.h"
#include "mongo/db/index/index_access_method.h"
#include "mongo/db/matcher/matcher_type_set.h"
-#include "mongo/db/query/optimizer/rewrites/const_eval.h"
-#include "mongo/db/query/optimizer/rewrites/path_lower.h"
#include "mongo/db/query/sbe_stage_builder.h"
#include "mongo/db/storage/execution_context.h"
#include "mongo/logv2/log.h"
@@ -322,8 +320,7 @@ std::pair<sbe::value::SlotId, EvalStage> projectEvalExpr(
EvalExpr expr,
EvalStage stage,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap) {
+ sbe::value::SlotIdGenerator* slotIdGenerator) {
// If expr's value is already in a slot, return the slot.
if (expr.hasSlot()) {
return {*expr.getSlot(), std::move(stage)};
@@ -332,7 +329,7 @@ std::pair<sbe::value::SlotId, EvalStage> projectEvalExpr(
// If expr's value is an expression, create a ProjectStage to evaluate the expression
// into a slot.
auto slot = slotIdGenerator->generate();
- stage = makeProject(std::move(stage), planNodeId, slot, expr.extractExpr(slotVarMap));
+ stage = makeProject(std::move(stage), planNodeId, slot, expr.extractExpr());
return {slot, std::move(stage)};
}
@@ -540,8 +537,7 @@ std::unique_ptr<sbe::EExpression> makeIfNullExpr(
EvalExprStagePair generateUnion(std::vector<EvalExprStagePair> branches,
BranchFn branchFn,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap) {
+ sbe::value::SlotIdGenerator* slotIdGenerator) {
sbe::PlanStage::Vector stages;
std::vector<sbe::value::SlotVector> inputs;
stages.reserve(branches.size());
@@ -553,11 +549,10 @@ EvalExprStagePair generateUnion(std::vector<EvalExprStagePair> branches,
if (!branchFn || i + 1 == branches.size()) {
return projectEvalExpr(
- std::move(expr), std::move(stage), planNodeId, slotIdGenerator, slotVarMap);
+ std::move(expr), std::move(stage), planNodeId, slotIdGenerator);
}
- return branchFn(
- std::move(expr), std::move(stage), planNodeId, slotIdGenerator, slotVarMap);
+ return branchFn(std::move(expr), std::move(stage), planNodeId, slotIdGenerator);
}();
stages.emplace_back(stage.extractStage(planNodeId));
@@ -575,35 +570,14 @@ EvalExprStagePair generateUnion(std::vector<EvalExprStagePair> branches,
EvalExprStagePair generateSingleResultUnion(std::vector<EvalExprStagePair> branches,
BranchFn branchFn,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap) {
- auto [unionEvalExpr, unionEvalStage] = generateUnion(
- std::move(branches), std::move(branchFn), planNodeId, slotIdGenerator, slotVarMap);
+ sbe::value::SlotIdGenerator* slotIdGenerator) {
+ auto [unionEvalExpr, unionEvalStage] =
+ generateUnion(std::move(branches), std::move(branchFn), planNodeId, slotIdGenerator);
return {std::move(unionEvalExpr),
EvalStage{makeLimitTree(unionEvalStage.extractStage(planNodeId), planNodeId),
unionEvalStage.extractOutSlots()}};
}
-optimizer::ABT makeBalancedBooleanOpTreeImpl(optimizer::Operations logicOp,
- std::vector<optimizer::ABT>& leaves,
- size_t from,
- size_t until) {
- invariant(from < until);
- if (from + 1 == until) {
- return std::move(leaves[from]);
- } else {
- size_t mid = (from + until) / 2;
- auto lhs = makeBalancedBooleanOpTreeImpl(logicOp, leaves, from, mid);
- auto rhs = makeBalancedBooleanOpTreeImpl(logicOp, leaves, mid, until);
- return optimizer::make<optimizer::BinaryOp>(logicOp, std::move(lhs), std::move(rhs));
- }
-}
-
-optimizer::ABT makeBalancedBooleanOpTree(optimizer::Operations logicOp,
- std::vector<optimizer::ABT> leaves) {
- return makeBalancedBooleanOpTreeImpl(logicOp, leaves, 0, leaves.size());
-}
-
std::unique_ptr<sbe::EExpression> makeBalancedBooleanOpTreeImpl(
sbe::EPrimBinary::Op logicOp,
std::vector<std::unique_ptr<sbe::EExpression>>& leaves,
@@ -629,7 +603,6 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp,
std::vector<EvalExprStagePair> branches,
PlanNodeId planNodeId,
sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap,
const FilterStateHelper& stateHelper) {
invariant(logicOp == sbe::EPrimBinary::logicAnd || logicOp == sbe::EPrimBinary::logicOr);
@@ -639,11 +612,7 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp,
// NOTE: There is no technical reason for that. We could support index tracking for OR
// expression, but this would differ from the existing behaviour.
auto& [expr, _] = branches.back();
- if (expr.hasExpr()) {
- expr = stateHelper.makeState(stateHelper.getBool(expr.extractExpr(slotVarMap)));
- } else {
- expr = stateHelper.makeState(stateHelper.getBool(expr.extractABT(slotVarMap)));
- }
+ expr = stateHelper.makeState(stateHelper.getBool(expr.extractExpr()));
}
// For AND and OR, if 'branches' only has one element, we can just return branches[0].
@@ -651,34 +620,20 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp,
return std::move(branches[0]);
}
- bool exprOnlyBranches = true, allAbtEligibleBranches = true;
+ bool exprOnlyBranches = true;
for (const auto& [expr, stage] : branches) {
- exprOnlyBranches &= stage.isNull();
- allAbtEligibleBranches &= expr.hasABT() || expr.hasSlot();
+ if (!stage.isNull()) {
+ exprOnlyBranches = false;
+ break;
+ }
}
if (exprOnlyBranches) {
- if (allAbtEligibleBranches) {
- std::vector<optimizer::ABT> leaves;
- leaves.reserve(branches.size());
- for (auto& branch : branches) {
- auto& [expr, _] = branch;
- leaves.emplace_back(stateHelper.getBool(expr.extractABT(slotVarMap)));
- }
- // Create the balanced binary tree to keep the tree shallow and safe for recursion.
- auto exprOnlyOp = makeBalancedBooleanOpTree(logicOp == sbe::EPrimBinary::logicAnd
- ? optimizer::Operations::And
- : optimizer::Operations::Or,
- std::move(leaves));
- return {EvalExpr{std::move(exprOnlyOp)}, EvalStage{}};
- }
- // Fallback to generate an SBE EExpression node.
-
std::vector<std::unique_ptr<sbe::EExpression>> leaves;
leaves.reserve(branches.size());
for (auto& branch : branches) {
auto& [expr, _] = branch;
- leaves.push_back(stateHelper.getBool(expr.extractExpr(slotVarMap)));
+ leaves.push_back(stateHelper.getBool(expr.extractExpr()));
}
// Create the balanced binary tree to keep the tree shallow and safe for recursion.
auto exprOnlyOp = makeBalancedBooleanOpTree(logicOp, std::move(leaves));
@@ -695,8 +650,7 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp,
auto branchFn = [logicOp, &stateHelper](EvalExpr expr,
EvalStage stage,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap) {
+ sbe::value::SlotIdGenerator* slotIdGenerator) {
// Create a FilterStage for each branch (except the last one). If a branch's filter
// condition is true, it will "short-circuit" the evaluation process. For AND, short-
// circuiting should happen if an operand evalautes to false. For OR, short-circuiting
@@ -704,7 +658,7 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp,
// Set up an output value to be returned if short-circuiting occurs. For AND, when
// short-circuiting occurs, the output returned should be false. For OR, when short-
// circuiting occurs, the output returned should be true.
- auto filterExpr = stateHelper.getBool(expr.extractExpr(slotVarMap));
+ auto filterExpr = stateHelper.getBool(expr.extractExpr());
if (logicOp == sbe::EPrimBinary::logicAnd) {
filterExpr = makeNot(std::move(filterExpr));
}
@@ -717,8 +671,7 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp,
return std::make_pair(resultSlot, std::move(stage));
};
- return generateSingleResultUnion(
- std::move(branches), branchFn, planNodeId, slotIdGenerator, slotVarMap);
+ return generateSingleResultUnion(std::move(branches), branchFn, planNodeId, slotIdGenerator);
}
std::pair<sbe::value::SlotId, std::unique_ptr<sbe::PlanStage>> generateVirtualScan(
@@ -1315,7 +1268,6 @@ std::pair<std::unique_ptr<sbe::PlanStage>, sbe::value::SlotVector> projectFields
sbe::value::SlotId resultSlot,
PlanNodeId nodeId,
sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap,
const PlanStageSlots* slots) {
// 'outputSlots' will match the order of 'fields'. Bail out early if 'fields' is empty.
auto outputSlots = sbe::makeSV();
@@ -1415,7 +1367,7 @@ std::pair<std::unique_ptr<sbe::PlanStage>, sbe::value::SlotVector> projectFields
auto getFieldExpr =
makeFunction("getField"_sd,
parent->value.hasSlot() ? makeVariable(*parent->value.getSlot())
- : parent->value.extractExpr(slotVarMap),
+ : parent->value.extractExpr(),
makeConstant(node->name));
auto hasOneChildToVisit = [&] {
@@ -1472,44 +1424,4 @@ std::pair<std::unique_ptr<sbe::PlanStage>, sbe::value::SlotVector> projectFields
return {std::move(stage), std::move(outputSlots)};
}
-
-std::unique_ptr<sbe::EExpression> abtToExpr(optimizer::ABT& abt, optimizer::SlotVarMap& slotMap) {
- auto env = optimizer::VariableEnvironment::build(abt);
-
- // Do not use descriptive names here.
- auto prefixId = optimizer::PrefixId::create(false /*useDescriptiveNames*/);
- // Convert paths into ABT expressions.
- optimizer::EvalPathLowering pathLower{prefixId, env};
- pathLower.optimize(abt);
-
- // Run the constant folding to eliminate lambda applications as they are not directly
- // supported by the SBE VM.
- optimizer::ConstEval constEval{env};
- constEval.optimize(abt);
-
- // And finally convert to the SBE expression.
- optimizer::SBEExpressionLowering exprLower{env, slotMap};
- return exprLower.optimize(abt);
-}
-
-optimizer::ABT makeFillEmptyFalse(optimizer::ABT e) {
- using namespace std::literals;
- return optimizer::make<optimizer::BinaryOp>(
- optimizer::Operations::FillEmpty, std::move(e), optimizer::Constant::boolean(false));
-}
-
-optimizer::ProjectionName makeVariableName(sbe::value::SlotId slotId) {
- // Use a naming scheme that reduces that chances of clashing into a user-created variable name.
- str::stream varName;
- varName << "__s" << slotId;
- return optimizer::ProjectionName{varName};
-}
-
-optimizer::ProjectionName makeLocalVariableName(sbe::FrameId frameId, sbe::value::SlotId slotId) {
- // Use a naming scheme that reduces that chances of clashing into a user-created variable name.
- str::stream varName;
- varName << "__l" << frameId << "." << slotId;
- return optimizer::ProjectionName{varName};
-}
-
} // namespace mongo::stage_builder
diff --git a/src/mongo/db/query/sbe_stage_builder_helpers.h b/src/mongo/db/query/sbe_stage_builder_helpers.h
index 1958e3988c6..e1be0c29f26 100644
--- a/src/mongo/db/query/sbe_stage_builder_helpers.h
+++ b/src/mongo/db/query/sbe_stage_builder_helpers.h
@@ -34,7 +34,6 @@
#include <string>
#include <utility>
-#include "mongo/db/exec/sbe/abt/abt_lower.h"
#include "mongo/db/exec/sbe/expressions/expression.h"
#include "mongo/db/exec/sbe/match_path.h"
#include "mongo/db/exec/sbe/stages/filter.h"
@@ -339,8 +338,7 @@ std::pair<sbe::value::SlotId, EvalStage> projectEvalExpr(
EvalExpr expr,
EvalStage stage,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap);
+ sbe::value::SlotIdGenerator* slotIdGenerator);
template <bool IsConst, bool IsEof = false>
EvalStage makeFilter(EvalStage stage,
@@ -440,8 +438,7 @@ using BranchFn = std::function<std::pair<sbe::value::SlotId, EvalStage>(
EvalExpr expr,
EvalStage stage,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap)>;
+ sbe::value::SlotIdGenerator* slotIdGenerator)>;
/**
* Creates a chain of EIf expressions that will inspect each arg in order and return the first
@@ -458,8 +455,7 @@ std::unique_ptr<sbe::EExpression> makeIfNullExpr(
EvalExprStagePair generateUnion(std::vector<EvalExprStagePair> branches,
BranchFn branchFn,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap);
+ sbe::value::SlotIdGenerator* slotIdGenerator);
/**
* Creates limit-1/union stage with specified branches. Each branch is passed to 'branchFn' first.
* If 'branchFn' is not set, expression from branch is simply projected to a slot.
@@ -467,8 +463,7 @@ EvalExprStagePair generateUnion(std::vector<EvalExprStagePair> branches,
EvalExprStagePair generateSingleResultUnion(std::vector<EvalExprStagePair> branches,
BranchFn branchFn,
PlanNodeId planNodeId,
- sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap);
+ sbe::value::SlotIdGenerator* slotIdGenerator);
/** This helper takes an SBE SlotIdGenerator and an SBE Array and returns an output slot and a
* unwind/project/limit/coscan subtree that streams out the elements of the array one at a time via
@@ -590,7 +585,6 @@ public:
* value. Index part of the constructed state is empty.
*/
virtual Expression makeState(Expression expr) const = 0;
- virtual optimizer::ABT makeState(optimizer::ABT expr) const = 0;
/**
* Creates an expression that constructs an initial state from 'expr'. 'expr' must evaluate to a
@@ -604,7 +598,6 @@ public:
* Creates an expression that extracts boolean value from the state evaluated from 'expr'.
*/
virtual Expression getBool(Expression expr) const = 0;
- virtual optimizer::ABT getBool(optimizer::ABT expr) const = 0;
Expression getBool(sbe::value::SlotId slotId) const {
return getBool(sbe::makeE<sbe::EVariable>(slotId));
@@ -634,8 +627,7 @@ public:
* Uses an expression from 'EvalExprStagePair' to construct state. Expresion must evaluate to
* boolean value.
*/
- virtual EvalExprStagePair makePredicateCombinator(EvalExprStagePair pair,
- optimizer::SlotVarMap& varMap) const = 0;
+ virtual EvalExprStagePair makePredicateCombinator(EvalExprStagePair pair) const = 0;
/**
* Creates traverse stage with fold and final expressions tuned to maintain consistent state.
@@ -686,11 +678,6 @@ public:
return sbe::makeE<sbe::EIf>(std::move(expr), makeState(true), makeState(false));
}
- optimizer::ABT makeState(optimizer::ABT expr) const override {
- return optimizer::make<optimizer::If>(
- std::move(expr), optimizer::Constant::int64(0), optimizer::Constant::int64(-1));
- }
-
Expression makeInitialState(Expression expr) const override {
return sbe::makeE<sbe::EIf>(
std::move(expr), makeConstant(ValueType, 1), makeConstant(ValueType, -2));
@@ -701,11 +688,6 @@ public:
sbe::EPrimBinary::greaterEq, std::move(expr), makeConstant(ValueType, 0));
}
- optimizer::ABT getBool(optimizer::ABT expr) const override {
- return optimizer::make<optimizer::BinaryOp>(
- optimizer::Operations::Gte, std::move(expr), optimizer::Constant::int64(0));
- }
-
Expression mergeStates(Expression left,
Expression right,
sbe::value::FrameIdGenerator* frameIdGenerator) const override {
@@ -753,10 +735,9 @@ public:
return {indexSlot, std::move(resultStage)};
}
- EvalExprStagePair makePredicateCombinator(EvalExprStagePair pair,
- optimizer::SlotVarMap& varMap) const override {
+ EvalExprStagePair makePredicateCombinator(EvalExprStagePair pair) const override {
auto [expr, stage] = std::move(pair);
- return {makeState(expr.extractExpr(varMap)), std::move(stage)};
+ return {makeState(expr.extractExpr()), std::move(stage)};
}
EvalStage makeTraverseCombinator(EvalStage outer,
@@ -786,10 +767,6 @@ public:
return expr;
}
- optimizer::ABT makeState(optimizer::ABT expr) const override {
- return expr;
- }
-
Expression makeInitialState(Expression expr) const override {
return expr;
}
@@ -798,10 +775,6 @@ public:
return expr;
}
- optimizer::ABT getBool(optimizer::ABT expr) const override {
- return expr;
- }
-
Expression mergeStates(Expression left,
Expression right,
sbe::value::FrameIdGenerator* frameIdGenerator) const override {
@@ -818,8 +791,7 @@ public:
return {stateSlot, std::move(stage)};
}
- EvalExprStagePair makePredicateCombinator(EvalExprStagePair pair,
- optimizer::SlotVarMap& varMap) const override {
+ EvalExprStagePair makePredicateCombinator(EvalExprStagePair pair) const override {
return pair;
}
@@ -866,7 +838,6 @@ EvalExprStagePair generateShortCircuitingLogicalOp(sbe::EPrimBinary::Op logicOp,
std::vector<EvalExprStagePair> branches,
PlanNodeId planNodeId,
sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap,
const FilterStateHelper& stateHelper);
/**
@@ -965,9 +936,6 @@ struct StageBuilderState {
// corresponding to field paths to 'generateExpression' to avoid repeated expression generation.
// Key is expected to represent field paths in form CURRENT.<field_name>[.<field_name>]*.
stdx::unordered_map<std::string /*field path*/, EvalExpr> preGeneratedExprs;
-
- // Holds the mapping between the custom ABT variable names and the slot id they are referencing.
- optimizer::SlotVarMap slotVarMap;
};
/**
@@ -1442,7 +1410,6 @@ std::pair<std::unique_ptr<sbe::PlanStage>, sbe::value::SlotVector> projectFields
sbe::value::SlotId resultSlot,
PlanNodeId nodeId,
sbe::value::SlotIdGenerator* slotIdGenerator,
- optimizer::SlotVarMap& slotVarMap,
const PlanStageSlots* slots = nullptr);
template <typename T>
@@ -1514,38 +1481,4 @@ inline std::vector<T> appendVectorUnique(std::vector<T> lhs, std::vector<T> rhs)
}
return lhs;
}
-
-std::unique_ptr<sbe::EExpression> abtToExpr(optimizer::ABT& abt, optimizer::SlotVarMap& slotMap);
-
-template <typename... Args>
-inline auto makeABTFunction(StringData name, Args&&... args) {
- return optimizer::make<optimizer::FunctionCall>(
- name.toString(), optimizer::makeSeq(std::forward<Args>(args)...));
-}
-
-template <typename T>
-inline auto makeABTConstant(sbe::value::TypeTags tag, T value) {
- return optimizer::make<optimizer::Constant>(tag, sbe::value::bitcastFrom<T>(value));
-}
-
-inline auto makeABTConstant(StringData str) {
- auto [tag, value] = sbe::value::makeNewString(str);
- return makeABTConstant(tag, value);
-}
-
-/**
- * Creates a balanced boolean binary expression tree from given collection of leaf expression.
- */
-optimizer::ABT makeBalancedBooleanOpTree(optimizer::Operations logicOp,
- std::vector<optimizer::ABT> leaves);
-
-/**
- * Check if expression returns Nothing and return boolean false if so. Otherwise, return the
- * expression.
- */
-optimizer::ABT makeFillEmptyFalse(optimizer::ABT e);
-
-optimizer::ProjectionName makeVariableName(sbe::value::SlotId slotId);
-optimizer::ProjectionName makeLocalVariableName(sbe::FrameId frameId, sbe::value::SlotId slotId);
-
} // namespace mongo::stage_builder
diff --git a/src/mongo/db/query/sbe_stage_builder_projection.cpp b/src/mongo/db/query/sbe_stage_builder_projection.cpp
index 28c447022d3..8a5ce212c96 100644
--- a/src/mongo/db/query/sbe_stage_builder_projection.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_projection.cpp
@@ -84,17 +84,16 @@ struct ProjectionTraversalVisitorContext {
EvalExpr getInputEvalExpr() const {
return inputExpr.clone();
}
-
- std::unique_ptr<sbe::EExpression> getInputExpr(optimizer::SlotVarMap& slotVarMap) const {
- return getInputEvalExpr().extractExpr(slotVarMap);
+ std::unique_ptr<sbe::EExpression> getInputExpr() const {
+ return getInputEvalExpr().extractExpr();
}
EvalExpr extractInputEvalExpr() {
return std::move(inputExpr);
}
- std::unique_ptr<sbe::EExpression> extractInputExpr(optimizer::SlotVarMap& slotVarMap) {
+ std::unique_ptr<sbe::EExpression> extractInputExpr() {
auto evalExpr = extractInputEvalExpr();
- return evalExpr.extractExpr(slotVarMap);
+ return evalExpr.extractExpr();
}
// The input expression for the current level. This is the parent sub-document for each of
@@ -375,7 +374,7 @@ public:
auto lambdaFrame = _context->topLevel().lambdaFrame;
tassert(6897005, "Expected lambda frame to be set", lambdaFrame);
- auto childInputExpr = _context->topLevel().extractInputExpr(_context->state.slotVarMap);
+ auto childInputExpr = _context->topLevel().extractInputExpr();
const bool containsComputedField = _context->topLevel().subtreeContainsComputedField;
@@ -395,7 +394,7 @@ public:
auto args = sbe::makeEs(std::move(makeObjSpecExpr), childInputExpr->clone());
for (auto& expr : projectExprs) {
- args.push_back(expr.extractExpr(_context->state.slotVarMap));
+ args.push_back(expr.extractExpr());
}
auto innerExpr = sbe::makeE<sbe::EFunction>("makeBsonObj", std::move(args));
@@ -425,7 +424,7 @@ public:
auto fromExpr = [&]() {
if (_context->isLastLevel()) {
- return _context->topLevel().getInputExpr(_context->state.slotVarMap);
+ return _context->topLevel().getInputExpr();
}
if (_context->numLevels() == 2 && _context->slots) {
auto name =
@@ -435,7 +434,7 @@ public:
}
}
return makeFunction("getField"_sd,
- _context->topLevel().getInputExpr(_context->state.slotVarMap),
+ _context->topLevel().getInputExpr(),
makeConstant(_context->topFrontField()));
}();
@@ -521,7 +520,7 @@ public:
auto lambdaFrame = _context->topLevel().lambdaFrame;
tassert(6929406, "Expected lambda frame to be set", lambdaFrame);
- auto childInputExpr = _context->topLevel().extractInputExpr(_context->state.slotVarMap);
+ auto childInputExpr = _context->topLevel().extractInputExpr();
// We've finished extracting what we need from the child level, so pop if off the stack.
_context->popLevel();
@@ -537,7 +536,7 @@ public:
auto args = sbe::makeEs(std::move(makeObjSpecExpr), childInputExpr->clone());
for (auto& expr : projectExprs) {
- args.push_back(expr.extractExpr(_context->state.slotVarMap));
+ args.push_back(expr.extractExpr());
}
auto innerExpr = sbe::makeE<sbe::EFunction>("makeBsonObj", std::move(args));
@@ -549,7 +548,7 @@ public:
auto fromExpr = [&]() {
if (_context->isLastLevel()) {
- return _context->topLevel().getInputExpr(_context->state.slotVarMap);
+ return _context->topLevel().getInputExpr();
}
if (_context->numLevels() == 2 && _context->slots) {
auto name =
@@ -559,7 +558,7 @@ public:
}
}
return makeFunction("getField"_sd,
- _context->topLevel().getInputExpr(_context->state.slotVarMap),
+ _context->topLevel().getInputExpr(),
makeConstant(_context->topFrontField()));
}();
@@ -579,10 +578,9 @@ public:
void visit(const projection_ast::ProjectionSliceASTNode* node) final {
using namespace std::literals;
- auto arrayFromField =
- makeFunction("getField"_sd,
- _context->topLevel().getInputExpr(_context->state.slotVarMap),
- makeConstant(_context->topFrontField()));
+ auto arrayFromField = makeFunction("getField"_sd,
+ _context->topLevel().getInputExpr(),
+ makeConstant(_context->topFrontField()));
auto binds = sbe::makeEs(std::move(arrayFromField));
auto frameId = _context->state.frameId();
sbe::EVariable arrayVariable{frameId, 0};
@@ -647,7 +645,7 @@ EvalExpr generateProjection(StageBuilderState& state,
}
auto frameId = state.frameId();
- auto binds = sbe::makeEs(resultExpr.extractExpr(state.slotVarMap));
+ auto binds = sbe::makeEs(resultExpr.extractExpr());
sbe::EVariable resultRef{frameId, 0};
// $slice projectional operator has different path traversal semantics compared to other
@@ -665,7 +663,6 @@ EvalExpr generateProjection(StageBuilderState& state,
auto sliceResultExpr = sliceContext.done();
- return sbe::makeE<sbe::ELocalBind>(
- frameId, std::move(binds), sliceResultExpr.extractExpr(state.slotVarMap));
+ return sbe::makeE<sbe::ELocalBind>(frameId, std::move(binds), sliceResultExpr.extractExpr());
}
} // namespace mongo::stage_builder