summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnton Korshunov <anton.korshunov@mongodb.com>2021-01-31 00:34:57 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-02-14 15:30:07 +0000
commit0fc5b56b12dbdc248556fdfa9da2f44479eac699 (patch)
treedfac279997b20789e8c376fcf5a74fce75b15d22 /src
parent4dd10ec20b608ec364db1ba4815bbf45d73e8da4 (diff)
downloadmongo-0fc5b56b12dbdc248556fdfa9da2f44479eac699.tar.gz
SERVER-51823 Use classic engine to evaluate queries containing expressions not supported in SBE
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/matcher/expression_parser.cpp45
-rw-r--r--src/mongo/db/matcher/schema/json_schema_parser.cpp1
-rw-r--r--src/mongo/db/pipeline/expression.cpp28
-rw-r--r--src/mongo/db/pipeline/expression.h152
-rw-r--r--src/mongo/db/pipeline/expression_context.h4
-rw-r--r--src/mongo/db/pipeline/expression_function.cpp4
-rw-r--r--src/mongo/db/pipeline/expression_js_emit.cpp4
-rw-r--r--src/mongo/db/pipeline/expression_test_api_version.cpp4
-rw-r--r--src/mongo/db/query/get_executor.cpp26
-rw-r--r--src/mongo/db/query/plan_explainer_sbe.cpp95
-rw-r--r--src/mongo/db/query/sbe_stage_builder.cpp4
-rw-r--r--src/mongo/db/query/sbe_stage_builder_expression.cpp6
-rw-r--r--src/mongo/db/query/sbe_stage_builder_filter.cpp7
-rw-r--r--src/mongo/db/query/stage_types.cpp4
14 files changed, 268 insertions, 116 deletions
diff --git a/src/mongo/db/matcher/expression_parser.cpp b/src/mongo/db/matcher/expression_parser.cpp
index 7ef37bc2e02..434955fcf95 100644
--- a/src/mongo/db/matcher/expression_parser.cpp
+++ b/src/mongo/db/matcher/expression_parser.cpp
@@ -491,7 +491,6 @@ StatusWithMatchExpression parseExpr(StringData name,
if ((allowedFeatures & MatchExpressionParser::AllowedFeatures::kExpr) == 0u) {
return {Status(ErrorCodes::QueryFeatureNotAllowed, "$expr is not allowed in this context")};
}
-
return {std::make_unique<ExprMatchExpression>(
std::move(elem),
expCtx,
@@ -620,6 +619,10 @@ StatusWithMatchExpression parseType(StringData name,
str::stream() << name << " must match at least one type")};
}
+ if constexpr (std::is_same_v<T, InternalSchemaTypeExpression> ||
+ std::is_same_v<T, InternalSchemaBinDataEncryptedTypeExpression>) {
+ expCtx->sbeCompatible = false;
+ }
return {std::make_unique<T>(
name,
std::move(typeSet.getValue()),
@@ -734,7 +737,8 @@ StatusWithMatchExpression parseBitTest(StringData name,
return {std::move(bitTestMatchExpression)};
}
-StatusWithMatchExpression parseInternalSchemaFmod(StringData name, BSONElement elem) {
+StatusWithMatchExpression parseInternalSchemaFmod(
+ StringData name, BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
StringData path(name);
if (elem.type() != BSONType::Array)
return {ErrorCodes::BadValue,
@@ -763,6 +767,7 @@ StatusWithMatchExpression parseInternalSchemaFmod(StringData name, BSONElement e
return {ErrorCodes::BadValue, str::stream() << path << " has too many elements"};
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaFmodMatchExpression>(
name, d.numberDecimal(), r.numberDecimal())};
}
@@ -785,6 +790,7 @@ StatusWithMatchExpression parseInternalSchemaRootDocEq(
str::stream() << InternalSchemaRootDocEqMatchExpression::kName
<< " must be an object, found type " << elem.type())};
}
+ expCtx->sbeCompatible = false;
auto rootDocEq =
std::make_unique<InternalSchemaRootDocEqMatchExpression>(elem.embeddedObject());
return {std::move(rootDocEq)};
@@ -795,13 +801,14 @@ StatusWithMatchExpression parseInternalSchemaRootDocEq(
* of type 'T' that gets initialized with the resulting integer.
*/
template <class T>
-StatusWithMatchExpression parseInternalSchemaSingleIntegerArgument(StringData name,
- BSONElement elem) {
+StatusWithMatchExpression parseInternalSchemaSingleIntegerArgument(
+ StringData name, BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
auto parsedInt = elem.parseIntegerElementToNonNegativeLong();
if (!parsedInt.isOK()) {
return parsedInt.getStatus();
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<T>(name, parsedInt.getValue())};
}
@@ -821,6 +828,7 @@ StatusWithMatchExpression parseTopLevelInternalSchemaSingleIntegerArgument(
if (!parsedInt.isOK()) {
return parsedInt.getStatus();
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<T>(parsedInt.getValue())};
}
@@ -1055,6 +1063,7 @@ StatusWithMatchExpression parseInternalSchemaAllowedProperties(
return properties.getStatus();
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaAllowedPropertiesMatchExpression>(
std::move(properties.getValue()),
namePlaceholder.getValue(),
@@ -1110,6 +1119,7 @@ StatusWithMatchExpression parseInternalSchemaMatchArrayIndex(
return expressionWithPlaceholder.getStatus();
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaMatchArrayIndexMatchExpression>(
path, index.getValue(), std::move(expressionWithPlaceholder.getValue()))};
}
@@ -1126,6 +1136,7 @@ StatusWithMatchExpression parseGeo(StringData name,
return parseStatus;
}
auto operatorName = section.firstElementFieldName();
+ expCtx->sbeCompatible = false;
return {std::make_unique<GeoMatchExpression>(
name,
gq.release(),
@@ -1144,6 +1155,7 @@ StatusWithMatchExpression parseGeo(StringData name,
if (!status.isOK()) {
return status;
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<GeoNearMatchExpression>(name, nq.release(), section)};
}
}
@@ -1179,6 +1191,9 @@ StatusWithMatchExpression parseTreeTopLevel(
temp->add(sub.getValue().release());
}
+ if constexpr (std::is_same_v<T, InternalSchemaXorMatchExpression>) {
+ expCtx->sbeCompatible = false;
+ }
return {std::move(temp)};
}
@@ -1382,6 +1397,7 @@ StatusWithMatchExpression parseInternalSchemaFixedArityArgument(
++position;
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<T>(std::move(expressions))};
}
@@ -1428,7 +1444,8 @@ StatusWithMatchExpression parseNot(StringData name,
theAnd.release(), doc_validation_error::createAnnotation(expCtx, "$not", BSONObj()))};
}
-StatusWithMatchExpression parseInternalSchemaBinDataSubType(StringData name, BSONElement e) {
+StatusWithMatchExpression parseInternalSchemaBinDataSubType(
+ StringData name, BSONElement e, const boost::intrusive_ptr<ExpressionContext>& expCtx) {
if (!e.isNumber()) {
return Status(ErrorCodes::FailedToParse,
str::stream() << InternalSchemaBinDataSubTypeExpression::kName
@@ -1450,6 +1467,7 @@ StatusWithMatchExpression parseInternalSchemaBinDataSubType(StringData name, BSO
<< " value must represent BinData subtype: " << valueAsInt.getValue());
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaBinDataSubTypeExpression>(
name, static_cast<BinDataType>(valueAsInt.getValue()))};
}
@@ -1759,16 +1777,16 @@ StatusWithMatchExpression parseSubField(const BSONObj& context,
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_FMOD:
- return parseInternalSchemaFmod(name, e);
+ return parseInternalSchemaFmod(name, e, expCtx);
case PathAcceptingKeyword::INTERNAL_SCHEMA_MIN_ITEMS: {
return parseInternalSchemaSingleIntegerArgument<InternalSchemaMinItemsMatchExpression>(
- name, e);
+ name, e, expCtx);
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_MAX_ITEMS: {
return parseInternalSchemaSingleIntegerArgument<InternalSchemaMaxItemsMatchExpression>(
- name, e);
+ name, e, expCtx);
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_OBJECT_MATCH: {
@@ -1786,6 +1804,7 @@ StatusWithMatchExpression parseSubField(const BSONObj& context,
return parsedSubObjExpr;
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaObjectMatchExpression>(
name,
std::move(parsedSubObjExpr.getValue()),
@@ -1798,17 +1817,18 @@ StatusWithMatchExpression parseSubField(const BSONObj& context,
str::stream() << name << " must be a boolean of value true"};
}
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaUniqueItemsMatchExpression>(name)};
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_MIN_LENGTH: {
return parseInternalSchemaSingleIntegerArgument<InternalSchemaMinLengthMatchExpression>(
- name, e);
+ name, e, expCtx);
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_MAX_LENGTH: {
return parseInternalSchemaSingleIntegerArgument<InternalSchemaMaxLengthMatchExpression>(
- name, e);
+ name, e, expCtx);
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_MATCH_ARRAY_INDEX: {
@@ -1876,6 +1896,8 @@ StatusWithMatchExpression parseSubField(const BSONObj& context,
if (!exprWithPlaceholder.isOK()) {
return exprWithPlaceholder.getStatus();
}
+
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaAllElemMatchFromIndexMatchExpression>(
name, parsedIndex.getValue(), std::move(exprWithPlaceholder.getValue()))};
}
@@ -1885,6 +1907,7 @@ StatusWithMatchExpression parseSubField(const BSONObj& context,
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_EQ: {
+ expCtx->sbeCompatible = false;
return {std::make_unique<InternalSchemaEqMatchExpression>(name, e)};
}
@@ -1893,7 +1916,7 @@ StatusWithMatchExpression parseSubField(const BSONObj& context,
}
case PathAcceptingKeyword::INTERNAL_SCHEMA_BIN_DATA_SUBTYPE: {
- return parseInternalSchemaBinDataSubType(name, e);
+ return parseInternalSchemaBinDataSubType(name, e, expCtx);
}
}
diff --git a/src/mongo/db/matcher/schema/json_schema_parser.cpp b/src/mongo/db/matcher/schema/json_schema_parser.cpp
index ec980d71ebc..c972c05c602 100644
--- a/src/mongo/db/matcher/schema/json_schema_parser.cpp
+++ b/src/mongo/db/matcher/schema/json_schema_parser.cpp
@@ -1885,6 +1885,7 @@ StatusWithMatchExpression JSONSchemaParser::parse(
doc_validation_error::createAnnotation(expCtx, "$jsonSchema", oldAnnotation));
}
}
+ expCtx->sbeCompatible = false;
return translation;
} catch (const DBException& ex) {
return {ex.toStatus()};
diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp
index 545be1a8a9d..4f2e60a5db1 100644
--- a/src/mongo/db/pipeline/expression.cpp
+++ b/src/mongo/db/pipeline/expression.cpp
@@ -1438,7 +1438,9 @@ ExpressionDateFromString::ExpressionDateFromString(ExpressionContext* const expC
_timeZone(_children[1]),
_format(_children[2]),
_onNull(_children[3]),
- _onError(_children[4]) {}
+ _onError(_children[4]) {
+ expCtx->sbeCompatible = false;
+}
intrusive_ptr<Expression> ExpressionDateFromString::optimize() {
_dateString = _dateString->optimize();
@@ -1756,7 +1758,9 @@ ExpressionDateToString::ExpressionDateToString(ExpressionContext* const expCtx,
_format(_children[0]),
_date(_children[1]),
_timeZone(_children[2]),
- _onNull(_children[3]) {}
+ _onNull(_children[3]) {
+ expCtx->sbeCompatible = false;
+}
intrusive_ptr<Expression> ExpressionDateToString::optimize() {
_date = _date->optimize();
@@ -2097,7 +2101,9 @@ const char* ExpressionExp::getOpName() const {
ExpressionObject::ExpressionObject(ExpressionContext* const expCtx,
std::vector<boost::intrusive_ptr<Expression>> _children,
vector<pair<string, intrusive_ptr<Expression>&>>&& expressions)
- : Expression(expCtx, std::move(_children)), _expressions(std::move(expressions)) {}
+ : Expression(expCtx, std::move(_children)), _expressions(std::move(expressions)) {
+ expCtx->sbeCompatible = false;
+}
boost::intrusive_ptr<ExpressionObject> ExpressionObject::create(
ExpressionContext* const expCtx,
@@ -2684,7 +2690,9 @@ ExpressionMap::ExpressionMap(ExpressionContext* const expCtx,
_varName(varName),
_varId(varId),
_input(_children[0]),
- _each(_children[1]) {}
+ _each(_children[1]) {
+ expCtx->sbeCompatible = false;
+}
intrusive_ptr<Expression> ExpressionMap::optimize() {
// TODO handle when _input is constant
@@ -2821,7 +2829,9 @@ intrusive_ptr<Expression> ExpressionMeta::parse(ExpressionContext* const expCtx,
}
ExpressionMeta::ExpressionMeta(ExpressionContext* const expCtx, MetaType metaType)
- : Expression(expCtx), _metaType(metaType) {}
+ : Expression(expCtx), _metaType(metaType) {
+ expCtx->sbeCompatible = false;
+}
Value ExpressionMeta::serialize(bool explain) const {
const auto nameIter = kMetaTypeToMetaName.find(_metaType);
@@ -6101,7 +6111,9 @@ ExpressionConvert::ExpressionConvert(ExpressionContext* const expCtx,
_input(_children[0]),
_to(_children[1]),
_onError(_children[2]),
- _onNull(_children[3]) {}
+ _onNull(_children[3]) {
+ expCtx->sbeCompatible = false;
+}
intrusive_ptr<Expression> ExpressionConvert::parse(ExpressionContext* const expCtx,
BSONElement expr,
@@ -6702,7 +6714,9 @@ REGISTER_EXPRESSION(rand, ExpressionRandom::parse);
static thread_local PseudoRandom threadLocalRNG(SecureRandom().nextInt64());
-ExpressionRandom::ExpressionRandom(ExpressionContext* const expCtx) : Expression(expCtx) {}
+ExpressionRandom::ExpressionRandom(ExpressionContext* const expCtx) : Expression(expCtx) {
+ expCtx->sbeCompatible = false;
+}
intrusive_ptr<Expression> ExpressionRandom::parse(ExpressionContext* const expCtx,
BSONElement exprElement,
diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h
index b2c657b8068..ff9680769d4 100644
--- a/src/mongo/db/pipeline/expression.h
+++ b/src/mongo/db/pipeline/expression.h
@@ -433,7 +433,9 @@ class ExpressionFromAccumulator
: public ExpressionVariadic<ExpressionFromAccumulator<AccumulatorState>> {
public:
explicit ExpressionFromAccumulator(ExpressionContext* const expCtx)
- : ExpressionVariadic<ExpressionFromAccumulator<AccumulatorState>>(expCtx) {}
+ : ExpressionVariadic<ExpressionFromAccumulator<AccumulatorState>>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final {
AccumulatorState accum(this->getExpressionContext());
@@ -870,7 +872,9 @@ public:
class ExpressionArray final : public ExpressionVariadic<ExpressionArray> {
public:
explicit ExpressionArray(ExpressionContext* const expCtx)
- : ExpressionVariadic<ExpressionArray>(expCtx) {}
+ : ExpressionVariadic<ExpressionArray>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionArray(ExpressionContext* const expCtx,
std::vector<boost::intrusive_ptr<Expression>>&& children)
@@ -943,7 +947,9 @@ public:
class ExpressionObjectToArray final : public ExpressionFixedArity<ExpressionObjectToArray, 1> {
public:
explicit ExpressionObjectToArray(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionObjectToArray, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionObjectToArray, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
const char* getOpName() const final;
@@ -956,7 +962,9 @@ public:
class ExpressionArrayToObject final : public ExpressionFixedArity<ExpressionArrayToObject, 1> {
public:
explicit ExpressionArrayToObject(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionArrayToObject, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionArrayToObject, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionArrayToObject(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionArrayToObject, 1>(expCtx, std::move(children)) {}
@@ -1629,7 +1637,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionHour>(
- expCtx, "$hour", std::move(date), std::move(timeZone)) {}
+ expCtx, "$hour", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.dateParts(date).hour);
@@ -1659,7 +1669,9 @@ public:
class ExpressionIn final : public ExpressionFixedArity<ExpressionIn, 2> {
public:
explicit ExpressionIn(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionIn, 2>(expCtx) {}
+ : ExpressionFixedArity<ExpressionIn, 2>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionIn(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionIn, 2>(expCtx, std::move(children)) {}
@@ -1677,7 +1689,9 @@ public:
class ExpressionIndexOfArray : public ExpressionRangedArity<ExpressionIndexOfArray, 2, 4> {
public:
explicit ExpressionIndexOfArray(ExpressionContext* const expCtx)
- : ExpressionRangedArity<ExpressionIndexOfArray, 2, 4>(expCtx) {}
+ : ExpressionRangedArity<ExpressionIndexOfArray, 2, 4>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionIndexOfArray(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionRangedArity<ExpressionIndexOfArray, 2, 4>(expCtx, std::move(children)) {}
@@ -1910,7 +1924,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionMillisecond>(
- expCtx, "$millisecond", std::move(date), std::move(timeZone)) {}
+ expCtx, "$millisecond", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.dateParts(date).millisecond);
@@ -1928,7 +1944,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionMinute>(
- expCtx, "$minute", std::move(date), std::move(timeZone)) {}
+ expCtx, "$minute", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.dateParts(date).minute);
@@ -1986,7 +2004,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionMonth>(
- expCtx, "$month", std::move(date), std::move(timeZone)) {}
+ expCtx, "$month", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.dateParts(date).month);
@@ -2098,7 +2118,9 @@ public:
class ExpressionPow final : public ExpressionFixedArity<ExpressionPow, 2> {
public:
explicit ExpressionPow(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionPow, 2>(expCtx) {}
+ : ExpressionFixedArity<ExpressionPow, 2>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionPow(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionPow, 2>(expCtx, std::move(children)) {}
@@ -2119,7 +2141,9 @@ private:
class ExpressionRange final : public ExpressionRangedArity<ExpressionRange, 2, 3> {
public:
explicit ExpressionRange(ExpressionContext* const expCtx)
- : ExpressionRangedArity<ExpressionRange, 2, 3>(expCtx) {}
+ : ExpressionRangedArity<ExpressionRange, 2, 3>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
const char* getOpName() const final;
@@ -2143,7 +2167,9 @@ public:
_initial(_children[1]),
_in(_children[2]),
_thisVar(thisVar),
- _valueVar(valueVar) {}
+ _valueVar(valueVar) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
boost::intrusive_ptr<Expression> optimize() final;
@@ -2221,7 +2247,13 @@ protected:
class ExpressionReplaceAll final : public ExpressionReplaceBase {
public:
- using ExpressionReplaceBase::ExpressionReplaceBase;
+ ExpressionReplaceAll(ExpressionContext* const expCtx,
+ boost::intrusive_ptr<Expression> input,
+ boost::intrusive_ptr<Expression> find,
+ boost::intrusive_ptr<Expression> replacement)
+ : ExpressionReplaceBase(expCtx, input, find, replacement) {
+ expCtx->sbeCompatible = false;
+ }
static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx,
BSONElement expr,
@@ -2246,7 +2278,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionSecond>(
- expCtx, "$second", std::move(date), std::move(timeZone)) {}
+ expCtx, "$second", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.dateParts(date).second);
@@ -2277,7 +2311,9 @@ public:
class ExpressionSetEquals final : public ExpressionVariadic<ExpressionSetEquals> {
public:
explicit ExpressionSetEquals(ExpressionContext* const expCtx)
- : ExpressionVariadic<ExpressionSetEquals>(expCtx) {}
+ : ExpressionVariadic<ExpressionSetEquals>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionSetEquals(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionVariadic<ExpressionSetEquals>(expCtx, std::move(children)) {}
@@ -2319,7 +2355,9 @@ public:
class ExpressionSetIsSubset : public ExpressionFixedArity<ExpressionSetIsSubset, 2> {
public:
explicit ExpressionSetIsSubset(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionSetIsSubset, 2>(expCtx) {}
+ : ExpressionFixedArity<ExpressionSetIsSubset, 2>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionSetIsSubset(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionSetIsSubset, 2>(expCtx, std::move(children)) {}
@@ -2363,7 +2401,9 @@ public:
class ExpressionSize final : public ExpressionFixedArity<ExpressionSize, 1> {
public:
explicit ExpressionSize(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionSize, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionSize, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
const char* getOpName() const final;
@@ -2377,7 +2417,9 @@ public:
class ExpressionReverseArray final : public ExpressionFixedArity<ExpressionReverseArray, 1> {
public:
explicit ExpressionReverseArray(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionReverseArray, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionReverseArray, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
const char* getOpName() const final;
@@ -2391,7 +2433,9 @@ public:
class ExpressionSlice final : public ExpressionRangedArity<ExpressionSlice, 2, 3> {
public:
explicit ExpressionSlice(ExpressionContext* const expCtx)
- : ExpressionRangedArity<ExpressionSlice, 2, 3>(expCtx) {}
+ : ExpressionRangedArity<ExpressionSlice, 2, 3>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionSlice(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionRangedArity<ExpressionSlice, 2, 3>(expCtx, std::move(children)) {}
@@ -2423,7 +2467,9 @@ public:
class ExpressionRound final : public ExpressionRangedArity<ExpressionRound, 1, 2> {
public:
explicit ExpressionRound(ExpressionContext* const expCtx)
- : ExpressionRangedArity<ExpressionRound, 1, 2>(expCtx) {}
+ : ExpressionRangedArity<ExpressionRound, 1, 2>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionRound(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionRangedArity<ExpressionRound, 1, 2>(expCtx, std::move(children)) {}
@@ -2470,7 +2516,9 @@ public:
class ExpressionStrcasecmp final : public ExpressionFixedArity<ExpressionStrcasecmp, 2> {
public:
explicit ExpressionStrcasecmp(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionStrcasecmp, 2>(expCtx) {}
+ : ExpressionFixedArity<ExpressionStrcasecmp, 2>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionStrcasecmp(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionStrcasecmp, 2>(expCtx, std::move(children)) {}
@@ -2486,7 +2534,9 @@ public:
class ExpressionSubstrBytes final : public ExpressionFixedArity<ExpressionSubstrBytes, 3> {
public:
explicit ExpressionSubstrBytes(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionSubstrBytes, 3>(expCtx) {}
+ : ExpressionFixedArity<ExpressionSubstrBytes, 3>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionSubstrBytes(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionSubstrBytes, 3>(expCtx, std::move(children)) {}
@@ -2502,7 +2552,9 @@ public:
class ExpressionSubstrCP final : public ExpressionFixedArity<ExpressionSubstrCP, 3> {
public:
explicit ExpressionSubstrCP(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionSubstrCP, 3>(expCtx) {}
+ : ExpressionFixedArity<ExpressionSubstrCP, 3>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionSubstrCP(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionSubstrCP, 3>(expCtx, std::move(children)) {}
@@ -2518,7 +2570,9 @@ public:
class ExpressionStrLenBytes final : public ExpressionFixedArity<ExpressionStrLenBytes, 1> {
public:
explicit ExpressionStrLenBytes(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionStrLenBytes, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionStrLenBytes, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionStrLenBytes(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionStrLenBytes, 1>(expCtx, std::move(children)) {}
@@ -2535,7 +2589,9 @@ public:
class ExpressionBinarySize final : public ExpressionFixedArity<ExpressionBinarySize, 1> {
public:
ExpressionBinarySize(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionBinarySize, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionBinarySize, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
const char* getOpName() const final;
@@ -2549,7 +2605,9 @@ public:
class ExpressionStrLenCP final : public ExpressionFixedArity<ExpressionStrLenCP, 1> {
public:
explicit ExpressionStrLenCP(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionStrLenCP, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionStrLenCP, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionStrLenCP(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionStrLenCP, 1>(expCtx, std::move(children)) {}
@@ -2565,7 +2623,9 @@ public:
class ExpressionSubtract final : public ExpressionFixedArity<ExpressionSubtract, 2> {
public:
explicit ExpressionSubtract(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionSubtract, 2>(expCtx) {}
+ : ExpressionFixedArity<ExpressionSubtract, 2>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionSubtract(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionSubtract, 2>(expCtx, std::move(children)) {}
@@ -2663,7 +2723,9 @@ public:
_trimType(trimType),
_name(name.toString()),
_input(_children[0]),
- _characters(_children[1]) {}
+ _characters(_children[1]) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
boost::intrusive_ptr<Expression> optimize() final;
@@ -2716,7 +2778,9 @@ private:
class ExpressionTrunc final : public ExpressionRangedArity<ExpressionTrunc, 1, 2> {
public:
explicit ExpressionTrunc(ExpressionContext* const expCtx)
- : ExpressionRangedArity<ExpressionTrunc, 1, 2>(expCtx) {}
+ : ExpressionRangedArity<ExpressionTrunc, 1, 2>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionTrunc(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionRangedArity<ExpressionTrunc, 1, 2>(expCtx, std::move(children)) {}
@@ -2735,7 +2799,9 @@ public:
class ExpressionType final : public ExpressionFixedArity<ExpressionType, 1> {
public:
explicit ExpressionType(ExpressionContext* const expCtx)
- : ExpressionFixedArity<ExpressionType, 1>(expCtx) {}
+ : ExpressionFixedArity<ExpressionType, 1>(expCtx) {
+ expCtx->sbeCompatible = false;
+ }
ExpressionType(ExpressionContext* const expCtx, ExpressionVector&& children)
: ExpressionFixedArity<ExpressionType, 1>(expCtx, std::move(children)) {}
@@ -2767,7 +2833,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionWeek>(
- expCtx, "$week", std::move(date), std::move(timeZone)) {}
+ expCtx, "$week", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.week(date));
@@ -2785,7 +2853,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionIsoWeekYear>(
- expCtx, "$isoWeekYear", std::move(date), std::move(timeZone)) {}
+ expCtx, "$isoWeekYear", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.isoYear(date));
@@ -2822,7 +2892,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionIsoWeek>(
- expCtx, "$isoWeek", std::move(date), std::move(timeZone)) {}
+ expCtx, "$isoWeek", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.isoWeek(date));
@@ -2840,7 +2912,9 @@ public:
boost::intrusive_ptr<Expression> date,
boost::intrusive_ptr<Expression> timeZone = nullptr)
: DateExpressionAcceptingTimeZone<ExpressionYear>(
- expCtx, "$year", std::move(date), std::move(timeZone)) {}
+ expCtx, "$year", std::move(date), std::move(timeZone)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluateDate(Date_t date, const TimeZone& timeZone) const final {
return Value(timeZone.dateParts(date).year);
@@ -2862,7 +2936,9 @@ public:
: Expression(expCtx, std::move(children)),
_useLongestLength(useLongestLength),
_inputs(std::move(inputs)),
- _defaults(std::move(defaults)) {}
+ _defaults(std::move(defaults)) {
+ expCtx->sbeCompatible = false;
+ }
Value evaluate(const Document& root, Variables* variables) const final;
boost::intrusive_ptr<Expression> optimize() final;
@@ -3136,7 +3212,9 @@ class ExpressionToHashedIndexKey : public Expression {
public:
ExpressionToHashedIndexKey(ExpressionContext* const expCtx,
boost::intrusive_ptr<Expression> inputExpression)
- : Expression(expCtx, {inputExpression}){};
+ : Expression(expCtx, {inputExpression}) {
+ expCtx->sbeCompatible = false;
+ };
static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx,
BSONElement expr,
diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h
index 33696061ecc..af83dbd31a7 100644
--- a/src/mongo/db/pipeline/expression_context.h
+++ b/src/mongo/db/pipeline/expression_context.h
@@ -365,6 +365,10 @@ public:
// construction.
const bool mayDbProfile = true;
+ // True if all expressions which use this expression context can be translated into equivalent
+ // SBE expressions.
+ bool sbeCompatible = true;
+
// API Parameters pulled from OperationContext upon object creation.
// This may become stale if OperationContext changes after object creation.
// Expressions should reach APIParameters with this variable instead of using the decorator.
diff --git a/src/mongo/db/pipeline/expression_function.cpp b/src/mongo/db/pipeline/expression_function.cpp
index 8f5074bb1c1..e28acaca61b 100644
--- a/src/mongo/db/pipeline/expression_function.cpp
+++ b/src/mongo/db/pipeline/expression_function.cpp
@@ -42,7 +42,9 @@ ExpressionFunction::ExpressionFunction(ExpressionContext* const expCtx,
_passedArgs(_children[0]),
_assignFirstArgToThis(assignFirstArgToThis),
_funcSource(std::move(funcSource)),
- _lang(std::move(lang)) {}
+ _lang(std::move(lang)) {
+ expCtx->sbeCompatible = false;
+}
Value ExpressionFunction::serialize(bool explain) const {
MutableDocument d;
diff --git a/src/mongo/db/pipeline/expression_js_emit.cpp b/src/mongo/db/pipeline/expression_js_emit.cpp
index 6340a53e98f..44242fefcf3 100644
--- a/src/mongo/db/pipeline/expression_js_emit.cpp
+++ b/src/mongo/db/pipeline/expression_js_emit.cpp
@@ -94,7 +94,9 @@ ExpressionInternalJsEmit::ExpressionInternalJsEmit(ExpressionContext* const expC
: Expression(expCtx, {std::move(thisRef)}),
_emitState{{}, internalQueryMaxJsEmitBytes.load(), 0},
_thisRef(_children[0]),
- _funcSource(std::move(funcSource)) {}
+ _funcSource(std::move(funcSource)) {
+ expCtx->sbeCompatible = false;
+}
void ExpressionInternalJsEmit::_doAddDependencies(mongo::DepsTracker* deps) const {
_children[0]->addDependencies(deps);
diff --git a/src/mongo/db/pipeline/expression_test_api_version.cpp b/src/mongo/db/pipeline/expression_test_api_version.cpp
index 8a30407961b..8428d6d78ab 100644
--- a/src/mongo/db/pipeline/expression_test_api_version.cpp
+++ b/src/mongo/db/pipeline/expression_test_api_version.cpp
@@ -38,7 +38,9 @@ REGISTER_TEST_EXPRESSION(_testApiVersion, ExpressionTestApiVersion::parse);
ExpressionTestApiVersion::ExpressionTestApiVersion(ExpressionContext* const expCtx,
bool unstable,
bool deprecated)
- : Expression(expCtx), _unstable(unstable), _deprecated(deprecated) {}
+ : Expression(expCtx), _unstable(unstable), _deprecated(deprecated) {
+ expCtx->sbeCompatible = false;
+}
boost::intrusive_ptr<Expression> ExpressionTestApiVersion::parse(ExpressionContext* const expCtx,
BSONElement expr,
diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp
index ade2971399e..19e068ca39c 100644
--- a/src/mongo/db/query/get_executor.cpp
+++ b/src/mongo/db/query/get_executor.cpp
@@ -916,10 +916,6 @@ protected:
std::unique_ptr<SlotBasedPrepareExecutionResult> buildIdHackPlan(
const IndexDescriptor* descriptor, QueryPlannerParams* plannerParams) final {
- uassert(4822862,
- "Queries that require sort key metadata are not supported by SBE yet",
- !_cq->metadataDeps()[DocumentMetadataFields::kSortKey]);
-
// Fall back to normal planning.
return nullptr;
}
@@ -1106,6 +1102,25 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getSlotBasedExe
std::move(nss),
std::move(yieldPolicy));
}
+
+// Checks if the given query can be executed with the SBE engine.
+inline bool isQuerySbeCompatible(const CanonicalQuery* const cq, size_t plannerOptions) {
+ invariant(cq);
+ auto expCtx = cq->getExpCtxRaw();
+ auto sortPattern = cq->getSortPattern();
+ const bool allExpressionsSupported = expCtx && expCtx->sbeCompatible;
+ const bool isNotCount = !(plannerOptions & QueryPlannerParams::IS_COUNT);
+ // Specifying 'ntoreturn' in an OP_QUERY style find may result in a QuerySolution with
+ // ENSURE_SORTED node, which is currently not supported by SBE.
+ const bool doesNotNeedEnsureSorted = !cq->getQueryRequest().getNToReturn();
+ const bool doesNotContainMetadataRequirements = cq->metadataDeps().none();
+ const bool doesNotSortOnDottedPath =
+ !sortPattern || std::all_of(sortPattern->begin(), sortPattern->end(), [](auto&& part) {
+ return part.fieldPath && part.fieldPath->getPathLength() == 1;
+ });
+ return allExpressionsSupported && isNotCount && doesNotNeedEnsureSorted &&
+ doesNotContainMetadataRequirements && doesNotSortOnDottedPath;
+}
} // namespace
StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor(
@@ -1114,7 +1129,8 @@ StatusWith<std::unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutor(
std::unique_ptr<CanonicalQuery> canonicalQuery,
PlanYieldPolicy::YieldPolicy yieldPolicy,
size_t plannerOptions) {
- return feature_flags::gSBE.isEnabledAndIgnoreFCV()
+ return feature_flags::gSBE.isEnabledAndIgnoreFCV() &&
+ isQuerySbeCompatible(canonicalQuery.get(), plannerOptions)
? getSlotBasedExecutor(
opCtx, collection, std::move(canonicalQuery), yieldPolicy, plannerOptions)
: getClassicExecutor(
diff --git a/src/mongo/db/query/plan_explainer_sbe.cpp b/src/mongo/db/query/plan_explainer_sbe.cpp
index e993b2cf6c0..953eed0ffdf 100644
--- a/src/mongo/db/query/plan_explainer_sbe.cpp
+++ b/src/mongo/db/query/plan_explainer_sbe.cpp
@@ -117,7 +117,7 @@ void statsToBSON(const QuerySolutionNode* node,
}
case STAGE_LIMIT: {
auto ln = static_cast<const LimitNode*>(node);
- bob->appendNumber("limitAmount", ln->limit);
+ bob->appendIntOrLL("limitAmount", ln->limit);
break;
}
case STAGE_PROJECTION_DEFAULT:
@@ -129,7 +129,7 @@ void statsToBSON(const QuerySolutionNode* node,
}
case STAGE_SKIP: {
auto sn = static_cast<const SkipNode*>(node);
- bob->appendNumber("skipAmount", sn->skip);
+ bob->appendIntOrLL("skipAmount", sn->skip);
break;
}
case STAGE_SORT_SIMPLE:
@@ -334,6 +334,7 @@ std::string PlanExplainerSBE::getPlanSummary() const {
}
StringBuilder sb;
+ bool seenLeaf = false;
std::queue<const QuerySolutionNode*> queue;
queue.push(_solution->root());
@@ -341,56 +342,60 @@ std::string PlanExplainerSBE::getPlanSummary() const {
auto node = queue.front();
queue.pop();
- sb << stageTypeToString(node->getType());
-
- switch (node->getType()) {
- case STAGE_COUNT_SCAN: {
- auto csn = static_cast<const CountScanNode*>(node);
- const KeyPattern keyPattern{csn->index.keyPattern};
- sb << " " << keyPattern;
- break;
- }
- case STAGE_DISTINCT_SCAN: {
- auto dn = static_cast<const DistinctNode*>(node);
- const KeyPattern keyPattern{dn->index.keyPattern};
- sb << " " << keyPattern;
- break;
- }
- case STAGE_GEO_NEAR_2D: {
- auto geo2d = static_cast<const GeoNear2DNode*>(node);
- const KeyPattern keyPattern{geo2d->index.keyPattern};
- sb << " " << keyPattern;
- break;
- }
- case STAGE_GEO_NEAR_2DSPHERE: {
- auto geo2dsphere = static_cast<const GeoNear2DSphereNode*>(node);
- const KeyPattern keyPattern{geo2dsphere->index.keyPattern};
- sb << " " << keyPattern;
- break;
- }
- case STAGE_IXSCAN: {
- auto ixn = static_cast<const IndexScanNode*>(node);
- const KeyPattern keyPattern{ixn->index.keyPattern};
- sb << " " << keyPattern;
- break;
+ if (node->children.empty()) {
+ if (seenLeaf) {
+ sb << ", ";
+ } else {
+ seenLeaf = true;
}
- case STAGE_TEXT: {
- auto tn = static_cast<const TextNode*>(node);
- const KeyPattern keyPattern{tn->indexPrefix};
- sb << " " << keyPattern;
- break;
+
+ sb << stageTypeToString(node->getType());
+
+ switch (node->getType()) {
+ case STAGE_COUNT_SCAN: {
+ auto csn = static_cast<const CountScanNode*>(node);
+ const KeyPattern keyPattern{csn->index.keyPattern};
+ sb << " " << keyPattern;
+ break;
+ }
+ case STAGE_DISTINCT_SCAN: {
+ auto dn = static_cast<const DistinctNode*>(node);
+ const KeyPattern keyPattern{dn->index.keyPattern};
+ sb << " " << keyPattern;
+ break;
+ }
+ case STAGE_GEO_NEAR_2D: {
+ auto geo2d = static_cast<const GeoNear2DNode*>(node);
+ const KeyPattern keyPattern{geo2d->index.keyPattern};
+ sb << " " << keyPattern;
+ break;
+ }
+ case STAGE_GEO_NEAR_2DSPHERE: {
+ auto geo2dsphere = static_cast<const GeoNear2DSphereNode*>(node);
+ const KeyPattern keyPattern{geo2dsphere->index.keyPattern};
+ sb << " " << keyPattern;
+ break;
+ }
+ case STAGE_IXSCAN: {
+ auto ixn = static_cast<const IndexScanNode*>(node);
+ const KeyPattern keyPattern{ixn->index.keyPattern};
+ sb << " " << keyPattern;
+ break;
+ }
+ case STAGE_TEXT: {
+ auto tn = static_cast<const TextNode*>(node);
+ const KeyPattern keyPattern{tn->indexPrefix};
+ sb << " " << keyPattern;
+ break;
+ }
+ default:
+ break;
}
- default:
- break;
}
for (auto&& child : node->children) {
queue.push(child);
}
-
- if (!queue.empty()) {
- sb << ", ";
- }
}
return sb.str();
diff --git a/src/mongo/db/query/sbe_stage_builder.cpp b/src/mongo/db/query/sbe_stage_builder.cpp
index 8b358546f65..fc041266768 100644
--- a/src/mongo/db/query/sbe_stage_builder.cpp
+++ b/src/mongo/db/query/sbe_stage_builder.cpp
@@ -1403,8 +1403,8 @@ std::pair<std::unique_ptr<sbe::PlanStage>, PlanStageSlots> SlotBasedStageBuilder
{STAGE_SORT_MERGE, &SlotBasedStageBuilder::buildSortMerge},
{STAGE_SHARDING_FILTER, &SlotBasedStageBuilder::buildShardFilter}};
- uassert(4822884,
- str::stream() << "Can't build exec tree for node: " << root->toString(),
+ tassert(4822884,
+ str::stream() << "Unsupported QSN in SBE stage builder: " << root->toString(),
kStageBuilders.find(root->getType()) != kStageBuilders.end());
// If this plan is for a tailable cursor scan, and we're not already in the process of building
diff --git a/src/mongo/db/query/sbe_stage_builder_expression.cpp b/src/mongo/db/query/sbe_stage_builder_expression.cpp
index d05ceb5bf34..a345e99d21f 100644
--- a/src/mongo/db/query/sbe_stage_builder_expression.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_expression.cpp
@@ -3411,8 +3411,10 @@ private:
}
void unsupportedExpression(const char* op) const {
- uasserted(ErrorCodes::InternalErrorNotSupported,
- str::stream() << "Expression is not supported in SBE: " << op);
+ // We're guaranteed to not fire this assertion by implementing a mechanism in the upper
+ // layer which directs the query to the classic engine when an unsupported expression
+ // appears.
+ tasserted(5182300, str::stream() << "Unsupported expression in SBE stage builder: " << op);
}
ExpressionVisitorContext* _context;
diff --git a/src/mongo/db/query/sbe_stage_builder_filter.cpp b/src/mongo/db/query/sbe_stage_builder_filter.cpp
index 0befaabeb1d..5a3b9e21862 100644
--- a/src/mongo/db/query/sbe_stage_builder_filter.cpp
+++ b/src/mongo/db/query/sbe_stage_builder_filter.cpp
@@ -955,8 +955,11 @@ public:
private:
void unsupportedExpression(const MatchExpression* expr) const {
- uasserted(4822878,
- str::stream() << "Match expression is not supported in SBE: "
+ // We're guaranteed to not fire this assertion by implementing a mechanism in the upper
+ // layer which directs the query to the classic engine when an unsupported expression
+ // appears.
+ tasserted(4822878,
+ str::stream() << "Unsupported match expression in SBE stage builder: "
<< expr->matchType());
}
diff --git a/src/mongo/db/query/stage_types.cpp b/src/mongo/db/query/stage_types.cpp
index 2f37ba89e0f..b5f1f16c106 100644
--- a/src/mongo/db/query/stage_types.cpp
+++ b/src/mongo/db/query/stage_types.cpp
@@ -63,8 +63,8 @@ StringData stageTypeToString(StageType stageType) {
{STAGE_RETURN_KEY, "RETURN_KEY"_sd},
{STAGE_SHARDING_FILTER, "SHARDING_FILTER"_sd},
{STAGE_SKIP, "SKIP"_sd},
- {STAGE_SORT_DEFAULT, "SORT_DEFAULT"_sd},
- {STAGE_SORT_SIMPLE, "SORT_SIMPLE"_sd},
+ {STAGE_SORT_DEFAULT, "SORT"_sd},
+ {STAGE_SORT_SIMPLE, "SORT"_sd},
{STAGE_SORT_KEY_GENERATOR, "SORT_KEY_GENERATOR"_sd},
{STAGE_SORT_MERGE, "SORT_MERGE"_sd},
{STAGE_SUBPLAN, "SUBPLAN"_sd},