diff options
author | Anton Korshunov <anton.korshunov@mongodb.com> | 2021-01-31 00:34:57 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-02-14 15:30:07 +0000 |
commit | 0fc5b56b12dbdc248556fdfa9da2f44479eac699 (patch) | |
tree | dfac279997b20789e8c376fcf5a74fce75b15d22 /src | |
parent | 4dd10ec20b608ec364db1ba4815bbf45d73e8da4 (diff) | |
download | mongo-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.cpp | 45 | ||||
-rw-r--r-- | src/mongo/db/matcher/schema/json_schema_parser.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.cpp | 28 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression.h | 152 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_context.h | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_function.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_js_emit.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/expression_test_api_version.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/query/get_executor.cpp | 26 | ||||
-rw-r--r-- | src/mongo/db/query/plan_explainer_sbe.cpp | 95 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder.cpp | 4 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_expression.cpp | 6 | ||||
-rw-r--r-- | src/mongo/db/query/sbe_stage_builder_filter.cpp | 7 | ||||
-rw-r--r-- | src/mongo/db/query/stage_types.cpp | 4 |
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}, |