diff options
author | Jacob Evans <jacob.evans@10gen.com> | 2020-05-12 15:55:02 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-05-16 01:30:05 +0000 |
commit | a7f769dd597e33e988832c43c99912c1d3139c9b (patch) | |
tree | 9366f0dfc75db2c9c92e2b101de17542ae573e89 /src | |
parent | 6b38c78843e7eb58dc344d88903727762d7d486d (diff) | |
download | mongo-a7f769dd597e33e988832c43c99912c1d3139c9b.tar.gz |
SERVER-47713 Change Expression code to remove intrusive ExpressionContext
Diffstat (limited to 'src')
76 files changed, 1880 insertions, 2009 deletions
diff --git a/src/mongo/db/commands/mr_common.cpp b/src/mongo/db/commands/mr_common.cpp index 00ba75a57c2..d3b8e792bb4 100644 --- a/src/mongo/db/commands/mr_common.cpp +++ b/src/mongo/db/commands/mr_common.cpp @@ -106,7 +106,9 @@ auto translateSort(boost::intrusive_ptr<ExpressionContext> expCtx, const BSONObj auto translateMap(boost::intrusive_ptr<ExpressionContext> expCtx, std::string code) { auto emitExpression = ExpressionInternalJsEmit::create( - expCtx, ExpressionFieldPath::parse(expCtx, "$$ROOT", expCtx->variablesParseState), code); + expCtx.get(), + ExpressionFieldPath::parse(expCtx.get(), "$$ROOT", expCtx->variablesParseState), + code); auto node = std::make_unique<projection_executor::InclusionNode>( ProjectionPolicies{ProjectionPolicies::DefaultIdPolicy::kExcludeId}); node->addExpressionForPath(FieldPath{"emits"s}, std::move(emitExpression)); @@ -120,17 +122,17 @@ auto translateMap(boost::intrusive_ptr<ExpressionContext> expCtx, std::string co } auto translateReduce(boost::intrusive_ptr<ExpressionContext> expCtx, std::string code) { - auto initializer = ExpressionArray::create(expCtx, {}); - auto argument = ExpressionFieldPath::parse(expCtx, "$emits", expCtx->variablesParseState); + auto initializer = ExpressionArray::create(expCtx.get(), {}); + auto argument = ExpressionFieldPath::parse(expCtx.get(), "$emits", expCtx->variablesParseState); auto reduceFactory = [expCtx, funcSource = std::move(code)]() { - return AccumulatorInternalJsReduce::create(expCtx, funcSource); + return AccumulatorInternalJsReduce::create(expCtx.get(), funcSource); }; AccumulationStatement jsReduce("value", AccumulationExpression(std::move(initializer), std::move(argument), std::move(reduceFactory))); auto groupKeyExpression = - ExpressionFieldPath::parse(expCtx, "$emits.k", expCtx->variablesParseState); + ExpressionFieldPath::parse(expCtx.get(), "$emits.k", expCtx->variablesParseState); return DocumentSourceGroup::create(expCtx, std::move(groupKeyExpression), make_vector<AccumulationStatement>(std::move(jsReduce)), @@ -141,12 +143,13 @@ auto translateFinalize(boost::intrusive_ptr<ExpressionContext> expCtx, MapReduceJavascriptCodeOrNull codeObj) { return codeObj.getCode().map([&](auto&& code) { auto jsExpression = ExpressionFunction::create( - expCtx, + expCtx.get(), ExpressionArray::create( - expCtx, + expCtx.get(), make_vector<boost::intrusive_ptr<Expression>>( - ExpressionFieldPath::parse(expCtx, "$_id", expCtx->variablesParseState), - ExpressionFieldPath::parse(expCtx, "$value", expCtx->variablesParseState))), + ExpressionFieldPath::parse(expCtx.get(), "$_id", expCtx->variablesParseState), + ExpressionFieldPath::parse( + expCtx.get(), "$value", expCtx->variablesParseState))), code, ExpressionFunction::kJavaScript); auto node = std::make_unique<projection_executor::InclusionNode>( diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp index 6293a8cac31..c8805eee8c3 100644 --- a/src/mongo/db/commands/run_aggregate.cpp +++ b/src/mongo/db/commands/run_aggregate.cpp @@ -216,8 +216,8 @@ bool handleCursorCommand(OperationContext* opCtx, // If adding this object will cause us to exceed the message size limit, then we stash it // for later. - auto* expCtx = exec->getExpCtx().get(); - BSONObj next = expCtx->needsMerge ? nextDoc.toBsonWithMetaData() : nextDoc.toBson(); + BSONObj next = + exec->getExpCtx()->needsMerge ? nextDoc.toBsonWithMetaData() : nextDoc.toBson(); if (!FindCommon::haveSpaceForNext(next, objCount, responseBuilder.bytesUsed())) { exec->enqueue(nextDoc); stashedResult = true; diff --git a/src/mongo/db/exec/add_fields_projection_executor.cpp b/src/mongo/db/exec/add_fields_projection_executor.cpp index ec3acc136bc..a91f42c1408 100644 --- a/src/mongo/db/exec/add_fields_projection_executor.cpp +++ b/src/mongo/db/exec/add_fields_projection_executor.cpp @@ -247,7 +247,7 @@ void AddFieldsProjectionExecutor::parse(const BSONObj& spec) { // This is a literal or regular value. _root->addExpressionForPath( FieldPath(elem.fieldName()), - Expression::parseOperand(_expCtx, elem, _expCtx->variablesParseState)); + Expression::parseOperand(_expCtx.get(), elem, _expCtx->variablesParseState)); } } } @@ -270,7 +270,7 @@ bool AddFieldsProjectionExecutor::parseObjectAsExpression( // This is an expression like {$add: [...]}. We already verified that it has only one field. invariant(objSpec.nFields() == 1); _root->addExpressionForPath( - pathToObject, Expression::parseExpression(_expCtx, objSpec, variablesParseState)); + pathToObject, Expression::parseExpression(_expCtx.get(), objSpec, variablesParseState)); return true; } return false; @@ -300,7 +300,7 @@ void AddFieldsProjectionExecutor::parseSubObject(const BSONObj& subObj, // This is a literal or regular value. node->addExpressionForPath( FieldPath(elem.fieldName()), - Expression::parseOperand(_expCtx, elem, variablesParseState)); + Expression::parseOperand(_expCtx.get(), elem, variablesParseState)); } } } diff --git a/src/mongo/db/exec/find_projection_executor_test.cpp b/src/mongo/db/exec/find_projection_executor_test.cpp index c0baf7a01fd..0940ef96be5 100644 --- a/src/mongo/db/exec/find_projection_executor_test.cpp +++ b/src/mongo/db/exec/find_projection_executor_test.cpp @@ -56,16 +56,17 @@ protected: const BSONObj& matchSpec, const std::string& path, const Document& input) { - auto executor = createProjectionExecutor(getExpCtx(), projSpec, {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), projSpec, {}); auto matchExpr = CopyableMatchExpression{matchSpec, - getExpCtx(), + getExpCtxRaw(), std::make_unique<ExtensionsCallbackNoop>(), MatchExpressionParser::kBanAllSpecialFeatures}; auto expr = make_intrusive<ExpressionInternalFindPositional>( - getExpCtx(), - ExpressionFieldPath::parse(getExpCtx(), "$$ROOT", getExpCtx()->variablesParseState), - ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), "$$ROOT", getExpCtx()->variablesParseState), + ExpressionFieldPath::parse(getExpCtxRaw(), + "$$" + kProjectionPostImageVarName, + getExpCtx()->variablesParseState), path, std::move(matchExpr)); executor->setRootReplacementExpression(expr); @@ -80,11 +81,12 @@ protected: boost::optional<int> skip, int limit, const Document& input) { - auto executor = createProjectionExecutor(getExpCtx(), projSpec, {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), projSpec, {}); auto expr = make_intrusive<ExpressionInternalFindSlice>( - getExpCtx(), - ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), + "$$" + kProjectionPostImageVarName, + getExpCtx()->variablesParseState), path, skip, limit); @@ -116,17 +118,17 @@ TEST_F(PositionalProjectionExecutionTest, AppliesProjectionToPreImage) { } TEST_F(PositionalProjectionExecutionTest, ShouldAddInclusionFieldsAndWholeDocumentToDependencies) { - auto executor = createProjectionExecutor(getExpCtx(), fromjson("{bar: 1, _id: 0}"), {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), fromjson("{bar: 1, _id: 0}"), {}); auto matchSpec = fromjson("{bar: 1, 'foo.bar': {$gte: 5}}"); auto matchExpr = CopyableMatchExpression{matchSpec, - getExpCtx(), + getExpCtxRaw(), std::make_unique<ExtensionsCallbackNoop>(), MatchExpressionParser::kBanAllSpecialFeatures}; auto expr = make_intrusive<ExpressionInternalFindPositional>( - getExpCtx(), - ExpressionFieldPath::parse(getExpCtx(), "$$ROOT", getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), "$$ROOT", getExpCtx()->variablesParseState), ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), "foo.bar", std::move(matchExpr)); executor->setRootReplacementExpression(expr); @@ -141,17 +143,17 @@ TEST_F(PositionalProjectionExecutionTest, ShouldAddInclusionFieldsAndWholeDocume } TEST_F(PositionalProjectionExecutionTest, ShouldConsiderAllPathsAsModified) { - auto executor = createProjectionExecutor(getExpCtx(), fromjson("{bar: 1, _id: 0}"), {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), fromjson("{bar: 1, _id: 0}"), {}); auto matchSpec = fromjson("{bar: 1, 'foo.bar': {$gte: 5}}"); auto matchExpr = CopyableMatchExpression{matchSpec, - getExpCtx(), + getExpCtxRaw(), std::make_unique<ExtensionsCallbackNoop>(), MatchExpressionParser::kBanAllSpecialFeatures}; auto expr = make_intrusive<ExpressionInternalFindPositional>( - getExpCtx(), - ExpressionFieldPath::parse(getExpCtx(), "$$ROOT", getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), "$$ROOT", getExpCtx()->variablesParseState), ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), "foo.bar", std::move(matchExpr)); executor->setRootReplacementExpression(expr); @@ -184,21 +186,21 @@ TEST_F(SliceProjectionExecutionTest, AppliesProjectionToPostImage) { } TEST_F(SliceProjectionExecutionTest, CanApplySliceAndPositionalProjectionsTogether) { - auto executor = createProjectionExecutor(getExpCtx(), fromjson("{foo: 1, bar: 1}"), {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), fromjson("{foo: 1, bar: 1}"), {}); auto matchSpec = fromjson("{foo: {$gte: 3}}"); auto matchExpr = CopyableMatchExpression{matchSpec, - getExpCtx(), + getExpCtxRaw(), std::make_unique<ExtensionsCallbackNoop>(), MatchExpressionParser::kBanAllSpecialFeatures}; auto positionalExpr = make_intrusive<ExpressionInternalFindPositional>( - getExpCtx(), - ExpressionFieldPath::parse(getExpCtx(), "$$ROOT", getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), "$$ROOT", getExpCtx()->variablesParseState), ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), "foo", std::move(matchExpr)); auto sliceExpr = - make_intrusive<ExpressionInternalFindSlice>(getExpCtx(), positionalExpr, "bar", 1, 1); + make_intrusive<ExpressionInternalFindSlice>(getExpCtxRaw(), positionalExpr, "bar", 1, 1); executor->setRootReplacementExpression(sliceExpr); ASSERT_DOCUMENT_EQ( @@ -215,11 +217,11 @@ TEST_F(SliceProjectionExecutionTest, CanApplySliceWithExclusionProjection) { TEST_F(SliceProjectionExecutionTest, ShouldAddFieldsAndWholeDocumentToDependenciesWithInclusionProjection) { - auto executor = createProjectionExecutor(getExpCtx(), fromjson("{bar: 1, _id: 0}"), {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), fromjson("{bar: 1, _id: 0}"), {}); auto expr = make_intrusive<ExpressionInternalFindSlice>( - getExpCtx(), + getExpCtxRaw(), ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), "foo.bar", 1, 1); @@ -234,11 +236,11 @@ TEST_F(SliceProjectionExecutionTest, } TEST_F(SliceProjectionExecutionTest, ShouldConsiderAllPathsAsModifiedWithInclusionProjection) { - auto executor = createProjectionExecutor(getExpCtx(), fromjson("{bar: 1}"), {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), fromjson("{bar: 1}"), {}); auto expr = make_intrusive<ExpressionInternalFindSlice>( - getExpCtx(), + getExpCtxRaw(), ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), "foo.bar", 1, 1); @@ -249,11 +251,11 @@ TEST_F(SliceProjectionExecutionTest, ShouldConsiderAllPathsAsModifiedWithInclusi } TEST_F(SliceProjectionExecutionTest, ShouldConsiderAllPathsAsModifiedWithExclusionProjection) { - auto executor = createProjectionExecutor(getExpCtx(), fromjson("{bar: 0}"), {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), fromjson("{bar: 0}"), {}); auto expr = make_intrusive<ExpressionInternalFindSlice>( - getExpCtx(), + getExpCtxRaw(), ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), "foo.bar", 1, 1); @@ -264,11 +266,11 @@ TEST_F(SliceProjectionExecutionTest, ShouldConsiderAllPathsAsModifiedWithExclusi } TEST_F(SliceProjectionExecutionTest, ShouldAddWholeDocumentToDependenciesWithExclusionProjection) { - auto executor = createProjectionExecutor(getExpCtx(), fromjson("{bar: 0}"), {}); + auto executor = createProjectionExecutor(getExpCtxRaw(), fromjson("{bar: 0}"), {}); auto expr = make_intrusive<ExpressionInternalFindSlice>( - getExpCtx(), + getExpCtxRaw(), ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), "foo.bar", 1, 1); diff --git a/src/mongo/db/exec/projection_executor_builder.cpp b/src/mongo/db/exec/projection_executor_builder.cpp index d8ff0f6dfb6..cd0e3cb49b4 100644 --- a/src/mongo/db/exec/projection_executor_builder.cpp +++ b/src/mongo/db/exec/projection_executor_builder.cpp @@ -76,15 +76,17 @@ using ProjectionExecutorVisitorContext = template <typename Executor> auto makeProjectionPreImageExpression(const ProjectionExecutorVisitorData<Executor>& data) { - return ExpressionFieldPath::parse(data.expCtx, "$$ROOT", data.expCtx->variablesParseState); + return ExpressionFieldPath::parse( + data.expCtx.get(), "$$ROOT", data.expCtx->variablesParseState); } template <typename Executor> auto makeProjectionPostImageExpression(const ProjectionExecutorVisitorData<Executor>& data) { return data.rootReplacementExpression ? data.rootReplacementExpression - : ExpressionFieldPath::parse( - data.expCtx, "$$" + kProjectionPostImageVarName, data.expCtx->variablesParseState); + : ExpressionFieldPath::parse(data.expCtx.get(), + "$$" + kProjectionPostImageVarName, + data.expCtx->variablesParseState); } /** @@ -106,7 +108,7 @@ auto createFindPositionalExpression(const projection_ast::ProjectionPositionalAS exact_pointer_cast<projection_ast::MatchExpressionASTNode*>(children[0].get()); invariant(matchExprNode); - return make_intrusive<ExpressionInternalFindPositional>(data.expCtx, + return make_intrusive<ExpressionInternalFindPositional>(data.expCtx.get(), makeProjectionPreImageExpression(data), makeProjectionPostImageExpression(data), path, @@ -125,8 +127,11 @@ auto createFindSliceExpression(const projection_ast::ProjectionSliceASTNode* nod const FieldPath& path) { invariant(node); - return make_intrusive<ExpressionInternalFindSlice>( - data.expCtx, makeProjectionPostImageExpression(data), path, node->skip(), node->limit()); + return make_intrusive<ExpressionInternalFindSlice>(data.expCtx.get(), + makeProjectionPostImageExpression(data), + path, + node->skip(), + node->limit()); } /** @@ -146,7 +151,7 @@ auto createFindElemMatchExpression(const projection_ast::ProjectionElemMatchASTN exact_pointer_cast<projection_ast::MatchExpressionASTNode*>(children[0].get()); invariant(matchExprNode); - return make_intrusive<ExpressionInternalFindElemMatch>(data.expCtx, + return make_intrusive<ExpressionInternalFindElemMatch>(data.expCtx.get(), makeProjectionPreImageExpression(data), path, matchExprNode->matchExpression()); diff --git a/src/mongo/db/exec/projection_executor_test.cpp b/src/mongo/db/exec/projection_executor_test.cpp index 3c6fea2808e..0ae80010b3e 100644 --- a/src/mongo/db/exec/projection_executor_test.cpp +++ b/src/mongo/db/exec/projection_executor_test.cpp @@ -569,9 +569,9 @@ TEST(ProjectionExecutorType, ShouldCoerceNumericsToBools) { } TEST(ProjectionExecutorType, GetExpressionForPathGetsTopLevelExpression) { - const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto projectObj = BSON("$add" << BSON_ARRAY(BSON("$const" << 1) << BSON("$const" << 3))); - auto expr = Expression::parseObject(expCtx, projectObj, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, projectObj, expCtx.variablesParseState); ProjectionPolicies defaultPolicies; auto node = InclusionNode(defaultPolicies); node.addExpressionForPath(FieldPath("key"), expr); @@ -580,11 +580,11 @@ TEST(ProjectionExecutorType, GetExpressionForPathGetsTopLevelExpression) { } TEST(ProjectionExecutorType, GetExpressionForPathGetsCorrectTopLevelExpression) { - const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto correctObj = BSON("$add" << BSON_ARRAY(BSON("$const" << 1) << BSON("$const" << 3))); auto incorrectObj = BSON("$add" << BSON_ARRAY(BSON("$const" << 2) << BSON("$const" << 4))); - auto correctExpr = Expression::parseObject(expCtx, correctObj, expCtx->variablesParseState); - auto incorrectExpr = Expression::parseObject(expCtx, incorrectObj, expCtx->variablesParseState); + auto correctExpr = Expression::parseObject(&expCtx, correctObj, expCtx.variablesParseState); + auto incorrectExpr = Expression::parseObject(&expCtx, incorrectObj, expCtx.variablesParseState); ProjectionPolicies defaultPolicies; auto node = InclusionNode(defaultPolicies); node.addExpressionForPath(FieldPath("key"), correctExpr); @@ -594,9 +594,9 @@ TEST(ProjectionExecutorType, GetExpressionForPathGetsCorrectTopLevelExpression) } TEST(ProjectionExecutorType, GetExpressionForPathGetsNonTopLevelExpression) { - const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto projectObj = BSON("$add" << BSON_ARRAY(BSON("$const" << 1) << BSON("$const" << 3))); - auto expr = Expression::parseObject(expCtx, projectObj, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, projectObj, expCtx.variablesParseState); ProjectionPolicies defaultPolicies; auto node = InclusionNode(defaultPolicies); node.addExpressionForPath(FieldPath("key.second"), expr); diff --git a/src/mongo/db/matcher/expression_expr.cpp b/src/mongo/db/matcher/expression_expr.cpp index 01f3affa84c..e649e22450a 100644 --- a/src/mongo/db/matcher/expression_expr.cpp +++ b/src/mongo/db/matcher/expression_expr.cpp @@ -43,7 +43,7 @@ ExprMatchExpression::ExprMatchExpression(boost::intrusive_ptr<Expression> expr, ExprMatchExpression::ExprMatchExpression(BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) - : ExprMatchExpression(Expression::parseOperand(expCtx, elem, expCtx->variablesParseState), + : ExprMatchExpression(Expression::parseOperand(expCtx.get(), elem, expCtx->variablesParseState), expCtx) {} bool ExprMatchExpression::matches(const MatchableDocument* doc, MatchDetails* details) const { @@ -108,8 +108,8 @@ std::unique_ptr<MatchExpression> ExprMatchExpression::shallowClone() const { // TODO SERVER-31003: Replace Expression clone via serialization with Expression::clone(). BSONObjBuilder bob; bob << "" << _expression->serialize(false); - boost::intrusive_ptr<Expression> clonedExpr = - Expression::parseOperand(_expCtx, bob.obj().firstElement(), _expCtx->variablesParseState); + boost::intrusive_ptr<Expression> clonedExpr = Expression::parseOperand( + _expCtx.get(), bob.obj().firstElement(), _expCtx->variablesParseState); auto clone = std::make_unique<ExprMatchExpression>(std::move(clonedExpr), _expCtx); if (_rewriteResult) { diff --git a/src/mongo/db/matcher/extensions_callback_real.cpp b/src/mongo/db/matcher/extensions_callback_real.cpp index 34d2dfc4a26..07fb7b38935 100644 --- a/src/mongo/db/matcher/extensions_callback_real.cpp +++ b/src/mongo/db/matcher/extensions_callback_real.cpp @@ -73,11 +73,11 @@ StatusWithMatchExpression ExtensionsCallbackReal::parseWhere( // Desugar $where to $expr. The $where function is invoked through a $function expression by // passing the document as $$CURRENT. auto fnExpression = ExpressionFunction::createForWhere( - expCtx, + expCtx.get(), ExpressionArray::create( - expCtx, - make_vector<boost::intrusive_ptr<Expression>>( - ExpressionFieldPath::parse(expCtx, "$$CURRENT", expCtx->variablesParseState))), + expCtx.get(), + make_vector<boost::intrusive_ptr<Expression>>(ExpressionFieldPath::parse( + expCtx.get(), "$$CURRENT", expCtx->variablesParseState))), code, ExpressionFunction::kJavaScript); diff --git a/src/mongo/db/matcher/rewrite_expr_test.cpp b/src/mongo/db/matcher/rewrite_expr_test.cpp index 6cad57f9c62..9fa64b3c70b 100644 --- a/src/mongo/db/matcher/rewrite_expr_test.cpp +++ b/src/mongo/db/matcher/rewrite_expr_test.cpp @@ -46,12 +46,12 @@ namespace { * - No MatchExpression (when full or superset rewrite is not possible) */ void testExprRewrite(BSONObj expr, BSONObj expectedMatch) { - boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto expression = - Expression::parseOperand(expCtx, expr.firstElement(), expCtx->variablesParseState); + Expression::parseOperand(&expCtx, expr.firstElement(), expCtx.variablesParseState); - auto result = RewriteExpr::rewrite(expression, expCtx->getCollator()); + auto result = RewriteExpr::rewrite(expression, expCtx.getCollator()); // Confirm expected match. if (!expectedMatch.isEmpty()) { diff --git a/src/mongo/db/pipeline/accumulation_statement.cpp b/src/mongo/db/pipeline/accumulation_statement.cpp index a5950af7c96..31c97af9168 100644 --- a/src/mongo/db/pipeline/accumulation_statement.cpp +++ b/src/mongo/db/pipeline/accumulation_statement.cpp @@ -29,6 +29,7 @@ #include "mongo/platform/basic.h" +#include <boost/intrusive_ptr.hpp> #include <string> #include "mongo/db/pipeline/accumulation_statement.h" @@ -42,7 +43,6 @@ namespace mongo { -using boost::intrusive_ptr; using std::string; namespace { @@ -88,9 +88,7 @@ boost::intrusive_ptr<AccumulatorState> AccumulationStatement::makeAccumulator() } AccumulationStatement AccumulationStatement::parseAccumulationStatement( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - const BSONElement& elem, - const VariablesParseState& vps) { + ExpressionContext* const expCtx, const BSONElement& elem, const VariablesParseState& vps) { auto fieldName = elem.fieldNameStringData(); uassert(40234, str::stream() << "The field '" << fieldName << "' must be an accumulator object", diff --git a/src/mongo/db/pipeline/accumulation_statement.h b/src/mongo/db/pipeline/accumulation_statement.h index e49930b1c61..83f0ad5561c 100644 --- a/src/mongo/db/pipeline/accumulation_statement.h +++ b/src/mongo/db/pipeline/accumulation_statement.h @@ -29,8 +29,6 @@ #pragma once -#include <boost/intrusive_ptr.hpp> - #include "mongo/bson/bsonelement.h" #include "mongo/db/pipeline/accumulator.h" #include "mongo/db/pipeline/expression.h" @@ -129,8 +127,9 @@ struct AccumulationExpression { * the expression to be evaluated by the accumulator and an AccumulatorState::Factory. */ template <class AccName> -AccumulationExpression genericParseSingleExpressionAccumulator( - boost::intrusive_ptr<ExpressionContext> expCtx, BSONElement elem, VariablesParseState vps) { +AccumulationExpression genericParseSingleExpressionAccumulator(ExpressionContext* const expCtx, + BSONElement elem, + VariablesParseState vps) { auto initializer = ExpressionConstant::create(expCtx, Value(BSONNULL)); auto argument = Expression::parseOperand(expCtx, elem, vps); return {initializer, argument, [expCtx]() { return AccName::create(expCtx); }}; @@ -144,7 +143,7 @@ AccumulationExpression genericParseSingleExpressionAccumulator( class AccumulationStatement { public: using Parser = std::function<AccumulationExpression( - boost::intrusive_ptr<ExpressionContext>, BSONElement, VariablesParseState)>; + ExpressionContext* const, BSONElement, VariablesParseState)>; AccumulationStatement(std::string fieldName, AccumulationExpression expr) : fieldName(std::move(fieldName)), expr(std::move(expr)) {} @@ -155,10 +154,9 @@ public: * * Throws an AssertionException if parsing fails. */ - static AccumulationStatement parseAccumulationStatement( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - const BSONElement& elem, - const VariablesParseState& vps); + static AccumulationStatement parseAccumulationStatement(ExpressionContext* const expCtx, + const BSONElement& elem, + const VariablesParseState& vps); /** * Registers an AccumulatorState with a parsing function, so that when an accumulator with the diff --git a/src/mongo/db/pipeline/accumulator.h b/src/mongo/db/pipeline/accumulator.h index e59ccb543da..2e70fbf6ad4 100644 --- a/src/mongo/db/pipeline/accumulator.h +++ b/src/mongo/db/pipeline/accumulator.h @@ -67,7 +67,7 @@ class AccumulatorState : public RefCountable { public: using Factory = std::function<boost::intrusive_ptr<AccumulatorState>()>; - AccumulatorState(const boost::intrusive_ptr<ExpressionContext>& expCtx) : _expCtx(expCtx) {} + AccumulatorState(ExpressionContext* const expCtx) : _expCtx(expCtx) {} /** Marks the beginning of a new group. The input is the result of evaluating * AccumulatorExpression::initializer, which can read from the group key. @@ -137,7 +137,7 @@ protected: /// Update subclass's internal state based on input virtual void processInternal(const Value& input, bool merging) = 0; - const boost::intrusive_ptr<ExpressionContext>& getExpressionContext() const { + auto getExpressionContext() const { return _expCtx; } @@ -145,7 +145,7 @@ protected: int _memUsageBytes = 0; private: - boost::intrusive_ptr<ExpressionContext> _expCtx; + ExpressionContext* _expCtx; }; class AccumulatorAddToSet final : public AccumulatorState { @@ -154,7 +154,7 @@ public: * Creates a new $addToSet accumulator. If no memory limit is given, defaults to the value of * the server parameter 'internalQueryMaxAddToSetBytes'. */ - AccumulatorAddToSet(const boost::intrusive_ptr<ExpressionContext>& expCtx, + AccumulatorAddToSet(ExpressionContext* const expCtx, boost::optional<int> maxMemoryUsageBytes = boost::none); void processInternal(const Value& input, bool merging) final; @@ -162,8 +162,7 @@ public: const char* getOpName() const final; void reset() final; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); bool isAssociative() const final { return true; @@ -180,15 +179,14 @@ private: class AccumulatorFirst final : public AccumulatorState { public: - explicit AccumulatorFirst(const boost::intrusive_ptr<ExpressionContext>& expCtx); + explicit AccumulatorFirst(ExpressionContext* const expCtx); void processInternal(const Value& input, bool merging) final; Value getValue(bool toBeMerged) final; const char* getOpName() const final; void reset() final; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); AccumulatorDocumentsNeeded documentsNeeded() const final { return AccumulatorDocumentsNeeded::kFirstDocument; @@ -201,15 +199,14 @@ private: class AccumulatorLast final : public AccumulatorState { public: - explicit AccumulatorLast(const boost::intrusive_ptr<ExpressionContext>& expCtx); + explicit AccumulatorLast(ExpressionContext* const expCtx); void processInternal(const Value& input, bool merging) final; Value getValue(bool toBeMerged) final; const char* getOpName() const final; void reset() final; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); AccumulatorDocumentsNeeded documentsNeeded() const final { return AccumulatorDocumentsNeeded::kLastDocument; @@ -221,15 +218,14 @@ private: class AccumulatorSum final : public AccumulatorState { public: - explicit AccumulatorSum(const boost::intrusive_ptr<ExpressionContext>& expCtx); + explicit AccumulatorSum(ExpressionContext* const expCtx); void processInternal(const Value& input, bool merging) final; Value getValue(bool toBeMerged) final; const char* getOpName() const final; void reset() final; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); bool isAssociative() const final { return true; @@ -252,7 +248,7 @@ public: MAX = -1, // Used to "scale" comparison. }; - AccumulatorMinMax(const boost::intrusive_ptr<ExpressionContext>& expCtx, Sense sense); + AccumulatorMinMax(ExpressionContext* const expCtx, Sense sense); void processInternal(const Value& input, bool merging) final; Value getValue(bool toBeMerged) final; @@ -274,18 +270,14 @@ private: class AccumulatorMax final : public AccumulatorMinMax { public: - explicit AccumulatorMax(const boost::intrusive_ptr<ExpressionContext>& expCtx) - : AccumulatorMinMax(expCtx, MAX) {} - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + explicit AccumulatorMax(ExpressionContext* const expCtx) : AccumulatorMinMax(expCtx, MAX) {} + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); }; class AccumulatorMin final : public AccumulatorMinMax { public: - explicit AccumulatorMin(const boost::intrusive_ptr<ExpressionContext>& expCtx) - : AccumulatorMinMax(expCtx, MIN) {} - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + explicit AccumulatorMin(ExpressionContext* const expCtx) : AccumulatorMinMax(expCtx, MIN) {} + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); }; class AccumulatorPush final : public AccumulatorState { @@ -294,7 +286,7 @@ public: * Creates a new $push accumulator. If no memory limit is given, defaults to the value of the * server parameter 'internalQueryMaxPushBytes'. */ - AccumulatorPush(const boost::intrusive_ptr<ExpressionContext>& expCtx, + AccumulatorPush(ExpressionContext* const expCtx, boost::optional<int> maxMemoryUsageBytes = boost::none); void processInternal(const Value& input, bool merging) final; @@ -302,8 +294,7 @@ public: const char* getOpName() const final; void reset() final; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); private: std::vector<Value> _array; @@ -312,15 +303,14 @@ private: class AccumulatorAvg final : public AccumulatorState { public: - explicit AccumulatorAvg(const boost::intrusive_ptr<ExpressionContext>& expCtx); + explicit AccumulatorAvg(ExpressionContext* const expCtx); void processInternal(const Value& input, bool merging) final; Value getValue(bool toBeMerged) final; const char* getOpName() const final; void reset() final; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); private: /** @@ -337,7 +327,7 @@ private: class AccumulatorStdDev : public AccumulatorState { public: - AccumulatorStdDev(const boost::intrusive_ptr<ExpressionContext>& expCtx, bool isSamp); + AccumulatorStdDev(ExpressionContext* const expCtx, bool isSamp); void processInternal(const Value& input, bool merging) final; Value getValue(bool toBeMerged) final; @@ -353,31 +343,28 @@ private: class AccumulatorStdDevPop final : public AccumulatorStdDev { public: - explicit AccumulatorStdDevPop(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit AccumulatorStdDevPop(ExpressionContext* const expCtx) : AccumulatorStdDev(expCtx, false) {} - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); }; class AccumulatorStdDevSamp final : public AccumulatorStdDev { public: - explicit AccumulatorStdDevSamp(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit AccumulatorStdDevSamp(ExpressionContext* const expCtx) : AccumulatorStdDev(expCtx, true) {} - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); }; class AccumulatorMergeObjects : public AccumulatorState { public: - AccumulatorMergeObjects(const boost::intrusive_ptr<ExpressionContext>& expCtx); + AccumulatorMergeObjects(ExpressionContext* const expCtx); void processInternal(const Value& input, bool merging) final; Value getValue(bool toBeMerged) final; const char* getOpName() const final; void reset() final; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx); private: MutableDocument _output; diff --git a/src/mongo/db/pipeline/accumulator_add_to_set.cpp b/src/mongo/db/pipeline/accumulator_add_to_set.cpp index 7af05eda870..d33e09b7f2d 100644 --- a/src/mongo/db/pipeline/accumulator_add_to_set.cpp +++ b/src/mongo/db/pipeline/accumulator_add_to_set.cpp @@ -79,7 +79,7 @@ Value AccumulatorAddToSet::getValue(bool toBeMerged) { return Value(vector<Value>(_set.begin(), _set.end())); } -AccumulatorAddToSet::AccumulatorAddToSet(const boost::intrusive_ptr<ExpressionContext>& expCtx, +AccumulatorAddToSet::AccumulatorAddToSet(ExpressionContext* const expCtx, boost::optional<int> maxMemoryUsageBytes) : AccumulatorState(expCtx), _set(expCtx->getValueComparator().makeUnorderedValueSet()), @@ -92,8 +92,7 @@ void AccumulatorAddToSet::reset() { _memUsageBytes = sizeof(*this); } -intrusive_ptr<AccumulatorState> AccumulatorAddToSet::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorAddToSet::create(ExpressionContext* const expCtx) { return new AccumulatorAddToSet(expCtx, boost::none); } diff --git a/src/mongo/db/pipeline/accumulator_avg.cpp b/src/mongo/db/pipeline/accumulator_avg.cpp index 1e7f55f5ab3..143ac643222 100644 --- a/src/mongo/db/pipeline/accumulator_avg.cpp +++ b/src/mongo/db/pipeline/accumulator_avg.cpp @@ -93,8 +93,7 @@ void AccumulatorAvg::processInternal(const Value& input, bool merging) { _count++; } -intrusive_ptr<AccumulatorState> AccumulatorAvg::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorAvg::create(ExpressionContext* const expCtx) { return new AccumulatorAvg(expCtx); } @@ -122,7 +121,7 @@ Value AccumulatorAvg::getValue(bool toBeMerged) { return Value(_nonDecimalTotal.getDouble() / static_cast<double>(_count)); } -AccumulatorAvg::AccumulatorAvg(const boost::intrusive_ptr<ExpressionContext>& expCtx) +AccumulatorAvg::AccumulatorAvg(ExpressionContext* const expCtx) : AccumulatorState(expCtx), _isDecimal(false), _count(0) { // This is a fixed size AccumulatorState so we never need to update this _memUsageBytes = sizeof(*this); diff --git a/src/mongo/db/pipeline/accumulator_first.cpp b/src/mongo/db/pipeline/accumulator_first.cpp index b48b9e2330e..cfb22aef242 100644 --- a/src/mongo/db/pipeline/accumulator_first.cpp +++ b/src/mongo/db/pipeline/accumulator_first.cpp @@ -58,7 +58,7 @@ Value AccumulatorFirst::getValue(bool toBeMerged) { return _first; } -AccumulatorFirst::AccumulatorFirst(const boost::intrusive_ptr<ExpressionContext>& expCtx) +AccumulatorFirst::AccumulatorFirst(ExpressionContext* const expCtx) : AccumulatorState(expCtx), _haveFirst(false) { _memUsageBytes = sizeof(*this); } @@ -70,8 +70,7 @@ void AccumulatorFirst::reset() { } -intrusive_ptr<AccumulatorState> AccumulatorFirst::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorFirst::create(ExpressionContext* const expCtx) { return new AccumulatorFirst(expCtx); } } // namespace mongo diff --git a/src/mongo/db/pipeline/accumulator_js_reduce.cpp b/src/mongo/db/pipeline/accumulator_js_reduce.cpp index ce09c01c8a4..af34132130f 100644 --- a/src/mongo/db/pipeline/accumulator_js_reduce.cpp +++ b/src/mongo/db/pipeline/accumulator_js_reduce.cpp @@ -38,7 +38,7 @@ namespace mongo { REGISTER_ACCUMULATOR(_internalJsReduce, AccumulatorInternalJsReduce::parseInternalJsReduce); AccumulationExpression AccumulatorInternalJsReduce::parseInternalJsReduce( - boost::intrusive_ptr<ExpressionContext> expCtx, BSONElement elem, VariablesParseState vps) { + ExpressionContext* const expCtx, BSONElement elem, VariablesParseState vps) { uassert(31326, str::stream() << kAccumulatorName << " requires a document argument, but found " << elem.type(), @@ -173,7 +173,7 @@ Value AccumulatorInternalJsReduce::getValue(bool toBeMerged) { } boost::intrusive_ptr<AccumulatorState> AccumulatorInternalJsReduce::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, StringData funcSource) { + ExpressionContext* const expCtx, StringData funcSource) { return make_intrusive<AccumulatorInternalJsReduce>(expCtx, funcSource); } @@ -194,7 +194,7 @@ Document AccumulatorInternalJsReduce::serialize(boost::intrusive_ptr<Expression> REGISTER_ACCUMULATOR(accumulator, AccumulatorJs::parse); boost::intrusive_ptr<AccumulatorState> AccumulatorJs::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, std::string init, std::string accumulate, std::string merge, @@ -206,7 +206,7 @@ boost::intrusive_ptr<AccumulatorState> AccumulatorJs::create( namespace { // Parses a constant expression of type String or Code. std::string parseFunction(StringData fieldName, - boost::intrusive_ptr<ExpressionContext> expCtx, + ExpressionContext* const expCtx, BSONElement elem, VariablesParseState vps) { boost::intrusive_ptr<Expression> expr = Expression::parseOperand(expCtx, elem, vps); @@ -240,7 +240,7 @@ Document AccumulatorJs::serialize(boost::intrusive_ptr<Expression> initializer, return DOC(getOpName() << args.freeze()); } -AccumulationExpression AccumulatorJs::parse(boost::intrusive_ptr<ExpressionContext> expCtx, +AccumulationExpression AccumulatorJs::parse(ExpressionContext* const expCtx, BSONElement elem, VariablesParseState vps) { /* @@ -336,7 +336,7 @@ Value AccumulatorJs::getValue(bool toBeMerged) { // Get the final value given the current accumulator state. if (_finalize) { - auto& expCtx = getExpressionContext(); + auto expCtx = getExpressionContext(); auto jsExec = expCtx->getJsExecWithScope(); auto func = makeJsFunc(expCtx, *_finalize); @@ -361,7 +361,7 @@ void AccumulatorJs::startNewGroup(Value const& input) { // constructor, and we clear it at the end of each group (in .reset()). invariant(!_state); - auto& expCtx = getExpressionContext(); + auto expCtx = getExpressionContext(); auto jsExec = expCtx->getJsExecWithScope(); auto func = makeJsFunc(expCtx, _init); @@ -420,7 +420,7 @@ void AccumulatorJs::reducePendingCalls() { // ($accumulator is not registered as an expression the way $sum and $avg and others are). invariant(!_pendingCalls.empty()); - auto& expCtx = getExpressionContext(); + auto expCtx = getExpressionContext(); auto jsExec = expCtx->getJsExecWithScope(); // Expose user functions. diff --git a/src/mongo/db/pipeline/accumulator_js_reduce.h b/src/mongo/db/pipeline/accumulator_js_reduce.h index 5843f893a18..fe87b2b359a 100644 --- a/src/mongo/db/pipeline/accumulator_js_reduce.h +++ b/src/mongo/db/pipeline/accumulator_js_reduce.h @@ -42,14 +42,14 @@ class AccumulatorInternalJsReduce final : public AccumulatorState { public: static constexpr auto kAccumulatorName = "$_internalJsReduce"_sd; - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, StringData funcSource); + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx, + StringData funcSource); - static AccumulationExpression parseInternalJsReduce( - boost::intrusive_ptr<ExpressionContext> expCtx, BSONElement elem, VariablesParseState vps); + static AccumulationExpression parseInternalJsReduce(ExpressionContext* const expCtx, + BSONElement elem, + VariablesParseState vps); - AccumulatorInternalJsReduce(const boost::intrusive_ptr<ExpressionContext>& expCtx, - StringData funcSource) + AccumulatorInternalJsReduce(ExpressionContext* const expCtx, StringData funcSource) : AccumulatorState(expCtx), _funcSource(funcSource) { _memUsageBytes = sizeof(*this); } @@ -85,14 +85,13 @@ public: // An AccumulatorState instance only owns its "static" arguments: those that don't need to be // evaluated per input document. - static boost::intrusive_ptr<AccumulatorState> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - std::string init, - std::string accumulate, - std::string merge, - boost::optional<std::string> finalize); - - static AccumulationExpression parse(boost::intrusive_ptr<ExpressionContext> expCtx, + static boost::intrusive_ptr<AccumulatorState> create(ExpressionContext* const expCtx, + std::string init, + std::string accumulate, + std::string merge, + boost::optional<std::string> finalize); + + static AccumulationExpression parse(ExpressionContext* const expCtx, BSONElement elem, VariablesParseState vps); @@ -106,7 +105,7 @@ public: void startNewGroup(Value const& input) final; private: - AccumulatorJs(const boost::intrusive_ptr<ExpressionContext>& expCtx, + AccumulatorJs(ExpressionContext* const expCtx, std::string init, std::string accumulate, std::string merge, diff --git a/src/mongo/db/pipeline/accumulator_js_test.cpp b/src/mongo/db/pipeline/accumulator_js_test.cpp index f2c471b5536..6ce4adae7c9 100644 --- a/src/mongo/db/pipeline/accumulator_js_test.cpp +++ b/src/mongo/db/pipeline/accumulator_js_test.cpp @@ -45,19 +45,19 @@ namespace { class MapReduceFixture : public ServiceContextMongoDTest { protected: - MapReduceFixture() : _expCtx((new ExpressionContextForTest())) { - _expCtx->mongoProcessInterface = std::make_shared<StandaloneProcessInterface>(nullptr); + MapReduceFixture() { + _expCtx.mongoProcessInterface = std::make_shared<StandaloneProcessInterface>(nullptr); } - boost::intrusive_ptr<ExpressionContextForTest>& getExpCtx() { - return _expCtx; + auto getExpCtx() { + return &_expCtx; } private: void setUp() override; void tearDown() override; - boost::intrusive_ptr<ExpressionContextForTest> _expCtx; + ExpressionContextForTest _expCtx; }; @@ -75,7 +75,7 @@ void MapReduceFixture::tearDown() { namespace InternalJsReduce { template <typename AccName> -static void assertProcessFailsWithCode(const boost::intrusive_ptr<ExpressionContext>& expCtx, +static void assertProcessFailsWithCode(ExpressionContext* const expCtx, const std::string& eval, Value processArgument, int code) { @@ -83,7 +83,7 @@ static void assertProcessFailsWithCode(const boost::intrusive_ptr<ExpressionCont ASSERT_THROWS_CODE(accum->process(processArgument, false), AssertionException, code); } -static void assertParsingFailsWithCode(const boost::intrusive_ptr<ExpressionContext>& expCtx, +static void assertParsingFailsWithCode(ExpressionContext* const expCtx, BSONElement elem, int code) { ASSERT_THROWS_CODE(AccumulatorInternalJsReduce::parseInternalJsReduce( @@ -93,7 +93,7 @@ static void assertParsingFailsWithCode(const boost::intrusive_ptr<ExpressionCont } template <typename AccName> -static void assertExpectedResults(const boost::intrusive_ptr<ExpressionContext>& expCtx, +static void assertExpectedResults(ExpressionContext* const expCtx, const std::string& eval, std::vector<Value> data, Value expectedResult) { diff --git a/src/mongo/db/pipeline/accumulator_last.cpp b/src/mongo/db/pipeline/accumulator_last.cpp index 14362e42cab..a1dade1aefb 100644 --- a/src/mongo/db/pipeline/accumulator_last.cpp +++ b/src/mongo/db/pipeline/accumulator_last.cpp @@ -54,8 +54,7 @@ Value AccumulatorLast::getValue(bool toBeMerged) { return _last; } -AccumulatorLast::AccumulatorLast(const boost::intrusive_ptr<ExpressionContext>& expCtx) - : AccumulatorState(expCtx) { +AccumulatorLast::AccumulatorLast(ExpressionContext* const expCtx) : AccumulatorState(expCtx) { _memUsageBytes = sizeof(*this); } @@ -64,8 +63,7 @@ void AccumulatorLast::reset() { _last = Value(); } -intrusive_ptr<AccumulatorState> AccumulatorLast::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorLast::create(ExpressionContext* const expCtx) { return new AccumulatorLast(expCtx); } } // namespace mongo diff --git a/src/mongo/db/pipeline/accumulator_merge_objects.cpp b/src/mongo/db/pipeline/accumulator_merge_objects.cpp index 6b23ae528a1..5eb03eed74b 100644 --- a/src/mongo/db/pipeline/accumulator_merge_objects.cpp +++ b/src/mongo/db/pipeline/accumulator_merge_objects.cpp @@ -49,13 +49,11 @@ const char* AccumulatorMergeObjects::getOpName() const { return "$mergeObjects"; } -intrusive_ptr<AccumulatorState> AccumulatorMergeObjects::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorMergeObjects::create(ExpressionContext* const expCtx) { return new AccumulatorMergeObjects(expCtx); } -AccumulatorMergeObjects::AccumulatorMergeObjects( - const boost::intrusive_ptr<ExpressionContext>& expCtx) +AccumulatorMergeObjects::AccumulatorMergeObjects(ExpressionContext* const expCtx) : AccumulatorState(expCtx) { _memUsageBytes = sizeof(*this); } diff --git a/src/mongo/db/pipeline/accumulator_min_max.cpp b/src/mongo/db/pipeline/accumulator_min_max.cpp index 265a84b7075..f6dc80f8766 100644 --- a/src/mongo/db/pipeline/accumulator_min_max.cpp +++ b/src/mongo/db/pipeline/accumulator_min_max.cpp @@ -69,8 +69,7 @@ Value AccumulatorMinMax::getValue(bool toBeMerged) { return _val; } -AccumulatorMinMax::AccumulatorMinMax(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Sense sense) +AccumulatorMinMax::AccumulatorMinMax(ExpressionContext* const expCtx, Sense sense) : AccumulatorState(expCtx), _sense(sense) { _memUsageBytes = sizeof(*this); } @@ -80,13 +79,11 @@ void AccumulatorMinMax::reset() { _memUsageBytes = sizeof(*this); } -intrusive_ptr<AccumulatorState> AccumulatorMin::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorMin::create(ExpressionContext* const expCtx) { return new AccumulatorMin(expCtx); } -intrusive_ptr<AccumulatorState> AccumulatorMax::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorMax::create(ExpressionContext* const expCtx) { return new AccumulatorMax(expCtx); } } // namespace mongo diff --git a/src/mongo/db/pipeline/accumulator_push.cpp b/src/mongo/db/pipeline/accumulator_push.cpp index 3a004dd9731..98744314735 100644 --- a/src/mongo/db/pipeline/accumulator_push.cpp +++ b/src/mongo/db/pipeline/accumulator_push.cpp @@ -81,7 +81,7 @@ Value AccumulatorPush::getValue(bool toBeMerged) { return Value(_array); } -AccumulatorPush::AccumulatorPush(const boost::intrusive_ptr<ExpressionContext>& expCtx, +AccumulatorPush::AccumulatorPush(ExpressionContext* const expCtx, boost::optional<int> maxMemoryUsageBytes) : AccumulatorState(expCtx), _maxMemUsageBytes(maxMemoryUsageBytes.value_or(internalQueryMaxPushBytes.load())) { @@ -93,8 +93,7 @@ void AccumulatorPush::reset() { _memUsageBytes = sizeof(*this); } -intrusive_ptr<AccumulatorState> AccumulatorPush::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorPush::create(ExpressionContext* const expCtx) { return new AccumulatorPush(expCtx, boost::none); } } // namespace mongo diff --git a/src/mongo/db/pipeline/accumulator_std_dev.cpp b/src/mongo/db/pipeline/accumulator_std_dev.cpp index cdd31b2c897..84588fef6f3 100644 --- a/src/mongo/db/pipeline/accumulator_std_dev.cpp +++ b/src/mongo/db/pipeline/accumulator_std_dev.cpp @@ -96,18 +96,15 @@ Value AccumulatorStdDev::getValue(bool toBeMerged) { } } -intrusive_ptr<AccumulatorState> AccumulatorStdDevSamp::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorStdDevSamp::create(ExpressionContext* const expCtx) { return new AccumulatorStdDevSamp(expCtx); } -intrusive_ptr<AccumulatorState> AccumulatorStdDevPop::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorStdDevPop::create(ExpressionContext* const expCtx) { return new AccumulatorStdDevPop(expCtx); } -AccumulatorStdDev::AccumulatorStdDev(const boost::intrusive_ptr<ExpressionContext>& expCtx, - bool isSamp) +AccumulatorStdDev::AccumulatorStdDev(ExpressionContext* const expCtx, bool isSamp) : AccumulatorState(expCtx), _isSamp(isSamp), _count(0), _mean(0), _m2(0) { // This is a fixed size AccumulatorState so we never need to update this _memUsageBytes = sizeof(*this); diff --git a/src/mongo/db/pipeline/accumulator_sum.cpp b/src/mongo/db/pipeline/accumulator_sum.cpp index 182f592ce3f..59f08945ef1 100644 --- a/src/mongo/db/pipeline/accumulator_sum.cpp +++ b/src/mongo/db/pipeline/accumulator_sum.cpp @@ -85,8 +85,7 @@ void AccumulatorSum::processInternal(const Value& input, bool merging) { } } -intrusive_ptr<AccumulatorState> AccumulatorSum::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx) { +intrusive_ptr<AccumulatorState> AccumulatorSum::create(ExpressionContext* const expCtx) { return new AccumulatorSum(expCtx); } @@ -127,8 +126,7 @@ Value AccumulatorSum::getValue(bool toBeMerged) { } } -AccumulatorSum::AccumulatorSum(const boost::intrusive_ptr<ExpressionContext>& expCtx) - : AccumulatorState(expCtx) { +AccumulatorSum::AccumulatorSum(ExpressionContext* const expCtx) : AccumulatorState(expCtx) { // This is a fixed size AccumulatorState so we never need to update this. _memUsageBytes = sizeof(*this); } diff --git a/src/mongo/db/pipeline/accumulator_test.cpp b/src/mongo/db/pipeline/accumulator_test.cpp index d3da839801f..dbae124306d 100644 --- a/src/mongo/db/pipeline/accumulator_test.cpp +++ b/src/mongo/db/pipeline/accumulator_test.cpp @@ -55,7 +55,7 @@ using std::string; */ template <typename AccName> static void assertExpectedResults( - const intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, std::initializer_list<std::pair<std::vector<Value>, Value>> operations) { for (auto&& op : operations) { try { @@ -103,9 +103,9 @@ static void assertExpectedResults( } TEST(Accumulators, Avg) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; assertExpectedResults<AccumulatorAvg>( - expCtx, + &expCtx, { // No documents evaluated. {{}, Value(BSONNULL)}, @@ -158,9 +158,9 @@ TEST(Accumulators, Avg) { } TEST(Accumulators, First) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; assertExpectedResults<AccumulatorFirst>( - expCtx, + &expCtx, {// No documents evaluated. {{}, Value()}, @@ -176,9 +176,9 @@ TEST(Accumulators, First) { } TEST(Accumulators, Last) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; assertExpectedResults<AccumulatorLast>( - expCtx, + &expCtx, {// No documents evaluated. {{}, Value()}, @@ -194,9 +194,9 @@ TEST(Accumulators, Last) { } TEST(Accumulators, Min) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; assertExpectedResults<AccumulatorMin>( - expCtx, + &expCtx, {// No documents evaluated. {{}, Value(BSONNULL)}, @@ -212,18 +212,18 @@ TEST(Accumulators, Min) { } TEST(Accumulators, MinRespectsCollation) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto collator = std::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kReverseString); - expCtx->setCollator(std::move(collator)); - assertExpectedResults<AccumulatorMin>(expCtx, + expCtx.setCollator(std::move(collator)); + assertExpectedResults<AccumulatorMin>(&expCtx, {{{Value("abc"_sd), Value("cba"_sd)}, Value("cba"_sd)}}); } TEST(Accumulators, Max) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; assertExpectedResults<AccumulatorMax>( - expCtx, + &expCtx, {// No documents evaluated. {{}, Value(BSONNULL)}, @@ -239,18 +239,18 @@ TEST(Accumulators, Max) { } TEST(Accumulators, MaxRespectsCollation) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto collator = std::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kReverseString); - expCtx->setCollator(std::move(collator)); - assertExpectedResults<AccumulatorMax>(expCtx, + expCtx.setCollator(std::move(collator)); + assertExpectedResults<AccumulatorMax>(&expCtx, {{{Value("abc"_sd), Value("cba"_sd)}, Value("abc"_sd)}}); } TEST(Accumulators, Sum) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; assertExpectedResults<AccumulatorSum>( - expCtx, + &expCtx, {// No documents evaluated. {{}, Value(0)}, @@ -337,19 +337,19 @@ TEST(Accumulators, Sum) { } TEST(Accumulators, AddToSetRespectsCollation) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto collator = std::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kAlwaysEqual); - expCtx->setCollator(std::move(collator)); - assertExpectedResults<AccumulatorAddToSet>(expCtx, + expCtx.setCollator(std::move(collator)); + assertExpectedResults<AccumulatorAddToSet>(&expCtx, {{{Value("a"_sd), Value("b"_sd), Value("c"_sd)}, Value(std::vector<Value>{Value("a"_sd)})}}); } TEST(Accumulators, AddToSetRespectsMaxMemoryConstraint) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; const int maxMemoryBytes = 20ull; - auto addToSet = AccumulatorAddToSet(expCtx, maxMemoryBytes); + auto addToSet = AccumulatorAddToSet(&expCtx, maxMemoryBytes); ASSERT_THROWS_CODE( addToSet.process( Value("This is a large string. Certainly we must be over 20 bytes by now"_sd), false), @@ -358,9 +358,9 @@ TEST(Accumulators, AddToSetRespectsMaxMemoryConstraint) { } TEST(Accumulators, PushRespectsMaxMemoryConstraint) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; const int maxMemoryBytes = 20ull; - auto addToSet = AccumulatorPush(expCtx, maxMemoryBytes); + auto addToSet = AccumulatorPush(&expCtx, maxMemoryBytes); ASSERT_THROWS_CODE( addToSet.process( Value("This is a large string. Certainly we must be over 20 bytes by now"_sd), false), @@ -371,52 +371,52 @@ TEST(Accumulators, PushRespectsMaxMemoryConstraint) { /* ------------------------- AccumulatorMergeObjects -------------------------- */ TEST(AccumulatorMergeObjects, MergingZeroObjectsShouldReturnEmptyDocument) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; - assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{}, {Value(Document({}))}}}); + assertExpectedResults<AccumulatorMergeObjects>(&expCtx, {{{}, {Value(Document({}))}}}); } TEST(AccumulatorMergeObjects, MergingWithSingleObjectShouldLeaveUnchanged) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; - assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{}, {Value(Document({}))}}}); + assertExpectedResults<AccumulatorMergeObjects>(&expCtx, {{{}, {Value(Document({}))}}}); auto doc = Value(Document({{"a", 1}, {"b", 1}})); - assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{doc}, doc}}); + assertExpectedResults<AccumulatorMergeObjects>(&expCtx, {{{doc}, doc}}); } TEST(AccumulatorMergeObjects, MergingDisjointObjectsShouldIncludeAllFields) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto first = Value(Document({{"a", 1}, {"b", 1}})); auto second = Value(Document({{"c", 1}})); assertExpectedResults<AccumulatorMergeObjects>( - expCtx, {{{first, second}, Value(Document({{"a", 1}, {"b", 1}, {"c", 1}}))}}); + &expCtx, {{{first, second}, Value(Document({{"a", 1}, {"b", 1}, {"c", 1}}))}}); } TEST(AccumulatorMergeObjects, MergingIntersectingObjectsShouldOverrideInOrderReceived) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto first = Value(Document({{"a", "oldValue"_sd}, {"b", 0}, {"c", 1}})); auto second = Value(Document({{"a", "newValue"_sd}})); assertExpectedResults<AccumulatorMergeObjects>( - expCtx, {{{first, second}, Value(Document({{"a", "newValue"_sd}, {"b", 0}, {"c", 1}}))}}); + &expCtx, {{{first, second}, Value(Document({{"a", "newValue"_sd}, {"b", 0}, {"c", 1}}))}}); } TEST(AccumulatorMergeObjects, MergingIntersectingEmbeddedObjectsShouldOverrideInOrderReceived) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto firstSubDoc = Document({{"a", 1}, {"b", 2}, {"c", 3}}); auto secondSubDoc = Document({{"a", 2}, {"b", 1}}); auto first = Value(Document({{"d", 1}, {"subDoc", firstSubDoc}})); auto second = Value(Document({{"subDoc", secondSubDoc}})); auto expected = Value(Document({{"d", 1}, {"subDoc", secondSubDoc}})); - assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{first, second}, expected}}); + assertExpectedResults<AccumulatorMergeObjects>(&expCtx, {{{first, second}, expected}}); } TEST(AccumulatorMergeObjects, MergingWithEmptyDocumentShouldIgnore) { - intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto first = Value(Document({{"a", 0}, {"b", 1}, {"c", 1}})); auto second = Value(Document({})); auto expected = Value(Document({{"a", 0}, {"b", 1}, {"c", 1}})); - assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{first, second}, expected}}); + assertExpectedResults<AccumulatorMergeObjects>(&expCtx, {{{first, second}, expected}}); } } // namespace AccumulatorTests diff --git a/src/mongo/db/pipeline/aggregation_context_fixture.h b/src/mongo/db/pipeline/aggregation_context_fixture.h index cd7d2887e99..287caae977c 100644 --- a/src/mongo/db/pipeline/aggregation_context_fixture.h +++ b/src/mongo/db/pipeline/aggregation_context_fixture.h @@ -53,11 +53,15 @@ public: _expCtx->tempDir = tempDir.path(); } - boost::intrusive_ptr<ExpressionContextForTest> getExpCtx() { + auto getExpCtx() { return _expCtx; } - OperationContext* getOpCtx() { + auto getExpCtxRaw() { + return _expCtx.get(); + } + + auto getOpCtx() { return _opCtx.get(); } diff --git a/src/mongo/db/pipeline/document_source_bucket.cpp b/src/mongo/db/pipeline/document_source_bucket.cpp index 3245d21b742..73386201792 100644 --- a/src/mongo/db/pipeline/document_source_bucket.cpp +++ b/src/mongo/db/pipeline/document_source_bucket.cpp @@ -45,10 +45,9 @@ REGISTER_MULTI_STAGE_ALIAS(bucket, DocumentSourceBucket::createFromBson); namespace { -intrusive_ptr<ExpressionConstant> getExpressionConstant( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expressionElem, - const VariablesParseState& vps) { +intrusive_ptr<ExpressionConstant> getExpressionConstant(ExpressionContext* const expCtx, + BSONElement expressionElem, + const VariablesParseState& vps) { auto expr = Expression::parseOperand(expCtx, expressionElem, vps)->optimize(); return dynamic_cast<ExpressionConstant*>(expr.get()); } @@ -95,7 +94,7 @@ list<intrusive_ptr<DocumentSource>> DocumentSourceBucket::createFromBson( argument.type() == BSONType::Array); for (auto&& boundaryElem : argument.embeddedObject()) { - auto exprConst = getExpressionConstant(pExpCtx, boundaryElem, vps); + auto exprConst = getExpressionConstant(pExpCtx.get(), boundaryElem, vps); uassert(40191, str::stream() << "The $bucket 'boundaries' field must be an array of " "constant values, but found value: " @@ -134,7 +133,7 @@ list<intrusive_ptr<DocumentSource>> DocumentSourceBucket::createFromBson( } else if ("default" == argName) { // If there is a default, make sure that it parses to a constant expression then add // default to switch. - auto exprConst = getExpressionConstant(pExpCtx, argument, vps); + auto exprConst = getExpressionConstant(pExpCtx.get(), argument, vps); uassert(40195, str::stream() << "The $bucket 'default' field must be a constant expression, but found: " diff --git a/src/mongo/db/pipeline/document_source_bucket_auto.cpp b/src/mongo/db/pipeline/document_source_bucket_auto.cpp index c6decbca69c..29199b451c9 100644 --- a/src/mongo/db/pipeline/document_source_bucket_auto.cpp +++ b/src/mongo/db/pipeline/document_source_bucket_auto.cpp @@ -53,10 +53,10 @@ boost::intrusive_ptr<Expression> parseGroupByExpression( const VariablesParseState& vps) { if (groupByField.type() == BSONType::Object && groupByField.embeddedObject().firstElementFieldName()[0] == '$') { - return Expression::parseObject(expCtx, groupByField.embeddedObject(), vps); + return Expression::parseObject(expCtx.get(), groupByField.embeddedObject(), vps); } else if (groupByField.type() == BSONType::String && groupByField.valueStringData()[0] == '$') { - return ExpressionFieldPath::parse(expCtx, groupByField.str(), vps); + return ExpressionFieldPath::parse(expCtx.get(), groupByField.str(), vps); } else { uasserted( 40239, @@ -431,9 +431,9 @@ intrusive_ptr<DocumentSourceBucketAuto> DocumentSourceBucketAuto::create( if (accumulationStatements.empty()) { accumulationStatements.emplace_back( "count", - AccumulationExpression(ExpressionConstant::create(pExpCtx, Value(BSONNULL)), - ExpressionConstant::create(pExpCtx, Value(1)), - [pExpCtx] { return AccumulatorSum::create(pExpCtx); })); + AccumulationExpression(ExpressionConstant::create(pExpCtx.get(), Value(BSONNULL)), + ExpressionConstant::create(pExpCtx.get(), Value(1)), + [pExpCtx] { return AccumulatorSum::create(pExpCtx.get()); })); } return new DocumentSourceBucketAuto(pExpCtx, groupByExpression, @@ -512,8 +512,8 @@ intrusive_ptr<DocumentSource> DocumentSourceBucketAuto::createFromBson( argument.type() == BSONType::Object); for (auto&& outputField : argument.embeddedObject()) { - auto stmt = - AccumulationStatement::parseAccumulationStatement(pExpCtx, outputField, vps); + auto stmt = AccumulationStatement::parseAccumulationStatement( + pExpCtx.get(), outputField, vps); stmt.expr.initializer = stmt.expr.initializer->optimize(); uassert(4544714, "Can't refer to the group key in $bucketAuto", diff --git a/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp b/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp index 970f8ecdfd7..09db9c459b4 100644 --- a/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp +++ b/src/mongo/db/pipeline/document_source_bucket_auto_test.cpp @@ -357,7 +357,7 @@ TEST_F(BucketAutoTests, ShouldBeAbleToCorrectlySpillToDisk) { const size_t maxMemoryUsageBytes = 1000; VariablesParseState vps = expCtx->variablesParseState; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$a", vps); + auto groupByExpression = ExpressionFieldPath::parse(expCtx.get(), "$a", vps); const int numBuckets = 2; auto bucketAutoStage = DocumentSourceBucketAuto::create( @@ -394,7 +394,7 @@ TEST_F(BucketAutoTests, ShouldBeAbleToPauseLoadingWhileSpilled) { const size_t maxMemoryUsageBytes = 1000; VariablesParseState vps = expCtx->variablesParseState; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$a", vps); + auto groupByExpression = ExpressionFieldPath::parse(expCtx.get(), "$a", vps); const int numBuckets = 2; auto bucketAutoStage = DocumentSourceBucketAuto::create( @@ -551,7 +551,7 @@ TEST_F(BucketAutoTests, FailsWithInvalidNumberOfBuckets) { const int numBuckets = 0; ASSERT_THROWS_CODE( DocumentSourceBucketAuto::create( - getExpCtx(), ExpressionConstant::create(getExpCtx(), Value(0)), numBuckets), + getExpCtx(), ExpressionConstant::create(getExpCtxRaw(), Value(0)), numBuckets), AssertionException, 40243); } @@ -636,7 +636,7 @@ void assertCannotSpillToDisk(const boost::intrusive_ptr<ExpressionContext>& expC const size_t maxMemoryUsageBytes = 1000; VariablesParseState vps = expCtx->variablesParseState; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$a", vps); + auto groupByExpression = ExpressionFieldPath::parse(expCtx.get(), "$a", vps); const int numBuckets = 2; auto bucketAutoStage = DocumentSourceBucketAuto::create( @@ -675,7 +675,7 @@ TEST_F(BucketAutoTests, ShouldCorrectlyTrackMemoryUsageBetweenPauses) { const size_t maxMemoryUsageBytes = 1000; VariablesParseState vps = expCtx->variablesParseState; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$a", vps); + auto groupByExpression = ExpressionFieldPath::parse(expCtx.get(), "$a", vps); const int numBuckets = 2; auto bucketAutoStage = DocumentSourceBucketAuto::create( diff --git a/src/mongo/db/pipeline/document_source_graph_lookup.cpp b/src/mongo/db/pipeline/document_source_graph_lookup.cpp index 98b795217fc..a84d1773a1f 100644 --- a/src/mongo/db/pipeline/document_source_graph_lookup.cpp +++ b/src/mongo/db/pipeline/document_source_graph_lookup.cpp @@ -525,7 +525,7 @@ intrusive_ptr<DocumentSource> DocumentSourceGraphLookUp::createFromBson( const auto argName = argument.fieldNameStringData(); if (argName == "startWith") { - startWith = Expression::parseOperand(expCtx, argument, vps); + startWith = Expression::parseOperand(expCtx.get(), argument, vps); continue; } else if (argName == "maxDepth") { uassert(40100, diff --git a/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp b/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp index 6453c4e2eb6..5d4fe741a6c 100644 --- a/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp +++ b/src/mongo/db/pipeline/document_source_graph_lookup_test.cpp @@ -93,7 +93,7 @@ TEST_F(DocumentSourceGraphLookUpTest, "results", "from", "to", - ExpressionFieldPath::create(expCtx, "_id"), + ExpressionFieldPath::create(expCtx.get(), "_id"), boost::none, boost::none, boost::none, @@ -122,7 +122,7 @@ TEST_F(DocumentSourceGraphLookUpTest, "results", "from", "to", - ExpressionFieldPath::create(expCtx, "_id"), + ExpressionFieldPath::create(expCtx.get(), "_id"), boost::none, boost::none, boost::none, @@ -152,7 +152,7 @@ TEST_F(DocumentSourceGraphLookUpTest, "results", "from", "to", - ExpressionFieldPath::create(expCtx, "_id"), + ExpressionFieldPath::create(expCtx.get(), "_id"), boost::none, boost::none, boost::none, @@ -195,7 +195,7 @@ TEST_F(DocumentSourceGraphLookUpTest, "results", "from", "to", - ExpressionFieldPath::create(expCtx, "_id"), + ExpressionFieldPath::create(expCtx.get(), "_id"), boost::none, boost::none, boost::none, @@ -259,7 +259,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldPropagatePauses) { "results", "from", "to", - ExpressionFieldPath::create(expCtx, "startPoint"), + ExpressionFieldPath::create(expCtx.get(), "startPoint"), boost::none, boost::none, boost::none, @@ -335,7 +335,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldPropagatePausesWhileUnwinding) { "results", "from", "to", - ExpressionFieldPath::create(expCtx, "startPoint"), + ExpressionFieldPath::create(expCtx.get(), "startPoint"), boost::none, boost::none, boost::none, @@ -394,7 +394,7 @@ TEST_F(DocumentSourceGraphLookUpTest, GraphLookupShouldReportAsFieldIsModified) "results", "from", "to", - ExpressionFieldPath::create(expCtx, "startPoint"), + ExpressionFieldPath::create(expCtx.get(), "startPoint"), boost::none, boost::none, boost::none, @@ -421,7 +421,7 @@ TEST_F(DocumentSourceGraphLookUpTest, GraphLookupShouldReportFieldsModifiedByAbs "results", "from", "to", - ExpressionFieldPath::create(expCtx, "startPoint"), + ExpressionFieldPath::create(expCtx.get(), "startPoint"), boost::none, boost::none, boost::none, @@ -453,10 +453,10 @@ TEST_F(DocumentSourceGraphLookUpTest, GraphLookupWithComparisonExpressionForStar "results", "from", "to", - ExpressionCompare::create(expCtx, + ExpressionCompare::create(expCtx.get(), ExpressionCompare::GT, - ExpressionFieldPath::create(expCtx, "a"), - ExpressionFieldPath::create(expCtx, "b")), + ExpressionFieldPath::create(expCtx.get(), "a"), + ExpressionFieldPath::create(expCtx.get(), "b")), boost::none, boost::none, boost::none, @@ -516,7 +516,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldExpandArraysAtEndOfConnectFromField) "results", "to", "_id", - ExpressionFieldPath::create(expCtx, "startVal"), + ExpressionFieldPath::create(expCtx.get(), "startVal"), boost::none, boost::none, boost::none, @@ -589,7 +589,7 @@ TEST_F(DocumentSourceGraphLookUpTest, ShouldNotExpandArraysWithinArraysAtEndOfCo "results", "connectedTo", "coordinate", - ExpressionFieldPath::create(expCtx, "startVal"), + ExpressionFieldPath::create(expCtx.get(), "startVal"), boost::none, boost::none, boost::none, diff --git a/src/mongo/db/pipeline/document_source_group.cpp b/src/mongo/db/pipeline/document_source_group.cpp index 230162d2f51..582ac6c8c41 100644 --- a/src/mongo/db/pipeline/document_source_group.cpp +++ b/src/mongo/db/pipeline/document_source_group.cpp @@ -372,23 +372,23 @@ intrusive_ptr<Expression> parseIdExpression(const intrusive_ptr<ExpressionContex if (groupField.type() == Object) { // {_id: {}} is treated as grouping on a constant, not an expression if (groupField.Obj().isEmpty()) { - return ExpressionConstant::create(expCtx, Value(groupField)); + return ExpressionConstant::create(expCtx.get(), Value(groupField)); } const BSONObj idKeyObj = groupField.Obj(); if (idKeyObj.firstElementFieldName()[0] == '$') { // grouping on a $op expression - return Expression::parseObject(expCtx, idKeyObj, vps); + return Expression::parseObject(expCtx.get(), idKeyObj, vps); } else { for (auto&& field : idKeyObj) { uassert(17390, "$group does not support inclusion-style expressions", !field.isNumber() && field.type() != Bool); } - return ExpressionObject::parse(expCtx, idKeyObj, vps); + return ExpressionObject::parse(expCtx.get(), idKeyObj, vps); } } else { - return Expression::parseOperand(expCtx, groupField, vps); + return Expression::parseOperand(expCtx.get(), groupField, vps); } } @@ -437,7 +437,7 @@ intrusive_ptr<DocumentSource> DocumentSourceGroup::createFromBson( } else { // Any other field will be treated as an accumulator specification. pGroup->addAccumulator( - AccumulationStatement::parseAccumulationStatement(pExpCtx, groupField, vps)); + AccumulationStatement::parseAccumulationStatement(pExpCtx.get(), groupField, vps)); } } @@ -707,7 +707,7 @@ boost::optional<DocumentSource::DistributedPlanLogic> DocumentSourceGroup::distr VariablesParseState vps = pExpCtx->variablesParseState; /* the merger will use the same grouping key */ - mergingGroup->setIdExpression(ExpressionFieldPath::parse(pExpCtx, "$$ROOT._id", vps)); + mergingGroup->setIdExpression(ExpressionFieldPath::parse(pExpCtx.get(), "$$ROOT._id", vps)); for (auto&& accumulatedField : _accumulatedFields) { // The merger's output field names will be the same, as will the accumulator factories. @@ -715,8 +715,8 @@ boost::optional<DocumentSource::DistributedPlanLogic> DocumentSourceGroup::distr // original accumulator may be collecting an expression based on a field expression or // constant. Here, we accumulate the output of the same name from the prior group. auto copiedAccumulatedField = accumulatedField; - copiedAccumulatedField.expr.argument = - ExpressionFieldPath::parse(pExpCtx, "$$ROOT." + copiedAccumulatedField.fieldName, vps); + copiedAccumulatedField.expr.argument = ExpressionFieldPath::parse( + pExpCtx.get(), "$$ROOT." + copiedAccumulatedField.fieldName, vps); mergingGroup->addAccumulator(copiedAccumulatedField); } @@ -794,7 +794,7 @@ DocumentSourceGroup::rewriteGroupAsTransformOnFirstDocument() const { } std::vector<std::pair<std::string, boost::intrusive_ptr<Expression>>> fields; - fields.push_back(std::make_pair("_id", ExpressionFieldPath::create(pExpCtx, groupId))); + fields.push_back(std::make_pair("_id", ExpressionFieldPath::create(pExpCtx.get(), groupId))); for (auto&& accumulator : _accumulatedFields) { fields.push_back(std::make_pair(accumulator.fieldName, accumulator.expr.argument)); diff --git a/src/mongo/db/pipeline/document_source_group_test.cpp b/src/mongo/db/pipeline/document_source_group_test.cpp index 584052ad8f6..568f31e08ff 100644 --- a/src/mongo/db/pipeline/document_source_group_test.cpp +++ b/src/mongo/db/pipeline/document_source_group_test.cpp @@ -75,10 +75,10 @@ TEST_F(DocumentSourceGroupTest, ShouldBeAbleToPauseLoading) { // This is the only way to do this in a debug build. auto&& parser = AccumulationStatement::getParser("$sum", boost::none); auto accumulatorArg = BSON("" << 1); - auto accExpr = parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + auto accExpr = parser(expCtx.get(), accumulatorArg.firstElement(), expCtx->variablesParseState); AccumulationStatement countStatement{"count", accExpr}; auto group = DocumentSourceGroup::create( - expCtx, ExpressionConstant::create(expCtx, Value(BSONNULL)), {countStatement}); + expCtx, ExpressionConstant::create(expCtx.get(), Value(BSONNULL)), {countStatement}); auto mock = DocumentSourceMock::createForTest({DocumentSource::GetNextResult::makePauseExecution(), Document(), @@ -113,10 +113,10 @@ TEST_F(DocumentSourceGroupTest, ShouldBeAbleToPauseLoadingWhileSpilled) { auto&& parser = AccumulationStatement::getParser("$push", boost::none); auto accumulatorArg = BSON("" << "$largeStr"); - auto accExpr = parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + auto accExpr = parser(expCtx.get(), accumulatorArg.firstElement(), expCtx->variablesParseState); AccumulationStatement pushStatement{"spaceHog", accExpr}; auto groupByExpression = - ExpressionFieldPath::parse(expCtx, "$_id", expCtx->variablesParseState); + ExpressionFieldPath::parse(expCtx.get(), "$_id", expCtx->variablesParseState); auto group = DocumentSourceGroup::create( expCtx, groupByExpression, {pushStatement}, maxMemoryUsageBytes); @@ -156,10 +156,10 @@ TEST_F(DocumentSourceGroupTest, ShouldErrorIfNotAllowedToSpillToDiskAndResultSet auto&& parser = AccumulationStatement::getParser("$push", boost::none); auto accumulatorArg = BSON("" << "$largeStr"); - auto accExpr = parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + auto accExpr = parser(expCtx.get(), accumulatorArg.firstElement(), expCtx->variablesParseState); AccumulationStatement pushStatement{"spaceHog", accExpr}; auto groupByExpression = - ExpressionFieldPath::parse(expCtx, "$_id", expCtx->variablesParseState); + ExpressionFieldPath::parse(expCtx.get(), "$_id", expCtx->variablesParseState); auto group = DocumentSourceGroup::create( expCtx, groupByExpression, {pushStatement}, maxMemoryUsageBytes); @@ -182,10 +182,10 @@ TEST_F(DocumentSourceGroupTest, ShouldCorrectlyTrackMemoryUsageBetweenPauses) { auto&& parser = AccumulationStatement::getParser("$push", boost::none); auto accumulatorArg = BSON("" << "$largeStr"); - auto accExpr = parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + auto accExpr = parser(expCtx.get(), accumulatorArg.firstElement(), expCtx->variablesParseState); AccumulationStatement pushStatement{"spaceHog", accExpr}; auto groupByExpression = - ExpressionFieldPath::parse(expCtx, "$_id", expCtx->variablesParseState); + ExpressionFieldPath::parse(expCtx.get(), "$_id", expCtx->variablesParseState); auto group = DocumentSourceGroup::create( expCtx, groupByExpression, {pushStatement}, maxMemoryUsageBytes); @@ -209,7 +209,7 @@ TEST_F(DocumentSourceGroupTest, ShouldCorrectlyTrackMemoryUsageBetweenPauses) { TEST_F(DocumentSourceGroupTest, ShouldReportSingleFieldGroupKeyAsARename) { auto expCtx = getExpCtx(); VariablesParseState vps = expCtx->variablesParseState; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$x", vps); + auto groupByExpression = ExpressionFieldPath::parse(expCtx.get(), "$x", vps); auto group = DocumentSourceGroup::create(expCtx, groupByExpression, {}); auto modifiedPathsRet = group->getModifiedPaths(); ASSERT(modifiedPathsRet.type == DocumentSource::GetModPathsReturn::Type::kAllExcept); @@ -221,9 +221,9 @@ TEST_F(DocumentSourceGroupTest, ShouldReportSingleFieldGroupKeyAsARename) { TEST_F(DocumentSourceGroupTest, ShouldReportMultipleFieldGroupKeysAsARename) { auto expCtx = getExpCtx(); VariablesParseState vps = expCtx->variablesParseState; - auto x = ExpressionFieldPath::parse(expCtx, "$x", vps); - auto y = ExpressionFieldPath::parse(expCtx, "$y", vps); - auto groupByExpression = ExpressionObject::create(expCtx, {{"x", x}, {"y", y}}); + auto x = ExpressionFieldPath::parse(expCtx.get(), "$x", vps); + auto y = ExpressionFieldPath::parse(expCtx.get(), "$y", vps); + auto groupByExpression = ExpressionObject::create(expCtx.get(), {{"x", x}, {"y", y}}); auto group = DocumentSourceGroup::create(expCtx, groupByExpression, {}); auto modifiedPathsRet = group->getModifiedPaths(); ASSERT(modifiedPathsRet.type == DocumentSource::GetModPathsReturn::Type::kAllExcept); @@ -236,7 +236,7 @@ TEST_F(DocumentSourceGroupTest, ShouldReportMultipleFieldGroupKeysAsARename) { TEST_F(DocumentSourceGroupTest, ShouldNotReportDottedGroupKeyAsARename) { auto expCtx = getExpCtx(); VariablesParseState vps = expCtx->variablesParseState; - auto xDotY = ExpressionFieldPath::parse(expCtx, "$x.y", vps); + auto xDotY = ExpressionFieldPath::parse(expCtx.get(), "$x.y", vps); auto group = DocumentSourceGroup::create(expCtx, xDotY, {}); auto modifiedPathsRet = group->getModifiedPaths(); ASSERT(modifiedPathsRet.type == DocumentSource::GetModPathsReturn::Type::kAllExcept); diff --git a/src/mongo/db/pipeline/document_source_lookup.cpp b/src/mongo/db/pipeline/document_source_lookup.cpp index 56b0cec6597..af45df02f2f 100644 --- a/src/mongo/db/pipeline/document_source_lookup.cpp +++ b/src/mongo/db/pipeline/document_source_lookup.cpp @@ -101,7 +101,7 @@ DocumentSourceLookUp::DocumentSourceLookUp(NamespaceString fromNs, _letVariables.emplace_back( varName.toString(), - Expression::parseOperand(expCtx, varElem, expCtx->variablesParseState), + Expression::parseOperand(expCtx.get(), varElem, expCtx->variablesParseState), _variablesParseState.defineVariable(varName)); } diff --git a/src/mongo/db/pipeline/document_source_merge.cpp b/src/mongo/db/pipeline/document_source_merge.cpp index 456d0615662..256f23f01a2 100644 --- a/src/mongo/db/pipeline/document_source_merge.cpp +++ b/src/mongo/db/pipeline/document_source_merge.cpp @@ -374,7 +374,7 @@ DocumentSourceMerge::DocumentSourceMerge(NamespaceString outputNs, _letVariables->emplace( varName.toString(), - Expression::parseOperand(expCtx, varElem, expCtx->variablesParseState)); + Expression::parseOperand(expCtx.get(), varElem, expCtx->variablesParseState)); } } } diff --git a/src/mongo/db/pipeline/document_source_redact.cpp b/src/mongo/db/pipeline/document_source_redact.cpp index fbb221594b6..efe6316c69b 100644 --- a/src/mongo/db/pipeline/document_source_redact.cpp +++ b/src/mongo/db/pipeline/document_source_redact.cpp @@ -179,7 +179,7 @@ intrusive_ptr<DocumentSource> DocumentSourceRedact::createFromBson( Variables::Id decendId = vps.defineVariable("DESCEND"); Variables::Id pruneId = vps.defineVariable("PRUNE"); Variables::Id keepId = vps.defineVariable("KEEP"); - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, elem, vps); + intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx.get(), elem, vps); intrusive_ptr<DocumentSourceRedact> source = new DocumentSourceRedact(expCtx, expression); // TODO figure out how much of this belongs in constructor and how much here. diff --git a/src/mongo/db/pipeline/document_source_replace_root.cpp b/src/mongo/db/pipeline/document_source_replace_root.cpp index eda91efb23c..2d3e1de27af 100644 --- a/src/mongo/db/pipeline/document_source_replace_root.cpp +++ b/src/mongo/db/pipeline/document_source_replace_root.cpp @@ -86,7 +86,7 @@ intrusive_ptr<DocumentSource> DocumentSourceReplaceRoot::createFromBson( const auto stageName = elem.fieldNameStringData(); auto newRootExpression = [&]() { if (stageName == kAliasNameReplaceWith) { - return Expression::parseOperand(expCtx, elem, expCtx->variablesParseState); + return Expression::parseOperand(expCtx.get(), elem, expCtx->variablesParseState); } invariant( @@ -106,7 +106,7 @@ intrusive_ptr<DocumentSource> DocumentSourceReplaceRoot::createFromBson( // to adapt the two. BSONObj parsingBson = BSON("newRoot" << spec.getNewRoot()); return Expression::parseOperand( - expCtx, parsingBson.firstElement(), expCtx->variablesParseState); + expCtx.get(), parsingBson.firstElement(), expCtx->variablesParseState); }(); // Whether this was specified as $replaceWith or $replaceRoot, always use the name $replaceRoot diff --git a/src/mongo/db/pipeline/expression.cpp b/src/mongo/db/pipeline/expression.cpp index 55d3b0cbf3f..1ef7406c421 100644 --- a/src/mongo/db/pipeline/expression.cpp +++ b/src/mongo/db/pipeline/expression.cpp @@ -88,10 +88,9 @@ string Expression::removeFieldPrefix(const string& prefixedField) { return string(pPrefixedField + 1); } -intrusive_ptr<Expression> Expression::parseObject( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONObj obj, - const VariablesParseState& vps) { +intrusive_ptr<Expression> Expression::parseObject(ExpressionContext* const expCtx, + BSONObj obj, + const VariablesParseState& vps) { if (obj.isEmpty()) { return ExpressionObject::create(expCtx, {}); } @@ -124,10 +123,9 @@ void Expression::registerExpression( parserMap[key] = {parser, requiredMinVersion}; } -intrusive_ptr<Expression> Expression::parseExpression( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONObj obj, - const VariablesParseState& vps) { +intrusive_ptr<Expression> Expression::parseExpression(ExpressionContext* const expCtx, + BSONObj obj, + const VariablesParseState& vps) { uassert(15983, str::stream() << "An object representing an expression must have exactly one " "field: " @@ -157,10 +155,9 @@ intrusive_ptr<Expression> Expression::parseExpression( return entry.parser(expCtx, obj.firstElement(), vps); } -Expression::ExpressionVector ExpressionNary::parseArguments( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement exprElement, - const VariablesParseState& vps) { +Expression::ExpressionVector ExpressionNary::parseArguments(ExpressionContext* const expCtx, + BSONElement exprElement, + const VariablesParseState& vps) { ExpressionVector out; if (exprElement.type() == Array) { BSONForEach(elem, exprElement.Obj()) { @@ -173,10 +170,9 @@ Expression::ExpressionVector ExpressionNary::parseArguments( return out; } -intrusive_ptr<Expression> Expression::parseOperand( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement exprElement, - const VariablesParseState& vps) { +intrusive_ptr<Expression> Expression::parseOperand(ExpressionContext* const expCtx, + BSONElement exprElement, + const VariablesParseState& vps) { BSONType type = exprElement.type(); if (type == String && exprElement.valuestr()[0] == '$') { @@ -755,11 +751,11 @@ const char* ExpressionCeil::getOpName() const { /* -------------------- ExpressionCoerceToBool ------------------------- */ intrusive_ptr<ExpressionCoerceToBool> ExpressionCoerceToBool::create( - const intrusive_ptr<ExpressionContext>& expCtx, intrusive_ptr<Expression> pExpression) { + ExpressionContext* const expCtx, intrusive_ptr<Expression> pExpression) { return new ExpressionCoerceToBool(expCtx, std::move(pExpression)); } -ExpressionCoerceToBool::ExpressionCoerceToBool(const intrusive_ptr<ExpressionContext>& expCtx, +ExpressionCoerceToBool::ExpressionCoerceToBool(ExpressionContext* const expCtx, intrusive_ptr<Expression> pExpression) : Expression(expCtx, {std::move(pExpression)}), pExpression(_children[0]) {} @@ -802,7 +798,7 @@ namespace { struct BoundOp { ExpressionCompare::CmpOp op; - auto operator()(const boost::intrusive_ptr<ExpressionContext>& expCtx, + auto operator()(ExpressionContext* const expCtx, BSONElement bsonExpr, const VariablesParseState& vps) const { return ExpressionCompare::parse(expCtx, std::move(bsonExpr), vps, op); @@ -818,11 +814,10 @@ REGISTER_EXPRESSION(lt, BoundOp{ExpressionCompare::LT}); REGISTER_EXPRESSION(lte, BoundOp{ExpressionCompare::LTE}); REGISTER_EXPRESSION(ne, BoundOp{ExpressionCompare::NE}); -intrusive_ptr<Expression> ExpressionCompare::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement bsonExpr, - const VariablesParseState& vps, - CmpOp op) { +intrusive_ptr<Expression> ExpressionCompare::parse(ExpressionContext* const expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps, + CmpOp op) { intrusive_ptr<ExpressionCompare> expr = new ExpressionCompare(expCtx, op); ExpressionVector args = parseArguments(expCtx, bsonExpr, vps); expr->validateArguments(args); @@ -831,7 +826,7 @@ intrusive_ptr<Expression> ExpressionCompare::parse( } boost::intrusive_ptr<ExpressionCompare> ExpressionCompare::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, CmpOp cmpOp, const boost::intrusive_ptr<Expression>& exprLeft, const boost::intrusive_ptr<Expression>& exprRight) { @@ -949,10 +944,9 @@ Value ExpressionCond::evaluate(const Document& root, Variables* variables) const return _children[idx]->evaluate(root, variables); } -intrusive_ptr<Expression> ExpressionCond::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionCond::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { if (expr.type() != Object) { return Base::parse(expCtx, expr, vps); } @@ -989,22 +983,20 @@ const char* ExpressionCond::getOpName() const { /* ---------------------- ExpressionConstant --------------------------- */ -intrusive_ptr<Expression> ExpressionConstant::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement exprElement, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionConstant::parse(ExpressionContext* const expCtx, + BSONElement exprElement, + const VariablesParseState& vps) { return new ExpressionConstant(expCtx, Value(exprElement)); } -intrusive_ptr<ExpressionConstant> ExpressionConstant::create( - const intrusive_ptr<ExpressionContext>& expCtx, const Value& value) { +intrusive_ptr<ExpressionConstant> ExpressionConstant::create(ExpressionContext* const expCtx, + const Value& value) { intrusive_ptr<ExpressionConstant> pEC(new ExpressionConstant(expCtx, value)); return pEC; } -ExpressionConstant::ExpressionConstant(const boost::intrusive_ptr<ExpressionContext>& expCtx, - const Value& value) +ExpressionConstant::ExpressionConstant(ExpressionContext* const expCtx, const Value& value) : Expression(expCtx), _value(value) {} @@ -1065,10 +1057,9 @@ boost::optional<TimeZone> makeTimeZone(const TimeZoneDatabase* tzdb, REGISTER_EXPRESSION(dateFromParts, ExpressionDateFromParts::parse); -intrusive_ptr<Expression> ExpressionDateFromParts::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionDateFromParts::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(40519, "$dateFromParts only supports an object as its argument", @@ -1146,19 +1137,18 @@ intrusive_ptr<Expression> ExpressionDateFromParts::parse( timeZoneElem ? parseOperand(expCtx, timeZoneElem, vps) : nullptr); } -ExpressionDateFromParts::ExpressionDateFromParts( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - intrusive_ptr<Expression> year, - intrusive_ptr<Expression> month, - intrusive_ptr<Expression> day, - intrusive_ptr<Expression> hour, - intrusive_ptr<Expression> minute, - intrusive_ptr<Expression> second, - intrusive_ptr<Expression> millisecond, - intrusive_ptr<Expression> isoWeekYear, - intrusive_ptr<Expression> isoWeek, - intrusive_ptr<Expression> isoDayOfWeek, - intrusive_ptr<Expression> timeZone) +ExpressionDateFromParts::ExpressionDateFromParts(ExpressionContext* const expCtx, + intrusive_ptr<Expression> year, + intrusive_ptr<Expression> month, + intrusive_ptr<Expression> day, + intrusive_ptr<Expression> hour, + intrusive_ptr<Expression> minute, + intrusive_ptr<Expression> second, + intrusive_ptr<Expression> millisecond, + intrusive_ptr<Expression> isoWeekYear, + intrusive_ptr<Expression> isoWeek, + intrusive_ptr<Expression> isoDayOfWeek, + intrusive_ptr<Expression> timeZone) : Expression(expCtx, {std::move(year), std::move(month), @@ -1405,10 +1395,9 @@ void ExpressionDateFromParts::_doAddDependencies(DepsTracker* deps) const { /* ---------------------- ExpressionDateFromString --------------------- */ REGISTER_EXPRESSION(dateFromString, ExpressionDateFromString::parse); -intrusive_ptr<Expression> ExpressionDateFromString::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionDateFromString::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(40540, str::stream() << "$dateFromString only supports an object as an argument, found: " @@ -1449,13 +1438,12 @@ intrusive_ptr<Expression> ExpressionDateFromString::parse( onErrorElem ? parseOperand(expCtx, onErrorElem, vps) : nullptr); } -ExpressionDateFromString::ExpressionDateFromString( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - intrusive_ptr<Expression> dateString, - intrusive_ptr<Expression> timeZone, - intrusive_ptr<Expression> format, - intrusive_ptr<Expression> onNull, - intrusive_ptr<Expression> onError) +ExpressionDateFromString::ExpressionDateFromString(ExpressionContext* const expCtx, + intrusive_ptr<Expression> dateString, + intrusive_ptr<Expression> timeZone, + intrusive_ptr<Expression> format, + intrusive_ptr<Expression> onNull, + intrusive_ptr<Expression> onError) : Expression(expCtx, {std::move(dateString), std::move(timeZone), @@ -1588,10 +1576,9 @@ void ExpressionDateFromString::_doAddDependencies(DepsTracker* deps) const { /* ---------------------- ExpressionDateToParts ----------------------- */ REGISTER_EXPRESSION(dateToParts, ExpressionDateToParts::parse); -intrusive_ptr<Expression> ExpressionDateToParts::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionDateToParts::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(40524, "$dateToParts only supports an object as its argument", @@ -1627,7 +1614,7 @@ intrusive_ptr<Expression> ExpressionDateToParts::parse( isoDateElem ? parseOperand(expCtx, isoDateElem, vps) : nullptr); } -ExpressionDateToParts::ExpressionDateToParts(const boost::intrusive_ptr<ExpressionContext>& expCtx, +ExpressionDateToParts::ExpressionDateToParts(ExpressionContext* const expCtx, intrusive_ptr<Expression> date, intrusive_ptr<Expression> timeZone, intrusive_ptr<Expression> iso8601) @@ -1737,10 +1724,9 @@ void ExpressionDateToParts::_doAddDependencies(DepsTracker* deps) const { /* ---------------------- ExpressionDateToString ----------------------- */ REGISTER_EXPRESSION(dateToString, ExpressionDateToString::parse); -intrusive_ptr<Expression> ExpressionDateToString::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionDateToString::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { verify(expr.fieldNameStringData() == "$dateToString"); uassert(18629, @@ -1776,12 +1762,11 @@ intrusive_ptr<Expression> ExpressionDateToString::parse( onNullElem ? parseOperand(expCtx, onNullElem, vps) : nullptr); } -ExpressionDateToString::ExpressionDateToString( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - intrusive_ptr<Expression> date, - intrusive_ptr<Expression> format, - intrusive_ptr<Expression> timeZone, - intrusive_ptr<Expression> onNull) +ExpressionDateToString::ExpressionDateToString(ExpressionContext* const expCtx, + intrusive_ptr<Expression> date, + intrusive_ptr<Expression> format, + intrusive_ptr<Expression> timeZone, + intrusive_ptr<Expression> onNull) : Expression(expCtx, {std::move(format), std::move(date), std::move(timeZone), std::move(onNull)}), _format(_children[0]), @@ -1932,13 +1917,13 @@ const char* ExpressionExp::getOpName() const { /* ---------------------- ExpressionObject --------------------------- */ -ExpressionObject::ExpressionObject(const boost::intrusive_ptr<ExpressionContext>& expCtx, +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)) {} boost::intrusive_ptr<ExpressionObject> ExpressionObject::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, std::vector<std::pair<std::string, boost::intrusive_ptr<Expression>>>&& expressionsWithChildrenInPlace) { std::vector<boost::intrusive_ptr<Expression>> children; @@ -1956,10 +1941,9 @@ boost::intrusive_ptr<ExpressionObject> ExpressionObject::create( return new ExpressionObject(expCtx, std::move(children), std::move(expressions)); } -intrusive_ptr<ExpressionObject> ExpressionObject::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONObj obj, - const VariablesParseState& vps) { +intrusive_ptr<ExpressionObject> ExpressionObject::parse(ExpressionContext* const expCtx, + BSONObj obj, + const VariablesParseState& vps) { // Make sure we don't have any duplicate field names. stdx::unordered_set<string> specifiedFields; @@ -2046,16 +2030,15 @@ Expression::ComputedPaths ExpressionObject::getComputedPaths(const std::string& /* --------------------- ExpressionFieldPath --------------------------- */ // this is the old deprecated version only used by tests not using variables -intrusive_ptr<ExpressionFieldPath> ExpressionFieldPath::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, const string& fieldPath) { +intrusive_ptr<ExpressionFieldPath> ExpressionFieldPath::create(ExpressionContext* const expCtx, + const string& fieldPath) { return new ExpressionFieldPath(expCtx, "CURRENT." + fieldPath, Variables::kRootId); } // this is the new version that supports every syntax -intrusive_ptr<ExpressionFieldPath> ExpressionFieldPath::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - const string& raw, - const VariablesParseState& vps) { +intrusive_ptr<ExpressionFieldPath> ExpressionFieldPath::parse(ExpressionContext* const expCtx, + const string& raw, + const VariablesParseState& vps) { uassert(16873, str::stream() << "FieldPath '" << raw << "' doesn't start with $", raw.c_str()[0] == '$'); // c_str()[0] is always a valid reference. @@ -2078,7 +2061,7 @@ intrusive_ptr<ExpressionFieldPath> ExpressionFieldPath::parse( } } -ExpressionFieldPath::ExpressionFieldPath(const boost::intrusive_ptr<ExpressionContext>& expCtx, +ExpressionFieldPath::ExpressionFieldPath(ExpressionContext* const expCtx, const string& theFieldPath, Variables::Id variable) : Expression(expCtx), _fieldPath(theFieldPath), _variable(variable) {} @@ -2215,10 +2198,9 @@ Expression::ComputedPaths ExpressionFieldPath::getComputedPaths(const std::strin /* ------------------------- ExpressionFilter ----------------------------- */ REGISTER_EXPRESSION(filter, ExpressionFilter::parse); -intrusive_ptr<Expression> ExpressionFilter::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn) { +intrusive_ptr<Expression> ExpressionFilter::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn) { verify(expr.fieldNameStringData() == "$filter"); uassert(28646, "$filter only supports an object as its argument", expr.type() == Object); @@ -2262,7 +2244,7 @@ intrusive_ptr<Expression> ExpressionFilter::parse( expCtx, std::move(varName), varId, std::move(input), std::move(cond)); } -ExpressionFilter::ExpressionFilter(const boost::intrusive_ptr<ExpressionContext>& expCtx, +ExpressionFilter::ExpressionFilter(ExpressionContext* const expCtx, string varName, Variables::Id varId, intrusive_ptr<Expression> input, @@ -2342,10 +2324,9 @@ const char* ExpressionFloor::getOpName() const { /* ------------------------- ExpressionLet ----------------------------- */ REGISTER_EXPRESSION(let, ExpressionLet::parse); -intrusive_ptr<Expression> ExpressionLet::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn) { +intrusive_ptr<Expression> ExpressionLet::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn) { verify(expr.fieldNameStringData() == "$let"); uassert(16874, "$let only supports an object as its argument", expr.type() == Object); @@ -2395,7 +2376,7 @@ intrusive_ptr<Expression> ExpressionLet::parse( return new ExpressionLet(expCtx, std::move(vars), std::move(children)); } -ExpressionLet::ExpressionLet(const boost::intrusive_ptr<ExpressionContext>& expCtx, +ExpressionLet::ExpressionLet(ExpressionContext* const expCtx, VariableMap&& vars, std::vector<boost::intrusive_ptr<Expression>> children) : Expression(expCtx, std::move(children)), @@ -2451,10 +2432,9 @@ void ExpressionLet::_doAddDependencies(DepsTracker* deps) const { /* ------------------------- ExpressionMap ----------------------------- */ REGISTER_EXPRESSION(map, ExpressionMap::parse); -intrusive_ptr<Expression> ExpressionMap::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn) { +intrusive_ptr<Expression> ExpressionMap::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn) { verify(expr.fieldNameStringData() == "$map"); uassert(16878, "$map only supports an object as its argument", expr.type() == Object); @@ -2500,7 +2480,7 @@ intrusive_ptr<Expression> ExpressionMap::parse( return new ExpressionMap(expCtx, varName, varId, input, in); } -ExpressionMap::ExpressionMap(const boost::intrusive_ptr<ExpressionContext>& expCtx, +ExpressionMap::ExpressionMap(ExpressionContext* const expCtx, const string& varName, Variables::Id varId, intrusive_ptr<Expression> input, @@ -2629,10 +2609,9 @@ const stdx::unordered_map<DocumentMetadataFields::MetaType, StringData> kMetaTyp } // namespace -intrusive_ptr<Expression> ExpressionMeta::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn) { +intrusive_ptr<Expression> ExpressionMeta::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn) { uassert(17307, "$meta only supports string arguments", expr.type() == String); const auto iter = kMetaNameToMetaType.find(expr.valueStringData()); @@ -2643,8 +2622,7 @@ intrusive_ptr<Expression> ExpressionMeta::parse( } } -ExpressionMeta::ExpressionMeta(const boost::intrusive_ptr<ExpressionContext>& expCtx, - MetaType metaType) +ExpressionMeta::ExpressionMeta(ExpressionContext* const expCtx, MetaType metaType) : Expression(expCtx), _metaType(metaType) {} Value ExpressionMeta::serialize(bool explain) const { @@ -2937,7 +2915,7 @@ ExpressionIndexOfArray::Arguments ExpressionIndexOfArray::evaluateAndValidateArg */ class ExpressionIndexOfArray::Optimized : public ExpressionIndexOfArray { public: - Optimized(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Optimized(ExpressionContext* const expCtx, const ValueUnorderedMap<vector<int>>& indexMap, const ExpressionVector& operands) : ExpressionIndexOfArray(expCtx), _indexMap(std::move(indexMap)) { @@ -3544,8 +3522,9 @@ bool representableAsLong(long long base, long long exp) { /* ----------------------- ExpressionPow ---------------------------- */ -intrusive_ptr<Expression> ExpressionPow::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, Value base, Value exp) { +intrusive_ptr<Expression> ExpressionPow::create(ExpressionContext* const expCtx, + Value base, + Value exp) { intrusive_ptr<ExpressionPow> expr(new ExpressionPow(expCtx)); expr->_children.push_back( ExpressionConstant::create(expr->getExpressionContext(), std::move(base))); @@ -3735,10 +3714,9 @@ const char* ExpressionRange::getOpName() const { /* ------------------------ ExpressionReduce ------------------------------ */ REGISTER_EXPRESSION(reduce, ExpressionReduce::parse); -intrusive_ptr<Expression> ExpressionReduce::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionReduce::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(40075, str::stream() << "$reduce requires an object as an argument, found: " << typeName(expr.type()), @@ -3837,7 +3815,7 @@ Value ExpressionReplaceBase::serialize(bool explain) const { namespace { std::tuple<intrusive_ptr<Expression>, intrusive_ptr<Expression>, intrusive_ptr<Expression>> parseExpressionReplaceBase(const char* opName, - const intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, BSONElement expr, const VariablesParseState& vps) { @@ -3913,10 +3891,9 @@ intrusive_ptr<Expression> ExpressionReplaceBase::optimize() { REGISTER_EXPRESSION(replaceOne, ExpressionReplaceOne::parse); -intrusive_ptr<Expression> ExpressionReplaceOne::parse( - const intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionReplaceOne::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { auto [input, find, replacement] = parseExpressionReplaceBase(opName, expCtx, expr, vps); return make_intrusive<ExpressionReplaceOne>( expCtx, std::move(input), std::move(find), std::move(replacement)); @@ -3945,10 +3922,9 @@ Value ExpressionReplaceOne::_doEval(StringData input, REGISTER_EXPRESSION(replaceAll, ExpressionReplaceAll::parse); -intrusive_ptr<Expression> ExpressionReplaceAll::parse( - const intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionReplaceAll::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { auto [input, find, replacement] = parseExpressionReplaceBase(opName, expCtx, expr, vps); return make_intrusive<ExpressionReplaceAll>( expCtx, std::move(input), std::move(find), std::move(replacement)); @@ -4189,7 +4165,7 @@ Value ExpressionSetIsSubset::evaluate(const Document& root, Variables* variables */ class ExpressionSetIsSubset::Optimized : public ExpressionSetIsSubset { public: - Optimized(const boost::intrusive_ptr<ExpressionContext>& expCtx, + Optimized(ExpressionContext* const expCtx, const ValueSet& cachedRhsSet, const ExpressionVector& operands) : ExpressionSetIsSubset(expCtx), _cachedRhsSet(cachedRhsSet) { @@ -4760,10 +4736,9 @@ Value ExpressionSwitch::evaluate(const Document& root, Variables* variables) con return _default->evaluate(root, variables); } -boost::intrusive_ptr<Expression> ExpressionSwitch::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +boost::intrusive_ptr<Expression> ExpressionSwitch::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(40060, str::stream() << "$switch requires an object as an argument, found: " << typeName(expr.type()), @@ -4912,10 +4887,9 @@ REGISTER_EXPRESSION(trim, ExpressionTrim::parse); REGISTER_EXPRESSION(ltrim, ExpressionTrim::parse); REGISTER_EXPRESSION(rtrim, ExpressionTrim::parse); -intrusive_ptr<Expression> ExpressionTrim::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionTrim::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { const auto name = expr.fieldNameStringData(); TrimType trimType = TrimType::kBoth; if (name == "$ltrim"_sd) { @@ -5231,7 +5205,7 @@ Value ExpressionTrunc::evaluate(const Document& root, Variables* variables) cons root, _children, getOpName(), Decimal128::kRoundTowardZero, &std::trunc, variables); } -intrusive_ptr<Expression> ExpressionTrunc::parse(const intrusive_ptr<ExpressionContext>& expCtx, +intrusive_ptr<Expression> ExpressionTrunc::parse(ExpressionContext* const expCtx, BSONElement elem, const VariablesParseState& vps) { return ExpressionRangedArity<ExpressionTrunc, 1, 2>::parse(expCtx, elem, vps); @@ -5270,10 +5244,9 @@ const char* ExpressionIsNumber::getOpName() const { /* -------------------------- ExpressionZip ------------------------------ */ REGISTER_EXPRESSION(zip, ExpressionZip::parse); -intrusive_ptr<Expression> ExpressionZip::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionZip::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(34460, str::stream() << "$zip only supports an object as an argument, found " << typeName(expr.type()), @@ -5458,8 +5431,7 @@ namespace { */ class ConversionTable { public: - using ConversionFunc = - std::function<Value(const boost::intrusive_ptr<ExpressionContext>&, Value)>; + using ConversionFunc = std::function<Value(ExpressionContext* const, Value)>; ConversionTable() { // @@ -5467,17 +5439,17 @@ public: // table[BSONType::NumberDouble][BSONType::NumberDouble] = &performIdentityConversion; table[BSONType::NumberDouble][BSONType::String] = &performFormatDouble; - table[BSONType::NumberDouble][BSONType::Bool] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberDouble][BSONType::Bool] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToBool()); + }; table[BSONType::NumberDouble][BSONType::Date] = &performCastNumberToDate; table[BSONType::NumberDouble][BSONType::NumberInt] = &performCastDoubleToInt; table[BSONType::NumberDouble][BSONType::NumberLong] = &performCastDoubleToLong; - table[BSONType::NumberDouble][BSONType::NumberDecimal] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToDecimal()); - }; + table[BSONType::NumberDouble][BSONType::NumberDecimal] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToDecimal()); + }; // // Conversions from String @@ -5486,11 +5458,11 @@ public: table[BSONType::String][BSONType::String] = &performIdentityConversion; table[BSONType::String][BSONType::jstOID] = &parseStringToOID; table[BSONType::String][BSONType::Bool] = &performConvertToTrue; - table[BSONType::String][BSONType::Date] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(expCtx->timeZoneDatabase->fromString( - inputValue.getStringData(), mongo::TimeZoneDatabase::utcZone())); - }; + table[BSONType::String][BSONType::Date] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(expCtx->timeZoneDatabase->fromString(inputValue.getStringData(), + mongo::TimeZoneDatabase::utcZone())); + }; table[BSONType::String][BSONType::NumberInt] = &parseStringToNumber<int, 10>; table[BSONType::String][BSONType::NumberLong] = &parseStringToNumber<long long, 10>; table[BSONType::String][BSONType::NumberDecimal] = &parseStringToNumber<Decimal128, 0>; @@ -5498,139 +5470,139 @@ public: // // Conversions from jstOID // - table[BSONType::jstOID][BSONType::String] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.getOid().toString()); - }; + table[BSONType::jstOID][BSONType::String] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.getOid().toString()); + }; table[BSONType::jstOID][BSONType::jstOID] = &performIdentityConversion; table[BSONType::jstOID][BSONType::Bool] = &performConvertToTrue; - table[BSONType::jstOID][BSONType::Date] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.getOid().asDateT()); - }; + table[BSONType::jstOID][BSONType::Date] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.getOid().asDateT()); + }; // // Conversions from Bool // - table[BSONType::Bool][BSONType::NumberDouble] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return inputValue.getBool() ? Value(1.0) : Value(0.0); - }; - table[BSONType::Bool][BSONType::String] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return inputValue.getBool() ? Value("true"_sd) : Value("false"_sd); - }; + table[BSONType::Bool][BSONType::NumberDouble] = [](ExpressionContext* const expCtx, + Value inputValue) { + return inputValue.getBool() ? Value(1.0) : Value(0.0); + }; + table[BSONType::Bool][BSONType::String] = [](ExpressionContext* const expCtx, + Value inputValue) { + return inputValue.getBool() ? Value("true"_sd) : Value("false"_sd); + }; table[BSONType::Bool][BSONType::Bool] = &performIdentityConversion; - table[BSONType::Bool][BSONType::NumberInt] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return inputValue.getBool() ? Value(int{1}) : Value(int{0}); - }; - table[BSONType::Bool][BSONType::NumberLong] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return inputValue.getBool() ? Value(1LL) : Value(0LL); - }; - table[BSONType::Bool][BSONType::NumberDecimal] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return inputValue.getBool() ? Value(Decimal128(1)) : Value(Decimal128(0)); - }; + table[BSONType::Bool][BSONType::NumberInt] = [](ExpressionContext* const expCtx, + Value inputValue) { + return inputValue.getBool() ? Value(int{1}) : Value(int{0}); + }; + table[BSONType::Bool][BSONType::NumberLong] = [](ExpressionContext* const expCtx, + Value inputValue) { + return inputValue.getBool() ? Value(1LL) : Value(0LL); + }; + table[BSONType::Bool][BSONType::NumberDecimal] = [](ExpressionContext* const expCtx, + Value inputValue) { + return inputValue.getBool() ? Value(Decimal128(1)) : Value(Decimal128(0)); + }; // // Conversions from Date // - table[BSONType::Date][BSONType::NumberDouble] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(static_cast<double>(inputValue.getDate().toMillisSinceEpoch())); - }; - table[BSONType::Date][BSONType::String] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - auto dateString = TimeZoneDatabase::utcZone().formatDate(Value::kISOFormatString, - inputValue.getDate()); - return Value(dateString); - }; - table[BSONType::Date][BSONType::Bool] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::Date][BSONType::NumberDouble] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(static_cast<double>(inputValue.getDate().toMillisSinceEpoch())); + }; + table[BSONType::Date][BSONType::String] = [](ExpressionContext* const expCtx, + Value inputValue) { + auto dateString = TimeZoneDatabase::utcZone().formatDate(Value::kISOFormatString, + inputValue.getDate()); + return Value(dateString); + }; + table[BSONType::Date][BSONType::Bool] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToBool()); + }; table[BSONType::Date][BSONType::Date] = &performIdentityConversion; - table[BSONType::Date][BSONType::NumberLong] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.getDate().toMillisSinceEpoch()); - }; - table[BSONType::Date][BSONType::NumberDecimal] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value( - Decimal128(static_cast<int64_t>(inputValue.getDate().toMillisSinceEpoch()))); - }; + table[BSONType::Date][BSONType::NumberLong] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.getDate().toMillisSinceEpoch()); + }; + table[BSONType::Date][BSONType::NumberDecimal] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value( + Decimal128(static_cast<int64_t>(inputValue.getDate().toMillisSinceEpoch()))); + }; // // Conversions from NumberInt // - table[BSONType::NumberInt][BSONType::NumberDouble] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToDouble()); - }; - table[BSONType::NumberInt][BSONType::String] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(static_cast<std::string>(str::stream() << inputValue.getInt())); - }; - table[BSONType::NumberInt][BSONType::Bool] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberInt][BSONType::NumberDouble] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToDouble()); + }; + table[BSONType::NumberInt][BSONType::String] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(static_cast<std::string>(str::stream() << inputValue.getInt())); + }; + table[BSONType::NumberInt][BSONType::Bool] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToBool()); + }; table[BSONType::NumberInt][BSONType::NumberInt] = &performIdentityConversion; - table[BSONType::NumberInt][BSONType::NumberLong] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(static_cast<long long>(inputValue.getInt())); - }; - table[BSONType::NumberInt][BSONType::NumberDecimal] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToDecimal()); - }; + table[BSONType::NumberInt][BSONType::NumberLong] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(static_cast<long long>(inputValue.getInt())); + }; + table[BSONType::NumberInt][BSONType::NumberDecimal] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToDecimal()); + }; // // Conversions from NumberLong // - table[BSONType::NumberLong][BSONType::NumberDouble] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToDouble()); - }; - table[BSONType::NumberLong][BSONType::String] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(static_cast<std::string>(str::stream() << inputValue.getLong())); - }; - table[BSONType::NumberLong][BSONType::Bool] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberLong][BSONType::NumberDouble] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToDouble()); + }; + table[BSONType::NumberLong][BSONType::String] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(static_cast<std::string>(str::stream() << inputValue.getLong())); + }; + table[BSONType::NumberLong][BSONType::Bool] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToBool()); + }; table[BSONType::NumberLong][BSONType::Date] = &performCastNumberToDate; table[BSONType::NumberLong][BSONType::NumberInt] = &performCastLongToInt; table[BSONType::NumberLong][BSONType::NumberLong] = &performIdentityConversion; - table[BSONType::NumberLong][BSONType::NumberDecimal] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToDecimal()); - }; + table[BSONType::NumberLong][BSONType::NumberDecimal] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToDecimal()); + }; // // Conversions from NumberDecimal // table[BSONType::NumberDecimal][BSONType::NumberDouble] = &performCastDecimalToDouble; - table[BSONType::NumberDecimal][BSONType::String] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.getDecimal().toString()); - }; - table[BSONType::NumberDecimal][BSONType::Bool] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return Value(inputValue.coerceToBool()); - }; + table[BSONType::NumberDecimal][BSONType::String] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.getDecimal().toString()); + }; + table[BSONType::NumberDecimal][BSONType::Bool] = [](ExpressionContext* const expCtx, + Value inputValue) { + return Value(inputValue.coerceToBool()); + }; table[BSONType::NumberDecimal][BSONType::Date] = &performCastNumberToDate; - table[BSONType::NumberDecimal][BSONType::NumberInt] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return performCastDecimalToInt(BSONType::NumberInt, inputValue); - }; - table[BSONType::NumberDecimal][BSONType::NumberLong] = - [](const boost::intrusive_ptr<ExpressionContext>& expCtx, Value inputValue) { - return performCastDecimalToInt(BSONType::NumberLong, inputValue); - }; + table[BSONType::NumberDecimal][BSONType::NumberInt] = [](ExpressionContext* const expCtx, + Value inputValue) { + return performCastDecimalToInt(BSONType::NumberInt, inputValue); + }; + table[BSONType::NumberDecimal][BSONType::NumberLong] = [](ExpressionContext* const expCtx, + Value inputValue) { + return performCastDecimalToInt(BSONType::NumberLong, inputValue); + }; table[BSONType::NumberDecimal][BSONType::NumberDecimal] = &performIdentityConversion; // @@ -5686,8 +5658,7 @@ private: std::isfinite(inputDouble)); } - static Value performCastDoubleToInt(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performCastDoubleToInt(ExpressionContext* const expCtx, Value inputValue) { double inputDouble = inputValue.getDouble(); validateDoubleValueIsFinite(inputDouble); @@ -5701,8 +5672,7 @@ private: return Value(static_cast<int>(inputDouble)); } - static Value performCastDoubleToLong(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performCastDoubleToLong(ExpressionContext* const expCtx, Value inputValue) { double inputDouble = inputValue.getDouble(); validateDoubleValueIsFinite(inputDouble); @@ -5757,8 +5727,7 @@ private: return result; } - static Value performCastDecimalToDouble(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performCastDecimalToDouble(ExpressionContext* const expCtx, Value inputValue) { Decimal128 inputDecimal = inputValue.getDecimal(); std::uint32_t signalingFlags = Decimal128::SignalingFlag::kNoFlag; @@ -5775,8 +5744,7 @@ private: return Value(result); } - static Value performCastLongToInt(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performCastLongToInt(ExpressionContext* const expCtx, Value inputValue) { long long longValue = inputValue.getLong(); uassert(ErrorCodes::ConversionFailure, @@ -5788,8 +5756,7 @@ private: return Value(static_cast<int>(longValue)); } - static Value performCastNumberToDate(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performCastNumberToDate(ExpressionContext* const expCtx, Value inputValue) { long long millisSinceEpoch; switch (inputValue.getType()) { @@ -5810,8 +5777,7 @@ private: return Value(Date_t::fromMillisSinceEpoch(millisSinceEpoch)); } - static Value performFormatDouble(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performFormatDouble(ExpressionContext* const expCtx, Value inputValue) { double doubleValue = inputValue.getDouble(); if (std::isinf(doubleValue)) { @@ -5826,8 +5792,7 @@ private: } template <class targetType, int base> - static Value parseStringToNumber(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value parseStringToNumber(ExpressionContext* const expCtx, Value inputValue) { auto stringValue = inputValue.getStringData(); targetType result; @@ -5848,8 +5813,7 @@ private: return Value(result); } - static Value parseStringToOID(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value parseStringToOID(ExpressionContext* const expCtx, Value inputValue) { try { return Value(OID::createFromString(inputValue.getStringData())); } catch (const DBException& ex) { @@ -5861,19 +5825,17 @@ private: } } - static Value performConvertToTrue(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performConvertToTrue(ExpressionContext* const expCtx, Value inputValue) { return Value(true); } - static Value performIdentityConversion(const boost::intrusive_ptr<ExpressionContext>& expCtx, - Value inputValue) { + static Value performIdentityConversion(ExpressionContext* const expCtx, Value inputValue) { return inputValue; } }; Expression::Parser makeConversionAlias(const StringData shortcutName, BSONType toType) { - return [=](const intrusive_ptr<ExpressionContext>& expCtx, + return [=](ExpressionContext* const expCtx, BSONElement elem, const VariablesParseState& vps) -> intrusive_ptr<Expression> { // Use parseArguments to allow for a singleton array, or the unwrapped version. @@ -5902,10 +5864,9 @@ REGISTER_EXPRESSION(toLong, makeConversionAlias("$toLong"_sd, BSONType::NumberLo REGISTER_EXPRESSION(toDecimal, makeConversionAlias("$toDecimal"_sd, BSONType::NumberDecimal)); REGISTER_EXPRESSION(toBool, makeConversionAlias("$toBool"_sd, BSONType::Bool)); -boost::intrusive_ptr<Expression> ExpressionConvert::create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - boost::intrusive_ptr<Expression> input, - BSONType toType) { +boost::intrusive_ptr<Expression> ExpressionConvert::create(ExpressionContext* const expCtx, + boost::intrusive_ptr<Expression> input, + BSONType toType) { return new ExpressionConvert( expCtx, std::move(input), @@ -5914,7 +5875,7 @@ boost::intrusive_ptr<Expression> ExpressionConvert::create( nullptr); } -ExpressionConvert::ExpressionConvert(const boost::intrusive_ptr<ExpressionContext>& expCtx, +ExpressionConvert::ExpressionConvert(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> input, boost::intrusive_ptr<Expression> to, boost::intrusive_ptr<Expression> onError, @@ -5925,10 +5886,9 @@ ExpressionConvert::ExpressionConvert(const boost::intrusive_ptr<ExpressionContex _onError(_children[2]), _onNull(_children[3]) {} -intrusive_ptr<Expression> ExpressionConvert::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +intrusive_ptr<Expression> ExpressionConvert::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(ErrorCodes::FailedToParse, str::stream() << "$convert expects an object of named arguments but found: " << typeName(expr.type()), @@ -6072,7 +6032,7 @@ Value ExpressionConvert::performConversion(BSONType targetType, Value inputValue namespace { -auto CommonRegexParse(const boost::intrusive_ptr<ExpressionContext>& expCtx, +auto CommonRegexParse(ExpressionContext* const expCtx, BSONElement expr, const VariablesParseState& vpsIn, StringData opName) { @@ -6366,10 +6326,9 @@ void ExpressionRegex::_doAddDependencies(DepsTracker* deps) const { /* -------------------------- ExpressionRegexFind ------------------------------ */ REGISTER_EXPRESSION(regexFind, ExpressionRegexFind::parse); -boost::intrusive_ptr<Expression> ExpressionRegexFind::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn) { +boost::intrusive_ptr<Expression> ExpressionRegexFind::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn) { auto opName = "$regexFind"_sd; auto [input, regex, options] = CommonRegexParse(expCtx, expr, vpsIn, opName); return new ExpressionRegexFind( @@ -6387,10 +6346,9 @@ Value ExpressionRegexFind::evaluate(const Document& root, Variables* variables) /* -------------------------- ExpressionRegexFindAll ------------------------------ */ REGISTER_EXPRESSION(regexFindAll, ExpressionRegexFindAll::parse); -boost::intrusive_ptr<Expression> ExpressionRegexFindAll::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn) { +boost::intrusive_ptr<Expression> ExpressionRegexFindAll::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn) { auto opName = "$regexFindAll"_sd; auto [input, regex, options] = CommonRegexParse(expCtx, expr, vpsIn, opName); return new ExpressionRegexFindAll( @@ -6448,10 +6406,9 @@ Value ExpressionRegexFindAll::evaluate(const Document& root, Variables* variable /* -------------------------- ExpressionRegexMatch ------------------------------ */ REGISTER_EXPRESSION(regexMatch, ExpressionRegexMatch::parse); -boost::intrusive_ptr<Expression> ExpressionRegexMatch::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn) { +boost::intrusive_ptr<Expression> ExpressionRegexMatch::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn) { auto opName = "$regexMatch"_sd; auto [input, regex, options] = CommonRegexParse(expCtx, expr, vpsIn, opName); return new ExpressionRegexMatch( diff --git a/src/mongo/db/pipeline/expression.h b/src/mongo/db/pipeline/expression.h index 4f772ca2363..b68ac1ab9fa 100644 --- a/src/mongo/db/pipeline/expression.h +++ b/src/mongo/db/pipeline/expression.h @@ -92,7 +92,7 @@ class DocumentSource; class Expression : public RefCountable { public: using Parser = std::function<boost::intrusive_ptr<Expression>( - const boost::intrusive_ptr<ExpressionContext>&, BSONElement, const VariablesParseState&)>; + ExpressionContext* const, BSONElement, const VariablesParseState&)>; /** * Represents new paths computed by an expression. Computed paths are partitioned into renames @@ -195,10 +195,9 @@ public: * Calls parseExpression() on any sub-document (including possibly the entire document) which * consists of a single field name starting with a '$'. */ - static boost::intrusive_ptr<Expression> parseObject( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONObj obj, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parseObject(ExpressionContext* const expCtx, + BSONObj obj, + const VariablesParseState& vps); /** * Parses a BSONObj which has already been determined to be a functional expression. @@ -206,10 +205,9 @@ public: * Throws an error if 'obj' does not contain exactly one field, or if that field's name does not * match a registered expression name. */ - static boost::intrusive_ptr<Expression> parseExpression( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONObj obj, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parseExpression(ExpressionContext* const expCtx, + BSONObj obj, + const VariablesParseState& vps); /** * Parses a BSONElement which is an argument to an Expression. @@ -218,10 +216,9 @@ public: * parseObject(), ExpressionFieldPath::parse(), ExpressionArray::parse(), or * ExpressionConstant::parse() as necessary. */ - static boost::intrusive_ptr<Expression> parseOperand( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement exprElement, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parseOperand(ExpressionContext* const expCtx, + BSONElement exprElement, + const VariablesParseState& vps); /** * Return whether 'name' refers to an expression in the language. @@ -256,16 +253,16 @@ public: return _children; } - const boost::intrusive_ptr<ExpressionContext>& getExpressionContext() const { + auto getExpressionContext() const { return _expCtx; } protected: using ExpressionVector = std::vector<boost::intrusive_ptr<Expression>>; - Expression(const boost::intrusive_ptr<ExpressionContext>& expCtx) : Expression(expCtx, {}) {} + Expression(ExpressionContext* const expCtx) : Expression(expCtx, {}) {} - Expression(const boost::intrusive_ptr<ExpressionContext>& expCtx, ExpressionVector&& children) + Expression(ExpressionContext* const expCtx, ExpressionVector&& children) : _children(std::move(children)), _expCtx(expCtx) { auto varIds = _expCtx->variablesParseState.getDefinedVariableIDs(); if (!varIds.empty()) { @@ -288,7 +285,7 @@ protected: private: boost::optional<Variables::Id> _boundaryVariableId; - boost::intrusive_ptr<ExpressionContext> _expCtx; + ExpressionContext* const _expCtx; }; /** @@ -318,7 +315,7 @@ public: virtual void validateArguments(const ExpressionVector& args) const {} - static ExpressionVector parseArguments(const boost::intrusive_ptr<ExpressionContext>& expCtx, + static ExpressionVector parseArguments(ExpressionContext* const expCtx, BSONElement bsonExpr, const VariablesParseState& vps); @@ -327,8 +324,7 @@ public: } protected: - explicit ExpressionNary(const boost::intrusive_ptr<ExpressionContext>& expCtx) - : Expression(expCtx) {} + explicit ExpressionNary(ExpressionContext* const expCtx) : Expression(expCtx) {} void _doAddDependencies(DepsTracker* deps) const override; }; @@ -337,10 +333,9 @@ protected: template <typename SubClass> class ExpressionNaryBase : public ExpressionNary { public: - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement bsonExpr, - const VariablesParseState& vps) { + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps) { auto expr = make_intrusive<SubClass>(expCtx); ExpressionVector args = parseArguments(expCtx, bsonExpr, vps); expr->validateArguments(args); @@ -349,15 +344,14 @@ public: } protected: - explicit ExpressionNaryBase(const boost::intrusive_ptr<ExpressionContext>& expCtx) - : ExpressionNary(expCtx) {} + explicit ExpressionNaryBase(ExpressionContext* const expCtx) : ExpressionNary(expCtx) {} }; /// Inherit from this class if your expression takes a variable number of arguments. template <typename SubClass> class ExpressionVariadic : public ExpressionNaryBase<SubClass> { public: - explicit ExpressionVariadic(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionVariadic(ExpressionContext* const expCtx) : ExpressionNaryBase<SubClass>(expCtx) {} }; @@ -368,7 +362,7 @@ public: template <typename SubClass, int MinArgs, int MaxArgs> class ExpressionRangedArity : public ExpressionNaryBase<SubClass> { public: - explicit ExpressionRangedArity(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionRangedArity(ExpressionContext* const expCtx) : ExpressionNaryBase<SubClass>(expCtx) {} void validateArguments(const Expression::ExpressionVector& args) const override { @@ -384,7 +378,7 @@ public: template <typename SubClass, int NArgs> class ExpressionFixedArity : public ExpressionNaryBase<SubClass> { public: - explicit ExpressionFixedArity(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionFixedArity(ExpressionContext* const expCtx) : ExpressionNaryBase<SubClass>(expCtx) {} void validateArguments(const Expression::ExpressionVector& args) const override { @@ -403,7 +397,7 @@ template <typename AccumulatorState> class ExpressionFromAccumulator : public ExpressionVariadic<ExpressionFromAccumulator<AccumulatorState>> { public: - explicit ExpressionFromAccumulator(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionFromAccumulator(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionFromAccumulator<AccumulatorState>>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final { @@ -457,7 +451,7 @@ public: template <typename SubClass> class ExpressionSingleNumericArg : public ExpressionFixedArity<SubClass, 1> { public: - explicit ExpressionSingleNumericArg(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSingleNumericArg(ExpressionContext* const expCtx) : ExpressionFixedArity<SubClass, 1>(expCtx) {} virtual ~ExpressionSingleNumericArg() = default; @@ -484,7 +478,7 @@ public: template <typename SubClass> class ExpressionTwoNumericArgs : public ExpressionFixedArity<SubClass, 2> { public: - explicit ExpressionTwoNumericArgs(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionTwoNumericArgs(ExpressionContext* const expCtx) : ExpressionFixedArity<SubClass, 2>(expCtx) {} virtual ~ExpressionTwoNumericArgs() = default; @@ -535,13 +529,12 @@ public: /** * Creates a new ExpressionConstant with value 'value'. */ - static boost::intrusive_ptr<ExpressionConstant> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, const Value& value); + static boost::intrusive_ptr<ExpressionConstant> create(ExpressionContext* const expCtx, + const Value& value); - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement bsonExpr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps); /** * Returns true if 'expression' is nullptr or if 'expression' is an instance of an @@ -581,7 +574,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const override; private: - ExpressionConstant(const boost::intrusive_ptr<ExpressionContext>& expCtx, const Value& value); + ExpressionConstant(ExpressionContext* const expCtx, const Value& value); Value _value; }; @@ -647,10 +640,9 @@ public: return this; } - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement operatorElem, - const VariablesParseState& variablesParseState) { + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement operatorElem, + const VariablesParseState& variablesParseState) { if (operatorElem.type() == BSONType::Object) { if (operatorElem.embeddedObject().firstElementFieldName()[0] == '$') { // Assume this is an expression specification representing the date argument @@ -703,7 +695,7 @@ public: } protected: - explicit DateExpressionAcceptingTimeZone(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit DateExpressionAcceptingTimeZone(ExpressionContext* const expCtx, const StringData opName, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone) @@ -738,7 +730,7 @@ private: class ExpressionAbs final : public ExpressionSingleNumericArg<ExpressionAbs> { public: - explicit ExpressionAbs(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionAbs(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<ExpressionAbs>(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final; @@ -751,7 +743,7 @@ public: class ExpressionAdd final : public ExpressionVariadic<ExpressionAdd> { public: - explicit ExpressionAdd(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionAdd(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionAdd>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -773,7 +765,7 @@ public: class ExpressionAllElementsTrue final : public ExpressionFixedArity<ExpressionAllElementsTrue, 1> { public: - explicit ExpressionAllElementsTrue(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionAllElementsTrue(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionAllElementsTrue, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -787,7 +779,7 @@ public: class ExpressionAnd final : public ExpressionVariadic<ExpressionAnd> { public: - explicit ExpressionAnd(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionAnd(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionAnd>(expCtx) {} boost::intrusive_ptr<Expression> optimize() final; @@ -810,7 +802,7 @@ public: class ExpressionAnyElementTrue final : public ExpressionFixedArity<ExpressionAnyElementTrue, 1> { public: - explicit ExpressionAnyElementTrue(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionAnyElementTrue(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionAnyElementTrue, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -824,10 +816,10 @@ public: class ExpressionArray final : public ExpressionVariadic<ExpressionArray> { public: - explicit ExpressionArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionArray(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionArray>(expCtx) {} - ExpressionArray(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionArray(ExpressionContext* const expCtx, std::vector<boost::intrusive_ptr<Expression>>&& children) : ExpressionVariadic<ExpressionArray>(expCtx) { _children = std::move(children); @@ -837,8 +829,7 @@ public: Value serialize(bool explain) const final; static boost::intrusive_ptr<ExpressionArray> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - std::vector<boost::intrusive_ptr<Expression>>&& children) { + ExpressionContext* const expCtx, std::vector<boost::intrusive_ptr<Expression>>&& children) { return make_intrusive<ExpressionArray>(expCtx, std::move(children)); } @@ -853,7 +844,7 @@ public: class ExpressionArrayElemAt final : public ExpressionFixedArity<ExpressionArrayElemAt, 2> { public: - explicit ExpressionArrayElemAt(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionArrayElemAt(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionArrayElemAt, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -866,7 +857,7 @@ public: class ExpressionFirst final : public ExpressionFixedArity<ExpressionFirst, 1> { public: - explicit ExpressionFirst(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionFirst(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionFirst, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -879,7 +870,7 @@ public: class ExpressionLast final : public ExpressionFixedArity<ExpressionLast, 1> { public: - explicit ExpressionLast(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionLast(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionLast, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -892,7 +883,7 @@ public: class ExpressionObjectToArray final : public ExpressionFixedArity<ExpressionObjectToArray, 1> { public: - explicit ExpressionObjectToArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionObjectToArray(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionObjectToArray, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -905,7 +896,7 @@ public: class ExpressionArrayToObject final : public ExpressionFixedArity<ExpressionArrayToObject, 1> { public: - explicit ExpressionArrayToObject(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionArrayToObject(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionArrayToObject, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -918,7 +909,7 @@ public: class ExpressionBsonSize final : public ExpressionFixedArity<ExpressionBsonSize, 1> { public: - explicit ExpressionBsonSize(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionBsonSize(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionBsonSize, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -933,7 +924,7 @@ public: class ExpressionCeil final : public ExpressionSingleNumericArg<ExpressionCeil> { public: - explicit ExpressionCeil(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionCeil(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<ExpressionCeil>(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final; @@ -952,8 +943,7 @@ public: Value serialize(bool explain) const final; static boost::intrusive_ptr<ExpressionCoerceToBool> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - boost::intrusive_ptr<Expression> pExpression); + ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> pExpression); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -963,7 +953,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionCoerceToBool(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionCoerceToBool(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> pExpression); boost::intrusive_ptr<Expression>& pExpression; @@ -986,7 +976,7 @@ public: CMP = 6, // return -1, 0, 1 for a < b, a == b, a > b }; - ExpressionCompare(const boost::intrusive_ptr<ExpressionContext>& expCtx, CmpOp cmpOp) + ExpressionCompare(ExpressionContext* const expCtx, CmpOp cmpOp) : ExpressionFixedArity<ExpressionCompare, 2>(expCtx), cmpOp(cmpOp) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -996,14 +986,13 @@ public: return cmpOp; } - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement bsonExpr, - const VariablesParseState& vps, - CmpOp cmpOp); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement bsonExpr, + const VariablesParseState& vps, + CmpOp cmpOp); static boost::intrusive_ptr<ExpressionCompare> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, CmpOp cmpOp, const boost::intrusive_ptr<Expression>& exprLeft, const boost::intrusive_ptr<Expression>& exprRight); @@ -1019,7 +1008,7 @@ private: class ExpressionConcat final : public ExpressionVariadic<ExpressionConcat> { public: - explicit ExpressionConcat(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionConcat(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionConcat>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1037,7 +1026,7 @@ public: class ExpressionConcatArrays final : public ExpressionVariadic<ExpressionConcatArrays> { public: - explicit ExpressionConcatArrays(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionConcatArrays(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionConcatArrays>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1055,15 +1044,14 @@ public: class ExpressionCond final : public ExpressionFixedArity<ExpressionCond, 3> { public: - explicit ExpressionCond(const boost::intrusive_ptr<ExpressionContext>& expCtx) : Base(expCtx) {} + explicit ExpressionCond(ExpressionContext* const expCtx) : Base(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; const char* getOpName() const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1079,10 +1067,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1092,7 +1079,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionDateFromString(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionDateFromString(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> dateString, boost::intrusive_ptr<Expression> timeZone, boost::intrusive_ptr<Expression> format, @@ -1112,10 +1099,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1125,7 +1111,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionDateFromParts(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionDateFromParts(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> year, boost::intrusive_ptr<Expression> month, boost::intrusive_ptr<Expression> day, @@ -1194,10 +1180,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1210,7 +1195,7 @@ private: /** * The iso8601 argument controls whether to output ISO8601 elements or natural calendar. */ - ExpressionDateToParts(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionDateToParts(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone, boost::intrusive_ptr<Expression> iso8601); @@ -1228,10 +1213,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1241,7 +1225,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionDateToString(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionDateToString(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> format, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone, @@ -1255,7 +1239,7 @@ private: class ExpressionDayOfMonth final : public DateExpressionAcceptingTimeZone<ExpressionDayOfMonth> { public: - explicit ExpressionDayOfMonth(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionDayOfMonth(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionDayOfMonth>( @@ -1273,7 +1257,7 @@ public: class ExpressionDayOfWeek final : public DateExpressionAcceptingTimeZone<ExpressionDayOfWeek> { public: - explicit ExpressionDayOfWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionDayOfWeek(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionDayOfWeek>( @@ -1291,7 +1275,7 @@ public: class ExpressionDayOfYear final : public DateExpressionAcceptingTimeZone<ExpressionDayOfYear> { public: - explicit ExpressionDayOfYear(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionDayOfYear(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionDayOfYear>( @@ -1309,7 +1293,7 @@ public: class ExpressionDivide final : public ExpressionFixedArity<ExpressionDivide, 2> { public: - explicit ExpressionDivide(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionDivide(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionDivide, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1323,7 +1307,7 @@ public: class ExpressionExp final : public ExpressionSingleNumericArg<ExpressionExp> { public: - explicit ExpressionExp(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionExp(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<ExpressionExp>(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final; @@ -1358,14 +1342,13 @@ public: indicator @returns the newly created field path expression */ - static boost::intrusive_ptr<ExpressionFieldPath> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, const std::string& fieldPath); + static boost::intrusive_ptr<ExpressionFieldPath> create(ExpressionContext* const expCtx, + const std::string& fieldPath); /// Like create(), but works with the raw std::string from the user with the "$" prefixes. - static boost::intrusive_ptr<ExpressionFieldPath> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - const std::string& raw, - const VariablesParseState& vps); + static boost::intrusive_ptr<ExpressionFieldPath> parse(ExpressionContext* const expCtx, + const std::string& raw, + const VariablesParseState& vps); /** * Returns true if this expression logically represents the path 'dottedPath'. For example, if @@ -1392,7 +1375,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionFieldPath(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionFieldPath(ExpressionContext* const expCtx, const std::string& fieldPath, Variables::Id variable); @@ -1425,10 +1408,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1438,7 +1420,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionFilter(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionFilter(ExpressionContext* const expCtx, std::string varName, Variables::Id varId, boost::intrusive_ptr<Expression> input, @@ -1457,7 +1439,7 @@ private: class ExpressionFloor final : public ExpressionSingleNumericArg<ExpressionFloor> { public: - explicit ExpressionFloor(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionFloor(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<ExpressionFloor>(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final; @@ -1471,7 +1453,7 @@ public: class ExpressionHour final : public DateExpressionAcceptingTimeZone<ExpressionHour> { public: - explicit ExpressionHour(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionHour(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionHour>( @@ -1489,7 +1471,7 @@ public: class ExpressionIfNull final : public ExpressionFixedArity<ExpressionIfNull, 2> { public: - explicit ExpressionIfNull(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionIfNull(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionIfNull, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1503,7 +1485,7 @@ public: class ExpressionIn final : public ExpressionFixedArity<ExpressionIn, 2> { public: - explicit ExpressionIn(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionIn(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionIn, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1517,7 +1499,7 @@ public: class ExpressionIndexOfArray : public ExpressionRangedArity<ExpressionIndexOfArray, 2, 4> { public: - explicit ExpressionIndexOfArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionIndexOfArray(ExpressionContext* const expCtx) : ExpressionRangedArity<ExpressionIndexOfArray, 2, 4>(expCtx) {} @@ -1558,7 +1540,7 @@ private: class ExpressionIndexOfBytes final : public ExpressionRangedArity<ExpressionIndexOfBytes, 2, 4> { public: - explicit ExpressionIndexOfBytes(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionIndexOfBytes(ExpressionContext* const expCtx) : ExpressionRangedArity<ExpressionIndexOfBytes, 2, 4>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1575,7 +1557,7 @@ public: */ class ExpressionIndexOfCP final : public ExpressionRangedArity<ExpressionIndexOfCP, 2, 4> { public: - explicit ExpressionIndexOfCP(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionIndexOfCP(ExpressionContext* const expCtx) : ExpressionRangedArity<ExpressionIndexOfCP, 2, 4>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1593,10 +1575,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); struct NameAndExpression { std::string name; @@ -1617,7 +1598,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionLet(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionLet(ExpressionContext* const expCtx, VariableMap&& vars, std::vector<boost::intrusive_ptr<Expression>> children); @@ -1627,7 +1608,7 @@ private: class ExpressionLn final : public ExpressionSingleNumericArg<ExpressionLn> { public: - explicit ExpressionLn(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionLn(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<ExpressionLn>(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final; @@ -1640,7 +1621,7 @@ public: class ExpressionLog final : public ExpressionFixedArity<ExpressionLog, 2> { public: - explicit ExpressionLog(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionLog(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionLog, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1653,7 +1634,7 @@ public: class ExpressionLog10 final : public ExpressionSingleNumericArg<ExpressionLog10> { public: - explicit ExpressionLog10(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionLog10(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<ExpressionLog10>(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final; @@ -1670,10 +1651,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); ComputedPaths getComputedPaths(const std::string& exprFieldPath, Variables::Id renamingVar) const final; @@ -1687,7 +1667,7 @@ protected: private: ExpressionMap( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, const std::string& varName, // name of variable to set Variables::Id varId, // id of variable to set boost::intrusive_ptr<Expression> input, // yields array to iterate @@ -1704,10 +1684,9 @@ public: Value serialize(bool explain) const final; Value evaluate(const Document& root, Variables* variables) const final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1721,15 +1700,14 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionMeta(const boost::intrusive_ptr<ExpressionContext>& expCtx, - DocumentMetadataFields::MetaType metaType); + ExpressionMeta(ExpressionContext* const expCtx, DocumentMetadataFields::MetaType metaType); DocumentMetadataFields::MetaType _metaType; }; class ExpressionMillisecond final : public DateExpressionAcceptingTimeZone<ExpressionMillisecond> { public: - explicit ExpressionMillisecond(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionMillisecond(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionMillisecond>( @@ -1747,7 +1725,7 @@ public: class ExpressionMinute final : public DateExpressionAcceptingTimeZone<ExpressionMinute> { public: - explicit ExpressionMinute(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionMinute(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionMinute>( @@ -1765,7 +1743,7 @@ public: class ExpressionMod final : public ExpressionFixedArity<ExpressionMod, 2> { public: - explicit ExpressionMod(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionMod(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionMod, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1779,7 +1757,7 @@ public: class ExpressionMultiply final : public ExpressionVariadic<ExpressionMultiply> { public: - explicit ExpressionMultiply(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionMultiply(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionMultiply>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1801,7 +1779,7 @@ public: class ExpressionMonth final : public DateExpressionAcceptingTimeZone<ExpressionMonth> { public: - explicit ExpressionMonth(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionMonth(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionMonth>( @@ -1819,7 +1797,7 @@ public: class ExpressionNot final : public ExpressionFixedArity<ExpressionNot, 1> { public: - explicit ExpressionNot(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionNot(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionNot, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1846,17 +1824,16 @@ public: Value serialize(bool explain) const final; static boost::intrusive_ptr<ExpressionObject> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, std::vector<std::pair<std::string, boost::intrusive_ptr<Expression>>>&& expressionsWithChildrenInPlace); /** * Parses and constructs an ExpressionObject from 'obj'. */ - static boost::intrusive_ptr<ExpressionObject> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONObj obj, - const VariablesParseState& vps); + static boost::intrusive_ptr<ExpressionObject> parse(ExpressionContext* const expCtx, + BSONObj obj, + const VariablesParseState& vps); /** * This ExpressionObject must outlive the returned vector. @@ -1877,7 +1854,7 @@ protected: private: ExpressionObject( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, std::vector<boost::intrusive_ptr<Expression>> children, std::vector<std::pair<std::string, boost::intrusive_ptr<Expression>&>>&& expressions); @@ -1889,7 +1866,7 @@ private: class ExpressionOr final : public ExpressionVariadic<ExpressionOr> { public: - explicit ExpressionOr(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionOr(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionOr>(expCtx) {} boost::intrusive_ptr<Expression> optimize() final; @@ -1911,11 +1888,12 @@ public: class ExpressionPow final : public ExpressionFixedArity<ExpressionPow, 2> { public: - explicit ExpressionPow(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionPow(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionPow, 2>(expCtx) {} - static boost::intrusive_ptr<Expression> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, Value base, Value exp); + static boost::intrusive_ptr<Expression> create(ExpressionContext* const expCtx, + Value base, + Value exp); void acceptVisitor(ExpressionVisitor* visitor) final { return visitor->visit(this); @@ -1929,7 +1907,7 @@ private: class ExpressionRange final : public ExpressionRangedArity<ExpressionRange, 2, 3> { public: - explicit ExpressionRange(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionRange(ExpressionContext* const expCtx) : ExpressionRangedArity<ExpressionRange, 2, 3>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -1943,7 +1921,7 @@ public: class ExpressionReduce final : public Expression { public: - ExpressionReduce(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionReduce(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> input, boost::intrusive_ptr<Expression> initial, boost::intrusive_ptr<Expression> in, @@ -1958,10 +1936,9 @@ public: Value evaluate(const Document& root, Variables* variables) const final; boost::intrusive_ptr<Expression> optimize() final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); Value serialize(bool explain) const final; void acceptVisitor(ExpressionVisitor* visitor) final { @@ -1983,7 +1960,7 @@ private: class ExpressionReplaceBase : public Expression { public: - ExpressionReplaceBase(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionReplaceBase(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> input, boost::intrusive_ptr<Expression> find, boost::intrusive_ptr<Expression> replacement) @@ -2014,10 +1991,9 @@ class ExpressionReplaceOne final : public ExpressionReplaceBase { public: using ExpressionReplaceBase::ExpressionReplaceBase; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); static constexpr const char* const opName = "$replaceOne"; const char* getOpName() const final { @@ -2036,10 +2012,9 @@ class ExpressionReplaceAll final : public ExpressionReplaceBase { public: using ExpressionReplaceBase::ExpressionReplaceBase; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); static constexpr const char* const opName = "$replaceAll"; const char* getOpName() const final { @@ -2056,7 +2031,7 @@ protected: class ExpressionSecond final : public DateExpressionAcceptingTimeZone<ExpressionSecond> { public: - ExpressionSecond(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionSecond(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionSecond>( @@ -2074,7 +2049,7 @@ public: class ExpressionSetDifference final : public ExpressionFixedArity<ExpressionSetDifference, 2> { public: - explicit ExpressionSetDifference(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSetDifference(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionSetDifference, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2088,7 +2063,7 @@ public: class ExpressionSetEquals final : public ExpressionVariadic<ExpressionSetEquals> { public: - explicit ExpressionSetEquals(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSetEquals(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionSetEquals>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2103,7 +2078,7 @@ public: class ExpressionSetIntersection final : public ExpressionVariadic<ExpressionSetIntersection> { public: - explicit ExpressionSetIntersection(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSetIntersection(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionSetIntersection>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2126,7 +2101,7 @@ public: // Not final, inherited from for optimizations. class ExpressionSetIsSubset : public ExpressionFixedArity<ExpressionSetIsSubset, 2> { public: - explicit ExpressionSetIsSubset(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSetIsSubset(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionSetIsSubset, 2>(expCtx) {} boost::intrusive_ptr<Expression> optimize() override; @@ -2144,7 +2119,7 @@ private: class ExpressionSetUnion final : public ExpressionVariadic<ExpressionSetUnion> { public: - explicit ExpressionSetUnion(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSetUnion(ExpressionContext* const expCtx) : ExpressionVariadic<ExpressionSetUnion>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2166,7 +2141,7 @@ public: class ExpressionSize final : public ExpressionFixedArity<ExpressionSize, 1> { public: - explicit ExpressionSize(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSize(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionSize, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2180,7 +2155,7 @@ public: class ExpressionReverseArray final : public ExpressionFixedArity<ExpressionReverseArray, 1> { public: - explicit ExpressionReverseArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionReverseArray(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionReverseArray, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2194,7 +2169,7 @@ public: class ExpressionSlice final : public ExpressionRangedArity<ExpressionSlice, 2, 3> { public: - explicit ExpressionSlice(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSlice(ExpressionContext* const expCtx) : ExpressionRangedArity<ExpressionSlice, 2, 3>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2208,7 +2183,7 @@ public: class ExpressionIsArray final : public ExpressionFixedArity<ExpressionIsArray, 1> { public: - explicit ExpressionIsArray(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionIsArray(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionIsArray, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2221,7 +2196,7 @@ public: class ExpressionRound final : public ExpressionRangedArity<ExpressionRound, 1, 2> { public: - explicit ExpressionRound(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionRound(ExpressionContext* const expCtx) : ExpressionRangedArity<ExpressionRound, 1, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2234,7 +2209,7 @@ public: class ExpressionSplit final : public ExpressionFixedArity<ExpressionSplit, 2> { public: - explicit ExpressionSplit(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSplit(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionSplit, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2248,7 +2223,7 @@ public: class ExpressionSqrt final : public ExpressionSingleNumericArg<ExpressionSqrt> { public: - explicit ExpressionSqrt(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSqrt(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<ExpressionSqrt>(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final; @@ -2262,7 +2237,7 @@ public: class ExpressionStrcasecmp final : public ExpressionFixedArity<ExpressionStrcasecmp, 2> { public: - explicit ExpressionStrcasecmp(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionStrcasecmp(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionStrcasecmp, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2276,7 +2251,7 @@ public: class ExpressionSubstrBytes final : public ExpressionFixedArity<ExpressionSubstrBytes, 3> { public: - explicit ExpressionSubstrBytes(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSubstrBytes(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionSubstrBytes, 3>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2290,7 +2265,7 @@ public: class ExpressionSubstrCP final : public ExpressionFixedArity<ExpressionSubstrCP, 3> { public: - explicit ExpressionSubstrCP(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSubstrCP(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionSubstrCP, 3>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2304,7 +2279,7 @@ public: class ExpressionStrLenBytes final : public ExpressionFixedArity<ExpressionStrLenBytes, 1> { public: - explicit ExpressionStrLenBytes(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionStrLenBytes(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionStrLenBytes, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2318,7 +2293,7 @@ public: class ExpressionBinarySize final : public ExpressionFixedArity<ExpressionBinarySize, 1> { public: - ExpressionBinarySize(const boost::intrusive_ptr<ExpressionContext>& expCtx) + ExpressionBinarySize(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionBinarySize, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2332,7 +2307,7 @@ public: class ExpressionStrLenCP final : public ExpressionFixedArity<ExpressionStrLenCP, 1> { public: - explicit ExpressionStrLenCP(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionStrLenCP(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionStrLenCP, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2346,7 +2321,7 @@ public: class ExpressionSubtract final : public ExpressionFixedArity<ExpressionSubtract, 2> { public: - explicit ExpressionSubtract(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionSubtract(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionSubtract, 2>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2363,7 +2338,7 @@ public: using ExpressionPair = std::pair<boost::intrusive_ptr<Expression>&, boost::intrusive_ptr<Expression>&>; - ExpressionSwitch(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionSwitch(ExpressionContext* const expCtx, std::vector<boost::intrusive_ptr<Expression>> children, std::vector<ExpressionPair> branches) : Expression(expCtx, std::move(children)), @@ -2372,10 +2347,9 @@ public: Value evaluate(const Document& root, Variables* variables) const final; boost::intrusive_ptr<Expression> optimize() final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value serialize(bool explain) const final; void acceptVisitor(ExpressionVisitor* visitor) final { @@ -2393,7 +2367,7 @@ private: class ExpressionToLower final : public ExpressionFixedArity<ExpressionToLower, 1> { public: - explicit ExpressionToLower(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionToLower(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionToLower, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2407,7 +2381,7 @@ public: class ExpressionToUpper final : public ExpressionFixedArity<ExpressionToUpper, 1> { public: - explicit ExpressionToUpper(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionToUpper(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionToUpper, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2431,7 +2405,7 @@ private: }; public: - ExpressionTrim(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionTrim(ExpressionContext* const expCtx, TrimType trimType, StringData name, boost::intrusive_ptr<Expression> input, @@ -2444,10 +2418,9 @@ public: Value evaluate(const Document& root, Variables* variables) const final; boost::intrusive_ptr<Expression> optimize() final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value serialize(bool explain) const final; void acceptVisitor(ExpressionVisitor* visitor) final { @@ -2493,13 +2466,12 @@ private: class ExpressionTrunc final : public ExpressionRangedArity<ExpressionTrunc, 1, 2> { public: - explicit ExpressionTrunc(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionTrunc(ExpressionContext* const expCtx) : ExpressionRangedArity<ExpressionTrunc, 1, 2>(expCtx) {} - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement elem, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement elem, + const VariablesParseState& vps); Value evaluate(const Document& root, Variables* variables) const final; const char* getOpName() const final; @@ -2511,7 +2483,7 @@ public: class ExpressionType final : public ExpressionFixedArity<ExpressionType, 1> { public: - explicit ExpressionType(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionType(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionType, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2524,7 +2496,7 @@ public: class ExpressionIsNumber final : public ExpressionFixedArity<ExpressionIsNumber, 1> { public: - explicit ExpressionIsNumber(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionIsNumber(ExpressionContext* const expCtx) : ExpressionFixedArity<ExpressionIsNumber, 1>(expCtx) {} Value evaluate(const Document& root, Variables* variables) const final; @@ -2537,7 +2509,7 @@ public: class ExpressionWeek final : public DateExpressionAcceptingTimeZone<ExpressionWeek> { public: - ExpressionWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionWeek(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionWeek>( @@ -2555,7 +2527,7 @@ public: class ExpressionIsoWeekYear final : public DateExpressionAcceptingTimeZone<ExpressionIsoWeekYear> { public: - explicit ExpressionIsoWeekYear(const boost::intrusive_ptr<ExpressionContext>& expCtx, + explicit ExpressionIsoWeekYear(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionIsoWeekYear>( @@ -2574,7 +2546,7 @@ public: class ExpressionIsoDayOfWeek final : public DateExpressionAcceptingTimeZone<ExpressionIsoDayOfWeek> { public: - ExpressionIsoDayOfWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionIsoDayOfWeek(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionIsoDayOfWeek>( @@ -2592,7 +2564,7 @@ public: class ExpressionIsoWeek final : public DateExpressionAcceptingTimeZone<ExpressionIsoWeek> { public: - ExpressionIsoWeek(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionIsoWeek(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionIsoWeek>( @@ -2610,7 +2582,7 @@ public: class ExpressionYear final : public DateExpressionAcceptingTimeZone<ExpressionYear> { public: - ExpressionYear(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionYear(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> date, boost::intrusive_ptr<Expression> timeZone = nullptr) : DateExpressionAcceptingTimeZone<ExpressionYear>( @@ -2628,7 +2600,7 @@ public: class ExpressionZip final : public Expression { public: - ExpressionZip(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionZip(ExpressionContext* const expCtx, bool useLongestLength, std::vector<boost::intrusive_ptr<Expression>> children, std::vector<std::reference_wrapper<boost::intrusive_ptr<Expression>>> inputs, @@ -2640,10 +2612,9 @@ public: Value evaluate(const Document& root, Variables* variables) const final; boost::intrusive_ptr<Expression> optimize() final; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value serialize(bool explain) const final; void acceptVisitor(ExpressionVisitor* visitor) final { @@ -2665,14 +2636,13 @@ public: * Creates a $convert expression converting from 'input' to the type given by 'toType'. Leaves * 'onNull' and 'onError' unspecified. */ - static boost::intrusive_ptr<Expression> create(const boost::intrusive_ptr<ExpressionContext>&, + static boost::intrusive_ptr<Expression> create(ExpressionContext* const, boost::intrusive_ptr<Expression> input, BSONType toType); - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value evaluate(const Document& root, Variables* variables) const final; boost::intrusive_ptr<Expression> optimize() final; @@ -2686,7 +2656,7 @@ protected: void _doAddDependencies(DepsTracker* deps) const final; private: - ExpressionConvert(const boost::intrusive_ptr<ExpressionContext>&, + ExpressionConvert(ExpressionContext* const, boost::intrusive_ptr<Expression> input, boost::intrusive_ptr<Expression> to, boost::intrusive_ptr<Expression> onError, @@ -2778,7 +2748,7 @@ public: return _opName; } - ExpressionRegex(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionRegex(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> input, boost::intrusive_ptr<Expression> regex, boost::intrusive_ptr<Expression> options, @@ -2822,10 +2792,9 @@ private: class ExpressionRegexFind final : public ExpressionRegex { public: - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value evaluate(const Document& root, Variables* variables) const final; @@ -2838,10 +2807,9 @@ public: class ExpressionRegexFindAll final : public ExpressionRegex { public: - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value evaluate(const Document& root, Variables* variables) const final; void acceptVisitor(ExpressionVisitor* visitor) final { @@ -2853,10 +2821,9 @@ public: class ExpressionRegexMatch final : public ExpressionRegex { public: - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vpsIn); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vpsIn); Value evaluate(const Document& root, Variables* variables) const final; diff --git a/src/mongo/db/pipeline/expression_and_test.cpp b/src/mongo/db/pipeline/expression_and_test.cpp index dc5b799b000..cbfa37a77d1 100644 --- a/src/mongo/db/pipeline/expression_and_test.cpp +++ b/src/mongo/db/pipeline/expression_and_test.cpp @@ -102,19 +102,18 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObject = BSON("" << spec()); BSONElement specElement = specObject.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); ASSERT_BSONOBJ_EQ( BSON("" << expectedResult()), - toBson(expression->evaluate(fromBson(BSON("a" << 1)), &expCtx->variables))); + toBson(expression->evaluate(fromBson(BSON("a" << 1)), &expCtx.variables))); intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_BSONOBJ_EQ( - BSON("" << expectedResult()), - toBson(optimized->evaluate(fromBson(BSON("a" << 1)), &expCtx->variables))); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), + toBson(optimized->evaluate(fromBson(BSON("a" << 1)), &expCtx.variables))); } protected: @@ -126,11 +125,11 @@ class OptimizeBase { public: virtual ~OptimizeBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObject = BSON("" << spec()); BSONElement specElement = specObject.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); intrusive_ptr<Expression> optimized = expression->optimize(); ASSERT_BSONOBJ_EQ(expectedOptimized(), expressionToBson(optimized)); diff --git a/src/mongo/db/pipeline/expression_compare_test.cpp b/src/mongo/db/pipeline/expression_compare_test.cpp index 8ed9b2aa3d8..11836d77267 100644 --- a/src/mongo/db/pipeline/expression_compare_test.cpp +++ b/src/mongo/db/pipeline/expression_compare_test.cpp @@ -91,9 +91,9 @@ public: void run() { BSONObj specObject = BSON("" << spec()); BSONElement specElement = specObject.firstElement(); - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); intrusive_ptr<Expression> optimized = expression->optimize(); ASSERT_BSONOBJ_EQ(constify(expectedOptimized()), expressionToBson(optimized)); } @@ -122,16 +122,16 @@ public: OptimizeBase::run(); BSONObj specObject = BSON("" << spec()); BSONElement specElement = specObject.firstElement(); - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); // Check expression spec round trip. ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); // Check evaluation result. - ASSERT_BSONOBJ_EQ(expectedResult(), toBson(expression->evaluate({}, &expCtx->variables))); + ASSERT_BSONOBJ_EQ(expectedResult(), toBson(expression->evaluate({}, &expCtx.variables))); // Check that the result is the same after optimizing. intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_BSONOBJ_EQ(expectedResult(), toBson(optimized->evaluate({}, &expCtx->variables))); + ASSERT_BSONOBJ_EQ(expectedResult(), toBson(optimized->evaluate({}, &expCtx.variables))); } protected: @@ -160,11 +160,11 @@ class ParseError { public: virtual ~ParseError() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObject = BSON("" << spec()); BSONElement specElement = specObject.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - ASSERT_THROWS(Expression::parseOperand(expCtx, specElement, vps), AssertionException); + VariablesParseState vps = expCtx.variablesParseState; + ASSERT_THROWS(Expression::parseOperand(&expCtx, specElement, vps), AssertionException); } protected: @@ -365,10 +365,10 @@ public: void run() { BSONObj specObject = BSON("" << BSON("$ne" << BSON_ARRAY("a" << 1))); BSONElement specElement = specObject.firstElement(); - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); - ASSERT_VALUE_EQ(expression->evaluate({}, &expCtx->variables), Value(true)); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); + ASSERT_VALUE_EQ(expression->evaluate({}, &expCtx.variables), Value(true)); } }; diff --git a/src/mongo/db/pipeline/expression_context.cpp b/src/mongo/db/pipeline/expression_context.cpp index a077071dca3..8625cf80903 100644 --- a/src/mongo/db/pipeline/expression_context.cpp +++ b/src/mongo/db/pipeline/expression_context.cpp @@ -36,7 +36,6 @@ #include "mongo/db/query/collation/collation_spec.h" #include "mongo/db/query/collation/collator_factory_interface.h" #include "mongo/util/intrusive_counter.h" -#include "mongo/util/scopeguard.h" namespace mongo { @@ -126,16 +125,8 @@ ExpressionContext::ExpressionContext( if (!isMapReduce) { jsHeapLimitMB = internalQueryJavaScriptHeapSizeLimitMB.load(); } - if (letParameters) { - // TODO SERVER-47713: One possible fix is to change the interface of everything that needs - // an expression context intrusive_ptr to take a raw ptr. - auto intrusiveThis = boost::intrusive_ptr{this}; - ON_BLOCK_EXIT([&] { - intrusiveThis.detach(); - unsafeRefDecRefCountTo(0u); - }); - variables.seedVariablesWithLetParameters(intrusiveThis, *letParameters); - } + if (letParameters) + variables.seedVariablesWithLetParameters(this, *letParameters); } ExpressionContext::ExpressionContext(OperationContext* opCtx, @@ -160,16 +151,8 @@ ExpressionContext::ExpressionContext(OperationContext* opCtx, } jsHeapLimitMB = internalQueryJavaScriptHeapSizeLimitMB.load(); - if (letParameters) { - // TODO SERVER-47713: One possible fix is to change the interface of everything that needs - // an expression context intrusive_ptr to take a raw ptr. - auto intrusiveThis = boost::intrusive_ptr{this}; - ON_BLOCK_EXIT([&] { - intrusiveThis.detach(); - unsafeRefDecRefCountTo(0u); - }); - variables.seedVariablesWithLetParameters(intrusiveThis, *letParameters); - } + if (letParameters) + variables.seedVariablesWithLetParameters(this, *letParameters); } void ExpressionContext::checkForInterrupt() { @@ -181,9 +164,8 @@ void ExpressionContext::checkForInterrupt() { } } -ExpressionContext::CollatorStash::CollatorStash( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - std::unique_ptr<CollatorInterface> newCollator) +ExpressionContext::CollatorStash::CollatorStash(ExpressionContext* const expCtx, + std::unique_ptr<CollatorInterface> newCollator) : _expCtx(expCtx), _originalCollator(std::move(_expCtx->_collator)) { _expCtx->setCollator(std::move(newCollator)); } diff --git a/src/mongo/db/pipeline/expression_context.h b/src/mongo/db/pipeline/expression_context.h index 7a5976a48b7..d3a491119d3 100644 --- a/src/mongo/db/pipeline/expression_context.h +++ b/src/mongo/db/pipeline/expression_context.h @@ -88,7 +88,7 @@ public: * This constructor is private, all CollatorStashes should be created by calling * ExpressionContext::temporarilyChangeCollator(). */ - CollatorStash(const boost::intrusive_ptr<ExpressionContext>& expCtx, + CollatorStash(ExpressionContext* const expCtx, std::unique_ptr<CollatorInterface> newCollator); friend class ExpressionContext; diff --git a/src/mongo/db/pipeline/expression_convert_test.cpp b/src/mongo/db/pipeline/expression_convert_test.cpp index 05f3de3ccf0..5d9e53fd519 100644 --- a/src/mongo/db/pipeline/expression_convert_test.cpp +++ b/src/mongo/db/pipeline/expression_convert_test.cpp @@ -64,7 +64,7 @@ TEST_F(ExpressionConvertTest, ParseAndSerializeWithoutOptionalArguments) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(fromjson("{$convert: {input: '$path1', to: {$const: 'int'}}}")), convertExp->serialize(false)); @@ -81,7 +81,7 @@ TEST_F(ExpressionConvertTest, ParseAndSerializeWithOnError) { << "to" << "int" << "onError" << 0)); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ( Value(fromjson("{$convert: {input: '$path1', to: {$const: 'int'}, onError: {$const: 0}}}")), @@ -100,7 +100,7 @@ TEST_F(ExpressionConvertTest, ParseAndSerializeWithOnNull) { << "to" << "int" << "onNull" << 0)); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ( Value(fromjson("{$convert: {input: '$path1', to: {$const: 'int'}, onNull: {$const: 0}}}")), @@ -117,13 +117,13 @@ TEST_F(ExpressionConvertTest, ConvertWithoutInputFailsToParse) { auto spec = BSON("$convert" << BSON("to" << "int" << "onError" << 0)); - ASSERT_THROWS_WITH_CHECK(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), - AssertionException, - [](const AssertionException& exception) { - ASSERT_EQ(exception.code(), ErrorCodes::FailedToParse); - ASSERT_STRING_CONTAINS(exception.reason(), - "Missing 'input' parameter to $convert"); - }); + ASSERT_THROWS_WITH_CHECK( + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), + AssertionException, + [](const AssertionException& exception) { + ASSERT_EQ(exception.code(), ErrorCodes::FailedToParse); + ASSERT_STRING_CONTAINS(exception.reason(), "Missing 'input' parameter to $convert"); + }); } TEST_F(ExpressionConvertTest, ConvertWithoutToFailsToParse) { @@ -132,13 +132,13 @@ TEST_F(ExpressionConvertTest, ConvertWithoutToFailsToParse) { auto spec = BSON("$convert" << BSON("input" << "$path1" << "onError" << 0)); - ASSERT_THROWS_WITH_CHECK(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), - AssertionException, - [](const AssertionException& exception) { - ASSERT_EQ(exception.code(), ErrorCodes::FailedToParse); - ASSERT_STRING_CONTAINS(exception.reason(), - "Missing 'to' parameter to $convert"); - }); + ASSERT_THROWS_WITH_CHECK( + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), + AssertionException, + [](const AssertionException& exception) { + ASSERT_EQ(exception.code(), ErrorCodes::FailedToParse); + ASSERT_STRING_CONTAINS(exception.reason(), "Missing 'to' parameter to $convert"); + }); } TEST_F(ExpressionConvertTest, InvalidTypeNameFails) { @@ -150,7 +150,7 @@ TEST_F(ExpressionConvertTest, InvalidTypeNameFails) { << "dinosaur" << "onError" << 0)); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate(Document(), &expCtx->variables), AssertionException, @@ -167,7 +167,7 @@ TEST_F(ExpressionConvertTest, NonIntegralTypeFails) { << "$path1" << "to" << 3.6 << "onError" << 0)); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate(Document(), &expCtx->variables), AssertionException, @@ -189,7 +189,7 @@ TEST_F(ExpressionConvertTest, NonStringNonNumericalTypeFails) { << "Tyrannosaurus rex") << "onError" << 0)); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate(Document(), &expCtx->variables), AssertionException, @@ -208,7 +208,7 @@ TEST_F(ExpressionConvertTest, InvalidNumericTargetTypeFails) { << "$path1" << "to" << 100 << "onError" << 0)); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate(Document(), &expCtx->variables), @@ -228,7 +228,7 @@ TEST_F(ExpressionConvertTest, NegativeNumericTargetTypeFails) { << "$path1" << "to" << -2 << "onError" << 0)); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate(Document(), &expCtx->variables), @@ -286,7 +286,8 @@ TEST_F(ExpressionConvertTest, UnsupportedConversionShouldThrowUnlessOnErrorProvi Document input{{"path1", inputValue}}; - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate(input, &expCtx->variables), AssertionException, @@ -309,7 +310,8 @@ TEST_F(ExpressionConvertTest, UnsupportedConversionShouldThrowUnlessOnErrorProvi Document input{{"path1", inputValue}}; - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate(input, &expCtx->variables), "X"_sd, BSONType::String); @@ -323,7 +325,7 @@ TEST_F(ExpressionConvertTest, ConvertNullishInput) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document nullInput{{"path1", BSONNULL}}; Document undefinedInput{{"path1", BSONUndefined}}; @@ -345,7 +347,7 @@ TEST_F(ExpressionConvertTest, ConvertNullishInputWithOnNull) { << "B)" << "onError" << "Should not be used here")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document nullInput{{"path1", BSONNULL}}; Document undefinedInput{{"path1", BSONUndefined}}; @@ -367,7 +369,7 @@ TEST_F(ExpressionConvertTest, NullishToReturnsNull) { << "Should not be used here" << "onError" << "Also should not be used")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document nullInput{{"path1", BSONNULL}}; Document undefinedInput{{"path1", BSONUndefined}}; @@ -384,7 +386,7 @@ TEST_F(ExpressionConvertTest, NullInputOverridesNullTo) { auto spec = BSON("$convert" << BSON("input" << Value(BSONNULL) << "to" << Value(BSONNULL) << "onNull" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate(Document{}, &expCtx->variables), "X"_sd, BSONType::String); @@ -395,7 +397,7 @@ TEST_F(ExpressionConvertTest, ConvertOptimizesToExpressionConstant) { auto spec = BSON("$convert" << BSON("input" << 0 << "to" << "double")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); convertExp = convertExp->optimize(); auto constResult = dynamic_cast<ExpressionConstant*>(convertExp.get()); @@ -410,7 +412,7 @@ TEST_F(ExpressionConvertTest, ConvertWithOnErrorOptimizesToExpressionConstant) { << "objectId" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); convertExp = convertExp->optimize(); auto constResult = dynamic_cast<ExpressionConstant*>(convertExp.get()); @@ -425,7 +427,7 @@ TEST_F(ExpressionConvertTest, DoubleIdentityConversion) { << "$path1" << "to" << "double")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document doubleInput{{"path1", 2.4}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -455,7 +457,7 @@ TEST_F(ExpressionConvertTest, BoolIdentityConversion) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document trueBoolInput{{"path1", true}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -473,7 +475,7 @@ TEST_F(ExpressionConvertTest, StringIdentityConversion) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document stringInput{{"path1", "More cowbell"_sd}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -487,7 +489,7 @@ TEST_F(ExpressionConvertTest, ObjectIdIdentityConversion) { << "$path1" << "to" << "objectId")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document oidInput{{"path1", OID("0123456789abcdef01234567")}}; ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate(oidInput, &expCtx->variables), @@ -502,7 +504,7 @@ TEST_F(ExpressionConvertTest, DateIdentityConversion) { << "$path1" << "to" << "date")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document dateInput{{"path1", Date_t{}}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -516,7 +518,7 @@ TEST_F(ExpressionConvertTest, IntIdentityConversion) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document intInput{{"path1", int{123}}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -530,7 +532,7 @@ TEST_F(ExpressionConvertTest, LongIdentityConversion) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document longInput{{"path1", 123LL}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -544,7 +546,7 @@ TEST_F(ExpressionConvertTest, DecimalIdentityConversion) { << "$path1" << "to" << "decimal")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document decimalInput{{"path1", Decimal128("2.4")}}; ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate(decimalInput, &expCtx->variables), @@ -575,7 +577,7 @@ TEST_F(ExpressionConvertTest, ConvertDateToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); // All date inputs evaluate as true. Document dateInput{{"path1", Date_t{}}}; @@ -590,7 +592,7 @@ TEST_F(ExpressionConvertTest, ConvertIntToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document trueIntInput{{"path1", int{1}}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -608,7 +610,7 @@ TEST_F(ExpressionConvertTest, ConvertLongToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document trueLongInput{{"path1", -1LL}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -626,7 +628,7 @@ TEST_F(ExpressionConvertTest, ConvertDoubleToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document trueDoubleInput{{"path1", 2.4}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -656,7 +658,7 @@ TEST_F(ExpressionConvertTest, ConvertDecimalToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document trueDecimalInput{{"path1", Decimal128(5)}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -698,7 +700,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document stringInput{{"path1", "str"_sd}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -716,7 +718,7 @@ TEST_F(ExpressionConvertTest, ConvertObjectIdToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document oidInput{{"path1", OID("59E8A8D8FEDCBA9876543210")}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -730,7 +732,7 @@ TEST_F(ExpressionConvertTest, ConvertMinKeyToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document minKeyInput{{"path1", MINKEY}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -744,7 +746,7 @@ TEST_F(ExpressionConvertTest, ConvertObjectToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document objectInput{{"path1", Document{{"foo", 1}}}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -758,7 +760,7 @@ TEST_F(ExpressionConvertTest, ConvertArrayToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document arrayInput{{"path1", BSON_ARRAY(1)}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -772,7 +774,7 @@ TEST_F(ExpressionConvertTest, ConvertBinDataToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); char data[] = "(^_^)"; Document binInput{{"path1", BSONBinData(data, sizeof(data), BinDataType::BinDataGeneral)}}; @@ -787,7 +789,7 @@ TEST_F(ExpressionConvertTest, ConvertRegexToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document regexInput{{"path1", BSONRegEx("ab*a"_sd)}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -801,7 +803,7 @@ TEST_F(ExpressionConvertTest, ConvertDBRefToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document refInput{{"path1", BSONDBRef("db.coll"_sd, OID("aaaaaaaaaaaaaaaaaaaaaaaa"))}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -815,7 +817,7 @@ TEST_F(ExpressionConvertTest, ConvertCodeToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document codeInput{{"path1", BSONCode("print('Hello world!');"_sd)}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -829,7 +831,7 @@ TEST_F(ExpressionConvertTest, ConvertSymbolToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document symbolInput{{"path1", BSONSymbol("print"_sd)}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -843,7 +845,7 @@ TEST_F(ExpressionConvertTest, ConvertCodeWScopeToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document codeWScopeInput{ {"path1", BSONCodeWScope("print('Hello again, world!')"_sd, BSONObj())}}; @@ -858,7 +860,7 @@ TEST_F(ExpressionConvertTest, ConvertTimestampToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document timestampInput{{"path1", Timestamp()}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -872,7 +874,7 @@ TEST_F(ExpressionConvertTest, ConvertMaxKeyToBool) { << "$path1" << "to" << "bool")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document maxKeyInput{{"path1", MAXKEY}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -886,7 +888,7 @@ TEST_F(ExpressionConvertTest, ConvertNumericToDouble) { << "$path1" << "to" << "double")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document intInput{{"path1", int{1}}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -949,7 +951,7 @@ TEST_F(ExpressionConvertTest, ConvertDateToDouble) { << "$path1" << "to" << "double")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document dateInput{{"path1", Date_t::fromMillisSinceEpoch(123)}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -970,7 +972,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDecimalToDouble) { << "$path1" << "to" << "double")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document overflowInput{{"path1", Decimal128("1e309")}}; ASSERT_THROWS_WITH_CHECK(convertExp->evaluate(overflowInput, &expCtx->variables), @@ -1000,7 +1002,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDecimalToDoubleWithOnError) { << "double" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document overflowInput{{"path1", Decimal128("1e309")}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1018,7 +1020,7 @@ TEST_F(ExpressionConvertTest, ConvertNumericToDecimal) { << "$path1" << "to" << "decimal")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document intInput{{"path1", int{1}}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1073,7 +1075,7 @@ TEST_F(ExpressionConvertTest, ConvertDateToDecimal) { << "$path1" << "to" << "decimal")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document dateInput{{"path1", Date_t::fromMillisSinceEpoch(123)}}; ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate(dateInput, &expCtx->variables), @@ -1093,7 +1095,7 @@ TEST_F(ExpressionConvertTest, ConvertDoubleToInt) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document simpleInput{{"path1", 1.0}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1134,7 +1136,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDoubleToInt) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); int maxInt = std::numeric_limits<int>::max(); double overflowInt = @@ -1199,7 +1201,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDoubleToIntWithOnError) { << "int" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); int maxInt = std::numeric_limits<int>::max(); double overflowInt = @@ -1235,7 +1237,7 @@ TEST_F(ExpressionConvertTest, ConvertDoubleToLong) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document simpleInput{{"path1", 1.0}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1280,7 +1282,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDoubleToLong) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); double overflowLong = BSONElement::kLongLongMaxPlusOneAsDouble; Document overflowInput{{"path1", overflowLong}}; @@ -1343,7 +1345,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDoubleToLongWithOnError) { << "long" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); double overflowLong = BSONElement::kLongLongMaxPlusOneAsDouble; Document overflowInput{{"path1", overflowLong}}; @@ -1377,7 +1379,7 @@ TEST_F(ExpressionConvertTest, ConvertDecimalToInt) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document simpleInput{{"path1", Decimal128("1.0")}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1418,7 +1420,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDecimalToInt) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); int maxInt = std::numeric_limits<int>::max(); Document overflowInput{{"path1", Decimal128(maxInt).add(Decimal128(1))}}; @@ -1488,7 +1490,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDecimalToIntWithOnError) { << "int" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); int maxInt = std::numeric_limits<int>::max(); Document overflowInput{{"path1", Decimal128(maxInt).add(Decimal128(1))}}; @@ -1526,7 +1528,7 @@ TEST_F(ExpressionConvertTest, ConvertDecimalToLong) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document simpleInput{{"path1", Decimal128("1.0")}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1567,7 +1569,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDecimalToLong) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); long long maxVal = std::numeric_limits<long long>::max(); Document overflowInput{{"path1", Decimal128(std::int64_t{maxVal}).add(Decimal128(1))}}; @@ -1638,7 +1640,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsDecimalToLongWithOnError) { << "long" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); long long maxVal = std::numeric_limits<long long>::max(); Document overflowInput{{"path1", Decimal128(std::int64_t{maxVal}).add(Decimal128(1))}}; @@ -1677,7 +1679,7 @@ TEST_F(ExpressionConvertTest, ConvertDateToLong) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document dateInput{{"path1", Date_t::fromMillisSinceEpoch(123LL)}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1691,7 +1693,7 @@ TEST_F(ExpressionConvertTest, ConvertIntToLong) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document simpleInput{{"path1", 1}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1715,7 +1717,7 @@ TEST_F(ExpressionConvertTest, ConvertLongToInt) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document simpleInput{{"path1", 1}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1739,7 +1741,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsLongToInt) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); long long maxInt = std::numeric_limits<int>::max(); Document overflowInput{{"path1", maxInt + 1}}; @@ -1771,7 +1773,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsLongToIntWithOnError) { << "int" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); long long maxInt = std::numeric_limits<int>::max(); Document overflowInput{{"path1", maxInt + 1}}; @@ -1791,7 +1793,7 @@ TEST_F(ExpressionConvertTest, ConvertBoolToInt) { << "$path1" << "to" << "int")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document boolFalse{{"path1", false}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1809,7 +1811,7 @@ TEST_F(ExpressionConvertTest, ConvertBoolToLong) { << "$path1" << "to" << "long")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document boolFalse{{"path1", false}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -1827,7 +1829,7 @@ TEST_F(ExpressionConvertTest, ConvertNumberToDate) { << "$path1" << "to" << "date")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document longInput{{"path1", 0LL}}; ASSERT_EQ(dateToISOStringUTC(convertExp->evaluate(longInput, &expCtx->variables).getDate()), @@ -1859,7 +1861,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsNumberToDate) { << "$path1" << "to" << "date")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document doubleOverflowInput{{"path1", 1.0e100}}; ASSERT_THROWS_WITH_CHECK(convertExp->evaluate(doubleOverflowInput, &expCtx->variables), @@ -1977,7 +1979,7 @@ TEST_F(ExpressionConvertTest, ConvertOutOfBoundsNumberToDateWithOnError) { << "date" << "onError" << "X")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); // Int is explicitly disallowed for date conversions. Clients must use 64-bit long instead. Document intInput{{"path1", int{0}}}; @@ -2042,7 +2044,7 @@ TEST_F(ExpressionConvertTest, ConvertObjectIdToDate) { << "$path1" << "to" << "date")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document oidInput{{"path1", OID("59E8A8D8FEDCBA9876543210")}}; @@ -2054,12 +2056,12 @@ TEST_F(ExpressionConvertTest, ConvertStringToInt) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '5', to: 'int'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 5, BSONType::NumberInt); spec = fromjson("{$convert: {input: '" + std::to_string(kIntMax) + "', to: 'int'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), kIntMax, BSONType::NumberInt); } @@ -2068,7 +2070,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToIntOverflow) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '" + std::to_string(kIntMax + 1) + "', to: 'int'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2077,7 +2079,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToIntOverflow) { }); spec = fromjson("{$convert: {input: '" + std::to_string(kIntMin - 1) + "', to: 'int'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2092,13 +2094,13 @@ TEST_F(ExpressionConvertTest, ConvertStringToIntOverflowWithOnError) { auto spec = fromjson("{$convert: {input: '" + std::to_string(kIntMax + 1) + "', to: 'int', onError: '" + onErrorValue + "'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '" + std::to_string(kIntMin - 1) + "', to: 'int', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); } @@ -2107,12 +2109,12 @@ TEST_F(ExpressionConvertTest, ConvertStringToLong) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '5', to: 'long'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 5LL, BSONType::NumberLong); spec = fromjson("{$convert: {input: '" + std::to_string(kLongMax) + "', to: 'long'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), kLongMax, BSONType::NumberLong); } @@ -2124,7 +2126,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToLongOverflow) { longMaxPlusOneAsString = longMaxPlusOneAsString.substr(0, longMaxPlusOneAsString.find('.')); auto spec = fromjson("{$convert: {input: '" + longMaxPlusOneAsString + "', to: 'long'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2136,7 +2138,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToLongOverflow) { longMinMinusOneAsString = longMinMinusOneAsString.substr(0, longMinMinusOneAsString.find('.')); spec = fromjson("{$convert: {input: '" + longMinMinusOneAsString + "', to: 'long'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2149,7 +2151,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToLongFailsForFloats) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '5.5', to: 'long'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2159,7 +2161,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToLongFailsForFloats) { }); spec = fromjson("{$convert: {input: '5.0', to: 'long'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2178,7 +2180,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToLongWithOnError) { auto spec = fromjson("{$convert: {input: '" + longMaxPlusOneAsString + "', to: 'long', onError: '" + onErrorValue + "'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); @@ -2187,17 +2189,17 @@ TEST_F(ExpressionConvertTest, ConvertStringToLongWithOnError) { spec = fromjson("{$convert: {input: '" + longMinMinusOneAsString + "', to: 'long', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '5.5', to: 'long', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '5.0', to: 'long', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); } @@ -2206,27 +2208,27 @@ TEST_F(ExpressionConvertTest, ConvertStringToDouble) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '5', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 5.0, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '5.5', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 5.5, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '.5', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 0.5, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '+5', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 5.0, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '+5.0e42', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 5.0e42, BSONType::NumberDouble); } @@ -2237,13 +2239,13 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleWithPrecisionLoss) { // Note that the least significant bits get lost, because the significand of a double is not // wide enough for the given input string in its entirety. auto spec = fromjson("{$convert: {input: '10000000000000000001', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 1e19, BSONType::NumberDouble); // Again, some precision is lost in the conversion to double. spec = fromjson("{$convert: {input: '1.125000000000000000005', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 1.125, BSONType::NumberDouble); } @@ -2252,7 +2254,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleFailsForInvalidFloats) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '.5.', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2262,7 +2264,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleFailsForInvalidFloats) { }); spec = fromjson("{$convert: {input: '5.5f', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2277,47 +2279,47 @@ TEST_F(ExpressionConvertTest, ConvertInfinityStringsToDouble) { auto infValue = std::numeric_limits<double>::infinity(); auto spec = fromjson("{$convert: {input: 'Infinity', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: 'INF', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: 'infinity', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '+InFiNiTy', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '-Infinity', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), -infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '-INF', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), -infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '-InFiNiTy', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), -infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '-inf', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), -infValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: '-infinity', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), -infValue, BSONType::NumberDouble); } @@ -2326,25 +2328,25 @@ TEST_F(ExpressionConvertTest, ConvertZeroStringsToDouble) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '-0', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDouble); ASSERT_TRUE(std::signbit(result.getDouble())); spec = fromjson("{$convert: {input: '-0.0', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDouble); ASSERT_TRUE(std::signbit(result.getDouble())); spec = fromjson("{$convert: {input: '+0', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDouble); ASSERT_FALSE(std::signbit(result.getDouble())); spec = fromjson("{$convert: {input: '+0.0', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDouble); ASSERT_FALSE(std::signbit(result.getDouble())); @@ -2355,29 +2357,29 @@ TEST_F(ExpressionConvertTest, ConvertNanStringsToDouble) { auto nanValue = std::numeric_limits<double>::quiet_NaN(); auto spec = fromjson("{$convert: {input: 'nan', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({}, &expCtx->variables); ASSERT_TRUE(std::isnan(result.getDouble())); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), nanValue, BSONType::NumberDouble); spec = fromjson("{$convert: {input: 'Nan', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_TRUE(std::isnan(result.getDouble())); spec = fromjson("{$convert: {input: 'NaN', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_TRUE(std::isnan(result.getDouble())); spec = fromjson("{$convert: {input: '-NAN', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_TRUE(std::isnan(result.getDouble())); spec = fromjson("{$convert: {input: '+NaN', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_TRUE(std::isnan(result.getDouble())); } @@ -2386,7 +2388,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleOverflow) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '" + kDoubleOverflow.toString() + "', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2396,7 +2398,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleOverflow) { spec = fromjson("{$convert: {input: '" + kDoubleNegativeOverflow.toString() + "', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2409,7 +2411,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleUnderflow) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '1E-1000', to: 'double'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, @@ -2421,7 +2423,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleUnderflow) { }); spec = fromjson("{$convert: {input: '-1E-1000', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, @@ -2439,23 +2441,23 @@ TEST_F(ExpressionConvertTest, ConvertStringToDoubleWithOnError) { auto spec = fromjson("{$convert: {input: '" + kDoubleOverflow.toString() + "', to: 'double', onError: '" + onErrorValue + "'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '" + kDoubleNegativeOverflow.toString() + "', to: 'double', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '.5.', to: 'double', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '5.5f', to: 'double', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); } @@ -2464,31 +2466,31 @@ TEST_F(ExpressionConvertTest, ConvertStringToDecimal) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '5', to: 'decimal'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), 5, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '2.02', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), Decimal128("2.02"), BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '2.02E200', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate({}, &expCtx->variables), Decimal128("2.02E200"), BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '" + Decimal128::kLargestPositive.toString() + "', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate({}, &expCtx->variables), Decimal128::kLargestPositive, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '" + Decimal128::kLargestNegative.toString() + "', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate({}, &expCtx->variables), Decimal128::kLargestNegative, BSONType::NumberDecimal); @@ -2500,47 +2502,47 @@ TEST_F(ExpressionConvertTest, ConvertInfinityStringsToDecimal) { auto negInfValue = Decimal128::kNegativeInfinity; auto spec = fromjson("{$convert: {input: 'Infinity', to: 'decimal'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: 'INF', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: 'infinity', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '+InFiNiTy', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), infValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-Infinity', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negInfValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-INF', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negInfValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-InFiNiTy', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negInfValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-inf', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negInfValue, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-infinity', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negInfValue, BSONType::NumberDecimal); } @@ -2551,37 +2553,37 @@ TEST_F(ExpressionConvertTest, ConvertNanStringsToDecimal) { auto negativeNan = Decimal128::kNegativeNaN; auto spec = fromjson("{$convert: {input: 'nan', to: 'decimal'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), positiveNan, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: 'Nan', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), positiveNan, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: 'NaN', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), positiveNan, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '+NaN', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), positiveNan, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-NAN', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negativeNan, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-nan', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negativeNan, BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '-NaN', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), negativeNan, BSONType::NumberDecimal); } @@ -2590,28 +2592,28 @@ TEST_F(ExpressionConvertTest, ConvertZeroStringsToDecimal) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '-0', to: 'decimal'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDecimal); ASSERT_TRUE(result.getDecimal().isZero()); ASSERT_TRUE(result.getDecimal().isNegative()); spec = fromjson("{$convert: {input: '-0.0', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDecimal); ASSERT_TRUE(result.getDecimal().isZero()); ASSERT_TRUE(result.getDecimal().isNegative()); spec = fromjson("{$convert: {input: '+0', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDecimal); ASSERT_TRUE(result.getDecimal().isZero()); ASSERT_FALSE(result.getDecimal().isNegative()); spec = fromjson("{$convert: {input: '+0.0', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, 0, BSONType::NumberDecimal); ASSERT_TRUE(result.getDecimal().isZero()); @@ -2622,7 +2624,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDecimalOverflow) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '1E6145', to: 'decimal'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2633,7 +2635,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDecimalOverflow) { }); spec = fromjson("{$convert: {input: '-1E6145', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2648,7 +2650,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDecimalUnderflow) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '1E-6178', to: 'decimal'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2659,7 +2661,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDecimalUnderflow) { }); spec = fromjson("{$convert: {input: '-1E-6177', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2675,12 +2677,12 @@ TEST_F(ExpressionConvertTest, ConvertStringToDecimalWithPrecisionLoss) { auto spec = fromjson("{$convert: {input: '10000000000000000000000000000000001', to: 'decimal'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), Decimal128("1e34"), BSONType::NumberDecimal); spec = fromjson("{$convert: {input: '1.1250000000000000000000000000000001', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), Decimal128("1.125"), BSONType::NumberDecimal); } @@ -2691,13 +2693,13 @@ TEST_F(ExpressionConvertTest, ConvertStringToDecimalWithOnError) { auto spec = fromjson("{$convert: {input: '1E6145', to: 'decimal', onError: '" + onErrorValue + "'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '-1E-6177', to: 'decimal', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); } @@ -2710,37 +2712,37 @@ TEST_F(ExpressionConvertTest, ConvertStringToNumberFailsForHexStrings) { }; auto spec = fromjson("{$convert: {input: '0xFF', to: 'int'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, invalidHexFailure); spec = fromjson("{$convert: {input: '0xFF', to: 'long'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, invalidHexFailure); spec = fromjson("{$convert: {input: '0xFF', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, invalidHexFailure); spec = fromjson("{$convert: {input: '0xFF', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, invalidHexFailure); spec = fromjson("{$convert: {input: '0x00', to: 'int'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, invalidHexFailure); spec = fromjson("{$convert: {input: '0x00', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK( convertExp->evaluate({}, &expCtx->variables), AssertionException, invalidHexFailure); spec = fromjson("{$convert: {input: 'FF', to: 'double'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2750,7 +2752,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToNumberFailsForHexStrings) { }); spec = fromjson("{$convert: {input: 'FF', to: 'decimal'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2765,12 +2767,12 @@ TEST_F(ExpressionConvertTest, ConvertStringToOID) { auto oid = OID::gen(); auto spec = fromjson("{$convert: {input: '" + oid.toString() + "', to: 'objectId'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), oid, BSONType::jstOID); spec = fromjson("{$convert: {input: '123456789abcdef123456789', to: 'objectId'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate({}, &expCtx->variables), OID("123456789abcdef123456789"), BSONType::jstOID); @@ -2780,7 +2782,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToOIDFailsForInvalidHexStrings) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: 'InvalidHexButSizeCorrect', to: 'objectId'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2790,7 +2792,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToOIDFailsForInvalidHexStrings) { }); spec = fromjson("{$convert: {input: 'InvalidSize', to: 'objectId'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2800,7 +2802,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToOIDFailsForInvalidHexStrings) { }); spec = fromjson("{$convert: {input: '0x123456789abcdef123456789', to: 'objectId'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_WITH_CHECK(convertExp->evaluate({}, &expCtx->variables), AssertionException, [](const AssertionException& exception) { @@ -2817,19 +2819,19 @@ TEST_F(ExpressionConvertTest, ConvertStringToOIDWithOnError) { auto spec = fromjson("{$convert: {input: 'InvalidHexButSizeCorrect', to: 'objectId', onError: '" + onErrorValue + "'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: 'InvalidSize', to: 'objectId', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); spec = fromjson("{$convert: {input: '0x123456789abcdef123456789', to: 'objectId', onError: '" + onErrorValue + "'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_CONTENTS_AND_TYPE( convertExp->evaluate({}, &expCtx->variables), onErrorValue, BSONType::String); } @@ -2838,13 +2840,13 @@ TEST_F(ExpressionConvertTest, ConvertStringToDateRejectsUnparsableString) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '60.Monday1770/06:59', to: 'date'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(convertExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); spec = fromjson("{$convert: {input: 'Definitely not a date', to: 'date'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(convertExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -2854,13 +2856,13 @@ TEST_F(ExpressionConvertTest, ConvertStringToDateRejectsTimezoneNameInString) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '2017-07-13T10:02:57 Europe/London', to: 'date'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(convertExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); spec = fromjson("{$convert: {input: 'July 4, 2017 Europe/London', to: 'date'}}"); - convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(convertExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -2870,7 +2872,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDate) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '$path1', to: 'date'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({{"path1", Value("2017-07-06T12:35:37Z"_sd)}}, &expCtx->variables); @@ -2891,7 +2893,7 @@ TEST_F(ExpressionConvertTest, ConvertStringWithTimezoneToDate) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '$path1', to: 'date'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({{"path1", Value("2017-07-14T12:02:44.771 GMT+02:00"_sd)}}, &expCtx->variables); @@ -2908,7 +2910,7 @@ TEST_F(ExpressionConvertTest, ConvertVerbalStringToDate) { auto expCtx = getExpCtx(); auto spec = fromjson("{$convert: {input: '$path1', to: 'date'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({{"path1", Value("July 4th, 2017"_sd)}}, &expCtx->variables); ASSERT_EQ(result.getType(), BSONType::Date); @@ -2929,7 +2931,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDateWithOnError) { auto spec = fromjson("{$convert: {input: '$path1', to: 'date', onError: '" + onErrorValue + "'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({{"path1", Value("Not a date"_sd)}}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, onErrorValue, BSONType::String); @@ -2948,7 +2950,7 @@ TEST_F(ExpressionConvertTest, ConvertStringToDateWithOnNull) { auto spec = fromjson("{$convert: {input: '$path1', to: 'date', onNull: '" + onNullValue + "'}}"); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto result = convertExp->evaluate({}, &expCtx->variables); ASSERT_VALUE_CONTENTS_AND_TYPE(result, onNullValue, BSONType::String); @@ -2964,7 +2966,7 @@ TEST_F(ExpressionConvertTest, FormatDouble) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document zeroInput{{"path1", 0.0}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -3037,7 +3039,7 @@ TEST_F(ExpressionConvertTest, FormatObjectId) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document zeroInput{{"path1", OID("000000000000000000000000")}}; ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate(zeroInput, &expCtx->variables), @@ -3057,7 +3059,7 @@ TEST_F(ExpressionConvertTest, FormatBool) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document trueInput{{"path1", true}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -3075,7 +3077,7 @@ TEST_F(ExpressionConvertTest, FormatDate) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document epochInput{{"path1", Date_t::fromMillisSinceEpoch(0LL)}}; ASSERT_VALUE_CONTENTS_AND_TYPE(convertExp->evaluate(epochInput, &expCtx->variables), @@ -3095,7 +3097,7 @@ TEST_F(ExpressionConvertTest, FormatInt) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document zeroInput{{"path1", int{0}}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -3117,7 +3119,7 @@ TEST_F(ExpressionConvertTest, FormatLong) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document zeroInput{{"path1", 0LL}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -3141,7 +3143,7 @@ TEST_F(ExpressionConvertTest, FormatDecimal) { << "$path1" << "to" << "string")); - auto convertExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convertExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); Document zeroInput{{"path1", Decimal128("0")}}; ASSERT_VALUE_CONTENTS_AND_TYPE( @@ -3253,15 +3255,15 @@ TEST_F(ExpressionConvertShortcutsTest, RejectsMoreThanOneInput) { auto expCtx = getExpCtx(); BSONObj spec = BSON("$toInt" << BSON_ARRAY(1 << 3)); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), + ASSERT_THROWS_CODE(Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), AssertionException, 50723); spec = BSON("$toLong" << BSON_ARRAY(1 << 3)); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), + ASSERT_THROWS_CODE(Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), AssertionException, 50723); spec = BSON("$toDouble" << BSON_ARRAY(1 << 3)); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), + ASSERT_THROWS_CODE(Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), AssertionException, 50723); } @@ -3270,15 +3272,15 @@ TEST_F(ExpressionConvertShortcutsTest, RejectsZeroInputs) { auto expCtx = getExpCtx(); BSONObj spec = BSON("$toInt" << BSONArray()); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), + ASSERT_THROWS_CODE(Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), AssertionException, 50723); spec = BSON("$toLong" << BSONArray()); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), + ASSERT_THROWS_CODE(Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), AssertionException, 50723); spec = BSON("$toDouble" << BSONArray()); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), + ASSERT_THROWS_CODE(Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), AssertionException, 50723); } @@ -3288,15 +3290,15 @@ TEST_F(ExpressionConvertShortcutsTest, AcceptsSingleArgumentInArrayOrByItself) { BSONObj spec = BSON("$toInt" << "1"); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); spec = BSON("$toInt" << BSON_ARRAY("1")); - convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); spec = BSON("$toInt" << BSON_ARRAY(BSON_ARRAY("1"))); - convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(convert->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -3307,7 +3309,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToInts) { BSONObj spec = BSON("$toInt" << "1"); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value(1), BSONType::NumberInt); @@ -3318,7 +3320,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToLongs) { BSONObj spec = BSON("$toLong" << "1"); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value(1), BSONType::NumberLong); @@ -3329,7 +3331,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToDoubles) { BSONObj spec = BSON("$toDouble" << "1"); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value(1), BSONType::NumberDouble); @@ -3340,7 +3342,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToDecimals) { BSONObj spec = BSON("$toDecimal" << "1"); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value(1), BSONType::NumberDecimal); @@ -3350,7 +3352,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToDates) { auto expCtx = getExpCtx(); BSONObj spec = BSON("$toDate" << 0LL); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE(convert->evaluate({}, &expCtx->variables), Value(Date_t::fromMillisSinceEpoch(0)), @@ -3362,7 +3364,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToObjectIds) { const auto hexString = "deadbeefdeadbeefdeadbeef"_sd; BSONObj spec = BSON("$toObjectId" << hexString); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE(convert->evaluate({}, &expCtx->variables), Value(OID::createFromString(hexString)), @@ -3373,7 +3375,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToString) { auto expCtx = getExpCtx(); BSONObj spec = BSON("$toString" << 1); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value("1"_sd), BSONType::String); @@ -3383,7 +3385,7 @@ TEST_F(ExpressionConvertShortcutsTest, ConvertsToBool) { auto expCtx = getExpCtx(); BSONObj spec = BSON("$toBool" << 1); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value(true), BSONType::Bool); @@ -3393,14 +3395,14 @@ TEST_F(ExpressionConvertShortcutsTest, ReturnsNullOnNullishInput) { auto expCtx = getExpCtx(); BSONObj spec = BSON("$toBool" << BSONNULL); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value(BSONNULL), BSONType::jstNULL); spec = BSON("$toInt" << "$missing"); - convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_VALUE_CONTENTS_AND_TYPE( convert->evaluate({}, &expCtx->variables), Value(BSONNULL), BSONType::jstNULL); @@ -3411,7 +3413,7 @@ TEST_F(ExpressionConvertShortcutsTest, ThrowsOnConversionFailure) { BSONObj spec = BSON("$toInt" << "not an int"); - auto convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_THROWS_CODE(convert->evaluate({}, &expCtx->variables), AssertionException, @@ -3419,7 +3421,7 @@ TEST_F(ExpressionConvertShortcutsTest, ThrowsOnConversionFailure) { spec = BSON("$toObjectId" << "not all hex values"); - convert = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + convert = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionConvert*>(convert.get())); ASSERT_THROWS_CODE(convert->evaluate({}, &expCtx->variables), AssertionException, diff --git a/src/mongo/db/pipeline/expression_date_test.cpp b/src/mongo/db/pipeline/expression_date_test.cpp index 78fdfac5b8d..3098eec3f5a 100644 --- a/src/mongo/db/pipeline/expression_date_test.cpp +++ b/src/mongo/db/pipeline/expression_date_test.cpp @@ -50,7 +50,7 @@ TEST_F(ExpressionDateFromPartsTest, SerializesToObjectSyntax) { << "minute" << 37 << "second" << 15 << "millisecond" << 414 << "timezone" << "America/Los_Angeles")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto expectedSerialization = Value(Document{{"$dateFromParts", Document{{"year", Document{{"$const", 2017}}}, @@ -68,13 +68,13 @@ TEST_F(ExpressionDateFromPartsTest, SerializesToObjectSyntax) { TEST_F(ExpressionDateFromPartsTest, OptimizesToConstantIfAllInputsAreConstant) { auto expCtx = getExpCtx(); auto spec = BSON("$dateFromParts" << BSON("year" << 2017)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both year, month and day are provided, and are both // constants. spec = BSON("$dateFromParts" << BSON("year" << 2017 << "month" << 6 << "day" << 27)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both year, hour and minute are provided, and are both @@ -82,20 +82,20 @@ TEST_F(ExpressionDateFromPartsTest, OptimizesToConstantIfAllInputsAreConstant) { spec = BSON("$dateFromParts" << BSON("year" << BSON("$add" << BSON_ARRAY(1900 << 107)) << "hour" << BSON("$add" << BSON_ARRAY(13 << 1)) << "minute" << BSON("$add" << BSON_ARRAY(40 << 3)))); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both year and milliseconds are provided, and year is an // expressions which evaluate to a constant, with milliseconds a constant spec = BSON("$dateFromParts" << BSON("year" << BSON("$add" << BSON_ARRAY(1900 << 107)) << "millisecond" << 514)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both isoWeekYear, and isoWeek are provided, and are both // constants. spec = BSON("$dateFromParts" << BSON("isoWeekYear" << 2017 << "isoWeek" << 26)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both isoWeekYear, isoWeek and isoDayOfWeek are provided, @@ -104,7 +104,7 @@ TEST_F(ExpressionDateFromPartsTest, OptimizesToConstantIfAllInputsAreConstant) { << BSON("$add" << BSON_ARRAY(1017 << 1000)) << "isoWeek" << BSON("$add" << BSON_ARRAY(20 << 6)) << "isoDayOfWeek" << BSON("$add" << BSON_ARRAY(3 << 2)))); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both year and month are provided, but @@ -112,21 +112,21 @@ TEST_F(ExpressionDateFromPartsTest, OptimizesToConstantIfAllInputsAreConstant) { spec = BSON("$dateFromParts" << BSON("year" << "$year" << "month" << 6)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both year and day are provided, but // day is not a constant. spec = BSON("$dateFromParts" << BSON("year" << 2017 << "day" << "$day")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both isoWeekYear and isoDayOfWeek are provided, // but isoDayOfWeek is not a constant. spec = BSON("$dateFromParts" << BSON("isoWeekYear" << 2017 << "isoDayOfWeek" << "$isoDayOfWeekday")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); } @@ -134,27 +134,27 @@ TEST_F(ExpressionDateFromPartsTest, TestThatOutOfRangeValuesRollOver) { auto expCtx = getExpCtx(); auto spec = BSON("$dateFromParts" << BSON("year" << 2017 << "month" << -1)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto dateVal = Date_t::fromMillisSinceEpoch(1477958400000); // 11/1/2016 in ms. ASSERT_VALUE_EQ(Value(dateVal), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromParts" << BSON("year" << 2017 << "day" << -1)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); dateVal = Date_t::fromMillisSinceEpoch(1483056000000); // 12/30/2016 ASSERT_VALUE_EQ(Value(dateVal), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromParts" << BSON("year" << 2017 << "hour" << 25)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); dateVal = Date_t::fromMillisSinceEpoch(1483318800000); // 1/2/2017 01:00:00 ASSERT_VALUE_EQ(Value(dateVal), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromParts" << BSON("year" << 2017 << "minute" << 61)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); dateVal = Date_t::fromMillisSinceEpoch(1483232460000); // 1/1/2017 01:01:00 ASSERT_VALUE_EQ(Value(dateVal), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromParts" << BSON("year" << 2017 << "second" << 61)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); dateVal = Date_t::fromMillisSinceEpoch(1483228861000); // 1/1/2017 00:01:01 ASSERT_VALUE_EQ(Value(dateVal), dateExp->evaluate({}, &expCtx->variables)); } @@ -174,7 +174,7 @@ TEST_F(ExpressionDateToPartsTest, SerializesToObjectSyntax) { BSONObj spec = BSON("$dateToParts" << BSON("date" << Date_t{} << "timezone" << "Europe/London" << "iso8601" << false)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto expectedSerialization = Value(Document{{"$dateToParts", Document{{"date", Document{{"$const", Date_t{}}}}, @@ -187,14 +187,14 @@ TEST_F(ExpressionDateToPartsTest, SerializesToObjectSyntax) { TEST_F(ExpressionDateToPartsTest, OptimizesToConstantIfAllInputsAreConstant) { auto expCtx = getExpCtx(); auto spec = BSON("$dateToParts" << BSON("date" << Date_t{})); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both date and timezone are provided, and are both // constants. spec = BSON("$dateToParts" << BSON("date" << Date_t{} << "timezone" << "UTC")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both date and timezone are provided, and are both @@ -204,20 +204,20 @@ TEST_F(ExpressionDateToPartsTest, OptimizesToConstantIfAllInputsAreConstant) { << BSON("$concat" << BSON_ARRAY("Europe" << "/" << "London")))); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both date and iso8601 are provided, and are both // constants. spec = BSON("$dateToParts" << BSON("date" << Date_t{} << "iso8601" << true)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both date and iso8601 are provided, and are both // expressions which evaluate to constants. spec = BSON("$dateToParts" << BSON("date" << BSON("$add" << BSON_ARRAY(Date_t{} << 1000)) << "iso8601" << BSON("$not" << false))); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both date and timezone are provided, but @@ -226,21 +226,21 @@ TEST_F(ExpressionDateToPartsTest, OptimizesToConstantIfAllInputsAreConstant) { << "$date" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both date and timezone are provided, but // timezone is not a constant. spec = BSON("$dateToParts" << BSON("date" << Date_t{} << "timezone" << "$tz")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both date and iso8601 are provided, but // iso8601 is not a constant. spec = BSON("$dateToParts" << BSON("date" << Date_t{} << "iso8601" << "$iso8601")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); } @@ -286,7 +286,7 @@ TEST_F(DateExpressionTest, ParsingAcceptsAllFormats) { BSON(expName << BSON("date" << Date_t{} << "timezone" << "$tz"))}; for (auto&& syntax : possibleSyntaxes) { - Expression::parseExpression(expCtx, syntax, expCtx->variablesParseState); + Expression::parseExpression(expCtx.get(), syntax, expCtx->variablesParseState); } } } @@ -297,9 +297,10 @@ TEST_F(DateExpressionTest, ParsingRejectsUnrecognizedFieldsInObjectSpecification BSONObj spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "Europe/London" << "extra" << 4)); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), - AssertionException, - 40535); + ASSERT_THROWS_CODE( + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), + AssertionException, + 40535); } } @@ -307,9 +308,10 @@ TEST_F(DateExpressionTest, ParsingRejectsEmptyObjectSpecification) { auto expCtx = getExpCtx(); for (auto&& expName : dateExpressions) { BSONObj spec = BSON(expName << BSONObj()); - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), - AssertionException, - 40539); + ASSERT_THROWS_CODE( + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), + AssertionException, + 40539); } } @@ -318,9 +320,10 @@ TEST_F(DateExpressionTest, RejectsEmptyArray) { for (auto&& expName : dateExpressions) { BSONObj spec = BSON(expName << BSONArray()); // It will parse as an ExpressionArray, and fail at runtime. - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), - AssertionException, - 40536); + ASSERT_THROWS_CODE( + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), + AssertionException, + 40536); } } @@ -330,9 +333,10 @@ TEST_F(DateExpressionTest, RejectsArraysWithMoreThanOneElement) { BSONObj spec = BSON(expName << BSON_ARRAY("$date" << "$tz")); // It will parse as an ExpressionArray, and fail at runtime. - ASSERT_THROWS_CODE(Expression::parseExpression(expCtx, spec, expCtx->variablesParseState), - AssertionException, - 40536); + ASSERT_THROWS_CODE( + Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState), + AssertionException, + 40536); } } @@ -342,7 +346,7 @@ TEST_F(DateExpressionTest, RejectsArraysWithinObjectSpecification) { BSONObj spec = BSON(expName << BSON("date" << BSON_ARRAY(Date_t{}) << "timezone" << "Europe/London")); // It will parse as an ExpressionArray, and fail at runtime. - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto contextDoc = Document{{"_id", 0}}; ASSERT_THROWS_CODE( dateExp->evaluate(contextDoc, &expCtx->variables), AssertionException, 16006); @@ -350,7 +354,7 @@ TEST_F(DateExpressionTest, RejectsArraysWithinObjectSpecification) { // Test that it rejects an array for the timezone option. spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << BSON_ARRAY("Europe/London"))); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); contextDoc = Document{{"_id", 0}}; ASSERT_THROWS_CODE( dateExp->evaluate(contextDoc, &expCtx->variables), AssertionException, 40533); @@ -361,7 +365,7 @@ TEST_F(DateExpressionTest, RejectsTypesThatCannotCoerceToDate) { auto expCtx = getExpCtx(); for (auto&& expName : dateExpressions) { BSONObj spec = BSON(expName << "$stringField"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto contextDoc = Document{{"stringField", "string"_sd}}; ASSERT_THROWS_CODE( dateExp->evaluate(contextDoc, &expCtx->variables), AssertionException, 16006); @@ -372,7 +376,7 @@ TEST_F(DateExpressionTest, AcceptsObjectIds) { auto expCtx = getExpCtx(); for (auto&& expName : dateExpressions) { BSONObj spec = BSON(expName << "$oid"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto contextDoc = Document{{"oid", OID::gen()}}; dateExp->evaluate(contextDoc, &expCtx->variables); // Should not throw. } @@ -382,7 +386,7 @@ TEST_F(DateExpressionTest, AcceptsTimestamps) { auto expCtx = getExpCtx(); for (auto&& expName : dateExpressions) { BSONObj spec = BSON(expName << "$ts"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto contextDoc = Document{{"ts", Timestamp{Date_t{}}}}; dateExp->evaluate(contextDoc, &expCtx->variables); // Should not throw. } @@ -393,7 +397,7 @@ TEST_F(DateExpressionTest, RejectsNonStringTimezone) { for (auto&& expName : dateExpressions) { BSONObj spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "$intField")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto contextDoc = Document{{"intField", 4}}; ASSERT_THROWS_CODE( dateExp->evaluate(contextDoc, &expCtx->variables), AssertionException, 40533); @@ -405,7 +409,7 @@ TEST_F(DateExpressionTest, RejectsUnrecognizedTimeZoneSpecification) { for (auto&& expName : dateExpressions) { BSONObj spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "UNRECOGNIZED!")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto contextDoc = Document{{"_id", 0}}; ASSERT_THROWS_CODE( dateExp->evaluate(contextDoc, &expCtx->variables), AssertionException, 40485); @@ -418,7 +422,7 @@ TEST_F(DateExpressionTest, SerializesToObjectSyntax) { // Test that it serializes to the full format if given an object specification. BSONObj spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "Europe/London")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto expectedSerialization = Value(Document{{expName, Document{{"date", Document{{"$const", Date_t{}}}}, @@ -430,13 +434,13 @@ TEST_F(DateExpressionTest, SerializesToObjectSyntax) { spec = BSON(expName << Date_t{}); expectedSerialization = Value(Document{{expName, Document{{"date", Document{{"$const", Date_t{}}}}}}}); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(dateExp->serialize(true), expectedSerialization); ASSERT_VALUE_EQ(dateExp->serialize(false), expectedSerialization); // Test that it serializes to the full format if given a date within an array. spec = BSON(expName << BSON_ARRAY(Date_t{})); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(dateExp->serialize(true), expectedSerialization); ASSERT_VALUE_EQ(dateExp->serialize(false), expectedSerialization); } @@ -447,14 +451,14 @@ TEST_F(DateExpressionTest, OptimizesToConstantIfAllInputsAreConstant) { for (auto&& expName : dateExpressions) { // Test that it becomes a constant if only date is provided, and it is constant. auto spec = BSON(expName << BSON("date" << Date_t{})); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both date and timezone are provided, and are both // constants. spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both date and timezone are provided, and are both @@ -464,7 +468,7 @@ TEST_F(DateExpressionTest, OptimizesToConstantIfAllInputsAreConstant) { << BSON("$concat" << BSON_ARRAY("Europe" << "/" << "London")))); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both date and timezone are provided, but @@ -473,14 +477,14 @@ TEST_F(DateExpressionTest, OptimizesToConstantIfAllInputsAreConstant) { << "$date" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both date and timezone are provided, but // timezone is not a constant. spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "$tz")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); } } @@ -491,7 +495,7 @@ TEST_F(DateExpressionTest, DoesRespectTimeZone) { for (auto&& expName : dateExpressions) { auto spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "America/New_York")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto contextDoc = Document{{"_id", 0}}; dateExp->evaluate(contextDoc, &expCtx->variables); // Should not throw. } @@ -500,14 +504,14 @@ TEST_F(DateExpressionTest, DoesRespectTimeZone) { auto date = Date_t::fromMillisSinceEpoch(1496777923000LL); // 2017-06-06T19:38:43:234Z. auto specWithoutTimezone = BSON("$hour" << BSON("date" << date)); auto hourWithoutTimezone = - Expression::parseExpression(expCtx, specWithoutTimezone, expCtx->variablesParseState) + Expression::parseExpression(expCtx.get(), specWithoutTimezone, expCtx->variablesParseState) ->evaluate({}, &expCtx->variables); ASSERT_VALUE_EQ(hourWithoutTimezone, Value(19)); auto specWithTimezone = BSON("$hour" << BSON("date" << date << "timezone" << "America/New_York")); auto hourWithTimezone = - Expression::parseExpression(expCtx, specWithTimezone, expCtx->variablesParseState) + Expression::parseExpression(expCtx.get(), specWithTimezone, expCtx->variablesParseState) ->evaluate({}, &expCtx->variables); ASSERT_VALUE_EQ(hourWithTimezone, Value(15)); } @@ -522,37 +526,37 @@ TEST_F(DateExpressionTest, DoesResultInNullIfGivenNullishInput) { // specified. auto spec = BSON(expName << BSON("date" << "$missing")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); spec = BSON(expName << BSON("date" << BSONNULL)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); spec = BSON(expName << BSON("date" << BSONUndefined)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); // Test that the expression results in null if the date is present but the timezone is // nullish. spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << "$missing")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << BSONNULL)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); spec = BSON(expName << BSON("date" << Date_t{} << "timezone" << BSONUndefined)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); // Test that the expression results in null if the date and timezone both nullish. spec = BSON(expName << BSON("date" << "$missing" << "timezone" << BSONUndefined)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); // Test that the expression results in null if the date is nullish and timezone is present. @@ -560,7 +564,7 @@ TEST_F(DateExpressionTest, DoesResultInNullIfGivenNullishInput) { << "$missing" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(contextDoc, &expCtx->variables)); } } @@ -583,7 +587,7 @@ TEST_F(ExpressionDateToStringTest, SerializesToObjectSyntax) { << "%Y-%m-%d" << "onNull" << "nullDefault")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto expectedSerialization = Value(Document{{"$dateToString", Document{{"date", Document{{"$const", Date_t{}}}}, @@ -601,7 +605,7 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { // Test that it becomes a constant if date is constant, and both format and timezone are // missing. auto spec = BSON("$dateToString" << BSON("date" << Date_t{})); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if both format and date are constant, and timezone is @@ -609,7 +613,7 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { spec = BSON("$dateToString" << BSON("format" << "%Y-%m-%d" << "date" << Date_t{})); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if format, date and timezone are provided, and all are @@ -618,7 +622,7 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { << "%Y-%m-%d" << "date" << Date_t{} << "timezone" << "Europe/Amsterdam")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if format, date and timezone are provided, and all @@ -630,7 +634,7 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { << BSON("$concat" << BSON_ARRAY("Europe" << "/" << "London")))); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant if all parameters are constant, including the optional @@ -641,7 +645,7 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { << "Europe/Amsterdam" << "onNull" << "null default")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both format, date and timezone are provided, but @@ -652,7 +656,7 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { << "$date" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if both format, date and timezone are provided, but @@ -661,7 +665,7 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { << "%Y-%m-%d" << "date" << Date_t{} << "timezone" << "$tz")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if 'onNull' does not evaluate to a constant. @@ -669,14 +673,14 @@ TEST_F(ExpressionDateToStringTest, OptimizesToConstantIfAllInputsAreConstant) { << "%Y-%m-%d" << "date" << Date_t{} << "onNull" << "$onNull")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if 'format' does not evaluate to a constant. spec = BSON("$dateToString" << BSON("format" << "$format" << "date" << Date_t{})); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); } @@ -687,13 +691,13 @@ TEST_F(ExpressionDateToStringTest, ReturnsOnNullValueWhenInputIsNullish) { << "%Y-%m-%d" << "date" << BSONNULL << "onNull" << "null default")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("null default"_sd), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateToString" << BSON("format" << "%Y-%m-%d" << "date" << BSONNULL << "onNull" << BSONNULL)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateToString" << BSON("format" @@ -702,7 +706,7 @@ TEST_F(ExpressionDateToStringTest, ReturnsOnNullValueWhenInputIsNullish) { << "$missing" << "onNull" << "null default")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("null default"_sd), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateToString" << BSON("format" @@ -711,7 +715,7 @@ TEST_F(ExpressionDateToStringTest, ReturnsOnNullValueWhenInputIsNullish) { << "$missing" << "onNull" << "$alsoMissing")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(), dateExp->evaluate({}, &expCtx->variables)); } @@ -719,7 +723,7 @@ TEST_F(ExpressionDateToStringTest, ReturnsNullIfInputDateIsNullish) { auto expCtx = getExpCtx(); auto spec = fromjson("{$dateToString: {date: '$date'}}"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate(Document{{"date", BSONNULL}}, &expCtx->variables)); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); @@ -729,7 +733,7 @@ TEST_F(ExpressionDateToStringTest, ReturnsNullIfFormatIsNullish) { auto expCtx = getExpCtx(); auto spec = fromjson("{$dateToString: {date: '$date', format: '$format'}}"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ( Value(BSONNULL), dateExp->evaluate(Document{{"date", Date_t{}}, {"format", BSONNULL}}, &expCtx->variables)); @@ -741,7 +745,7 @@ TEST_F(ExpressionDateToStringTest, UsesDefaultFormatIfNoneSpecified) { auto expCtx = getExpCtx(); auto spec = fromjson("{$dateToString: {date: '$date'}}"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("1970-01-01T00:00:00.000Z"_sd), dateExp->evaluate(Document{{"date", Date_t{}}}, &expCtx->variables)); } @@ -750,7 +754,7 @@ TEST_F(ExpressionDateToStringTest, FailsForInvalidTimezoneRegardlessOfInputDate) auto expCtx = getExpCtx(); auto spec = fromjson("{$dateToString: {date: '$date', timezone: '$tz'}}"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE( dateExp->evaluate(Document{{"date", BSONNULL}, {"tz", "invalid"_sd}}, &expCtx->variables), AssertionException, @@ -766,12 +770,12 @@ TEST_F(ExpressionDateToStringTest, FailsForInvalidFormatStrings) { auto spec = BSON("$dateToString" << BSON("date" << Date_t{} << "format" << "%n")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 18536); spec = BSON("$dateToString" << BSON("date" << Date_t{} << "format" << "%Y%")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 18535); } @@ -779,7 +783,7 @@ TEST_F(ExpressionDateToStringTest, FailsForInvalidFormatRegardlessOfInputDate) { auto expCtx = getExpCtx(); auto spec = fromjson("{$dateToString: {date: '$date', format: '$format', onNull: 0}}"); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE( dateExp->evaluate(Document{{"date", BSONNULL}, {"format", 5}}, &expCtx->variables), AssertionException, @@ -812,7 +816,7 @@ TEST_F(ExpressionDateFromStringTest, SerializesToObjectSyntax) { // Test that it serializes to the full format if given an object specification. BSONObj spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-04T13:06:44Z")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); auto expectedSerialization = Value( Document{{"$dateFromString", Document{{"dateString", Document{{"$const", "2017-07-04T13:06:44Z"_sd}}}}}}); @@ -825,7 +829,7 @@ TEST_F(ExpressionDateFromStringTest, SerializesToObjectSyntax) { << "2017-07-04T13:06:44Z" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); expectedSerialization = Value(Document{{"$dateFromString", Document{{"dateString", Document{{"$const", "2017-07-04T13:06:44Z"_sd}}}, @@ -840,7 +844,7 @@ TEST_F(ExpressionDateFromStringTest, SerializesToObjectSyntax) { << "Europe/London" << "format" << "%Y-%d-%mT%H:%M:%S")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); expectedSerialization = Value(Document{{"$dateFromString", Document{{"dateString", Document{{"$const", "2017-07-04T13:06:44Z"_sd}}}, @@ -860,7 +864,7 @@ TEST_F(ExpressionDateFromStringTest, SerializesToObjectSyntax) { << "nullDefault" << "onError" << "errorDefault")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); expectedSerialization = Value(Document{{"$dateFromString", Document{{"dateString", Document{{"$const", "2017-07-04T13:06:44Z"_sd}}}, @@ -879,7 +883,7 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) // Test that it becomes a constant if all parameters evaluate to a constant value. auto spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-04T13:09:57Z")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); Date_t dateVal = Date_t::fromMillisSinceEpoch(1499173797000); @@ -889,7 +893,7 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "2017-07-04T13:09:57" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it becomes a constant with the dateString, timezone, and format being a constant. @@ -899,7 +903,7 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "Europe/London" << "format" << "%Y-%m-%dT%H:%M:%S")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); dateVal = Date_t::fromMillisSinceEpoch(1499170197000); @@ -909,14 +913,14 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "2017-07-04T13:09:57" << "onNull" << "Null default")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-04T13:09:57" << "onError" << "Error default")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); spec = BSON("$dateFromString" << BSON("dateString" @@ -925,13 +929,13 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "Error default" << "onNull" << "null default")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if dateString is not a constant. spec = BSON("$dateFromString" << BSON("dateString" << "$date")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if timezone is not a constant. @@ -939,7 +943,7 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "2017-07-04T13:09:57Z" << "timezone" << "$tz")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if format is not a constant. @@ -949,7 +953,7 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "Europe/London" << "format" << "$format")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if onNull is not a constant. @@ -957,7 +961,7 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "2017-07-04T13:09:57Z" << "onNull" << "$onNull")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); // Test that it does *not* become a constant if onError is not a constant. @@ -965,7 +969,7 @@ TEST_F(ExpressionDateFromStringTest, OptimizesToConstantIfAllInputsAreConstant) << "2017-07-04T13:09:57Z" << "onError" << "$onError")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_FALSE(dynamic_cast<ExpressionConstant*>(dateExp->optimize().get())); } @@ -974,7 +978,7 @@ TEST_F(ExpressionDateFromStringTest, RejectsUnparsableString) { auto spec = BSON("$dateFromString" << BSON("dateString" << "60.Monday1770/06:59")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -985,14 +989,14 @@ TEST_F(ExpressionDateFromStringTest, RejectsTimeZoneInString) { auto spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-13T10:02:57 Europe/London")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); spec = BSON("$dateFromString" << BSON("dateString" << "July 4, 2017 Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -1006,7 +1010,7 @@ TEST_F(ExpressionDateFromStringTest, RejectsTimeZoneInStringAndArgument) { << "2017-07-14T15:24:38Z" << "timezone" << "Europe/London")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -1016,7 +1020,7 @@ TEST_F(ExpressionDateFromStringTest, RejectsTimeZoneInStringAndArgument) { << "2017-07-14T15:24:38 PDT" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -1026,7 +1030,7 @@ TEST_F(ExpressionDateFromStringTest, RejectsTimeZoneInStringAndArgument) { << "2017-07-14T15:24:38+02:00" << "timezone" << "Europe/London")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -1036,7 +1040,7 @@ TEST_F(ExpressionDateFromStringTest, RejectsTimeZoneInStringAndArgument) { << "2017-07-14 -0400" << "timezone" << "GMT")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -1048,13 +1052,13 @@ TEST_F(ExpressionDateFromStringTest, RejectsNonStringFormat) { auto spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-13T10:02:57" << "format" << 2)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40684); spec = BSON("$dateFromString" << BSON("dateString" << "July 4, 2017" << "format" << true)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40684); } @@ -1065,7 +1069,7 @@ TEST_F(ExpressionDateFromStringTest, RejectsStringsThatDoNotMatchFormat) { << "2017-07" << "format" << "%Y-%m-%d")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -1074,7 +1078,7 @@ TEST_F(ExpressionDateFromStringTest, RejectsStringsThatDoNotMatchFormat) { << "2017-07" << "format" << "%m-%Y")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, ErrorCodes::ConversionFailure); @@ -1087,7 +1091,7 @@ TEST_F(ExpressionDateFromStringTest, EscapeCharacterAllowsPrefixUsage) { << "2017 % 01 % 01" << "format" << "%Y %% %m %% %d")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-01-01T00:00:00.000Z", dateExp->evaluate({}, &expCtx->variables).toString()); } @@ -1098,20 +1102,20 @@ TEST_F(ExpressionDateFromStringTest, EvaluatesToNullIfFormatIsNullish) { auto spec = BSON("$dateFromString" << BSON("dateString" << "1/1/2017" << "format" << BSONNULL)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromString" << BSON("dateString" << "1/1/2017" << "format" << "$missing")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromString" << BSON("dateString" << "1/1/2017" << "format" << BSONUndefined)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); } @@ -1122,35 +1126,35 @@ TEST_F(ExpressionDateFromStringTest, ReadWithUTCOffset) { << "2017-07-28T10:47:52.912" << "timezone" << "-01:00")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-07-28T11:47:52.912Z", dateExp->evaluate({}, &expCtx->variables).toString()); spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-28T10:47:52.912" << "timezone" << "+01:00")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-07-28T09:47:52.912Z", dateExp->evaluate({}, &expCtx->variables).toString()); spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-28T10:47:52.912" << "timezone" << "+0445")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-07-28T06:02:52.912Z", dateExp->evaluate({}, &expCtx->variables).toString()); spec = BSON("$dateFromString" << BSON("dateString" << "2017-07-28T10:47:52.912" << "timezone" << "+10:45")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-07-28T00:02:52.912Z", dateExp->evaluate({}, &expCtx->variables).toString()); spec = BSON("$dateFromString" << BSON("dateString" << "1945-07-28T10:47:52.912" << "timezone" << "-08:00")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("1945-07-28T18:47:52.912Z", dateExp->evaluate({}, &expCtx->variables).toString()); } @@ -1163,7 +1167,7 @@ TEST_F(ExpressionDateFromStringTest, ConvertStringWithUTCOffsetAndFormat) { << "-01:00" << "format" << "%H:%M:%S.%L on %m/%d/%Y")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-07-28T11:47:52.912Z", dateExp->evaluate({}, &expCtx->variables).toString()); spec = BSON("$dateFromString" << BSON("dateString" @@ -1172,7 +1176,7 @@ TEST_F(ExpressionDateFromStringTest, ConvertStringWithUTCOffsetAndFormat) { << "+01:00" << "format" << "%H:%M:%S.%L on %m/%d/%Y")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-07-28T09:47:52.912Z", dateExp->evaluate({}, &expCtx->variables).toString()); } @@ -1183,7 +1187,7 @@ TEST_F(ExpressionDateFromStringTest, ConvertStringWithISODateFormat) { << "Day 7 Week 53 Year 2017" << "format" << "Day %u Week %V Year %G")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2018-01-07T00:00:00.000Z", dateExp->evaluate({}, &expCtx->variables).toString()); // Week and day of week default to '1' if not specified. @@ -1191,14 +1195,14 @@ TEST_F(ExpressionDateFromStringTest, ConvertStringWithISODateFormat) { << "Week 53 Year 2017" << "format" << "Week %V Year %G")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2018-01-01T00:00:00.000Z", dateExp->evaluate({}, &expCtx->variables).toString()); spec = BSON("$dateFromString" << BSON("dateString" << "Day 7 Year 2017" << "format" << "Day %u Year %G")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ("2017-01-08T00:00:00.000Z", dateExp->evaluate({}, &expCtx->variables).toString()); } @@ -1207,25 +1211,25 @@ TEST_F(ExpressionDateFromStringTest, ReturnsOnNullForNullishInput) { auto spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << "Null default")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("Null default"_sd), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromString" << BSON("dateString" << "$missing" << "onNull" << "Null default")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("Null default"_sd), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromString" << BSON("dateString" << "$missing" << "onNull" << "$alsoMissing")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << BSONNULL)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); } @@ -1235,14 +1239,14 @@ TEST_F(ExpressionDateFromStringTest, InvalidFormatTakesPrecedenceOverOnNull) { auto spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << "Null default" << "format" << 5)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40684); spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << "Null default" << "format" << "%")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 18535); } @@ -1254,14 +1258,14 @@ TEST_F(ExpressionDateFromStringTest, InvalidFormatTakesPrecedenceOverOnError) { << "onError" << "Not used default" << "format" << 5)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40684); spec = BSON("$dateFromString" << BSON("dateString" << 5 << "onError" << "Not used default" << "format" << "%")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 18535); } @@ -1271,14 +1275,14 @@ TEST_F(ExpressionDateFromStringTest, InvalidTimezoneTakesPrecedenceOverOnNull) { auto spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << "Null default" << "timezone" << 5)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40517); spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << "Null default" << "timezone" << "invalid timezone string")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40485); } @@ -1290,14 +1294,14 @@ TEST_F(ExpressionDateFromStringTest, InvalidTimezoneTakesPrecedenceOverOnError) << "onError" << "On error default" << "timezone" << 5)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40517); spec = BSON("$dateFromString" << BSON("dateString" << 5 << "onError" << "On error default" << "timezone" << "invalid timezone string")); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_THROWS_CODE(dateExp->evaluate({}, &expCtx->variables), AssertionException, 40485); } @@ -1307,13 +1311,13 @@ TEST_F(ExpressionDateFromStringTest, OnNullTakesPrecedenceOverOtherNullishParame auto spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << "Null default" << "timezone" << BSONNULL)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("Null default"_sd), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromString" << BSON("dateString" << BSONNULL << "onNull" << "Null default" << "format" << BSONNULL)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("Null default"_sd), dateExp->evaluate({}, &expCtx->variables)); } @@ -1325,7 +1329,7 @@ TEST_F(ExpressionDateFromStringTest, OnNullOnlyUsedIfInputStringIsNullish) { << "onNull" << "Null default" << "timezone" << BSONNULL)); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); spec = BSON("$dateFromString" << BSON("dateString" @@ -1333,7 +1337,7 @@ TEST_F(ExpressionDateFromStringTest, OnNullOnlyUsedIfInputStringIsNullish) { << "onNull" << "Null default" << "format" << BSONNULL)); - dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value(BSONNULL), dateExp->evaluate({}, &expCtx->variables)); } @@ -1345,7 +1349,7 @@ TEST_F(ExpressionDateFromStringTest, ReturnsOnErrorForParseFailures) { for (auto date : invalidDates) { auto spec = BSON("$dateFromString" << BSON("dateString" << date << "onError" << "Error default")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("Error default"_sd), dateExp->evaluate({}, &expCtx->variables)); } } @@ -1359,7 +1363,7 @@ TEST_F(ExpressionDateFromStringTest, ReturnsOnErrorForFormatMismatch) { auto spec = BSON("$dateFromString" << BSON("dateString" << date << "format" << format << "onError" << "Error default")); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_VALUE_EQ(Value("Error default"_sd), dateExp->evaluate({}, &expCtx->variables)); } } @@ -1371,7 +1375,7 @@ TEST_F(ExpressionDateFromStringTest, OnNullEvaluatedLazily) { BSON("$dateFromString" << BSON("dateString" << "$date" << "onNull" << BSON("$divide" << BSON_ARRAY(1 << 0)))); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ( "2018-02-14T00:00:00.000Z", dateExp->evaluate(Document{{"date", "2018-02-14"_sd}}, &expCtx->variables).toString()); @@ -1385,7 +1389,7 @@ TEST_F(ExpressionDateFromStringTest, OnErrorEvaluatedLazily) { BSON("$dateFromString" << BSON("dateString" << "$date" << "onError" << BSON("$divide" << BSON_ARRAY(1 << 0)))); - auto dateExp = Expression::parseExpression(expCtx, spec, expCtx->variablesParseState); + auto dateExp = Expression::parseExpression(expCtx.get(), spec, expCtx->variablesParseState); ASSERT_EQ( "2018-02-14T00:00:00.000Z", dateExp->evaluate(Document{{"date", "2018-02-14"_sd}}, &expCtx->variables).toString()); diff --git a/src/mongo/db/pipeline/expression_field_path_test.cpp b/src/mongo/db/pipeline/expression_field_path_test.cpp index ad119de701a..6a104e8cbab 100644 --- a/src/mongo/db/pipeline/expression_field_path_test.cpp +++ b/src/mongo/db/pipeline/expression_field_path_test.cpp @@ -73,54 +73,54 @@ namespace FieldPath { class Invalid { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - ASSERT_THROWS(ExpressionFieldPath::create(expCtx, ""), AssertionException); + auto expCtx = ExpressionContextForTest{}; + ASSERT_THROWS(ExpressionFieldPath::create(&expCtx, ""), AssertionException); } }; TEST(FieldPath, NoOptimizationForRootFieldPathWithDottedPath) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; intrusive_ptr<ExpressionFieldPath> expression = - ExpressionFieldPath::parse(expCtx, "$$ROOT.x.y", expCtx->variablesParseState); + ExpressionFieldPath::parse(&expCtx, "$$ROOT.x.y", expCtx.variablesParseState); // An attempt to optimize returns the Expression itself. ASSERT_EQUALS(expression, expression->optimize()); } TEST(FieldPath, NoOptimizationForCurrentFieldPathWithDottedPath) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; intrusive_ptr<ExpressionFieldPath> expression = - ExpressionFieldPath::parse(expCtx, "$$CURRENT.x.y", expCtx->variablesParseState); + ExpressionFieldPath::parse(&expCtx, "$$CURRENT.x.y", expCtx.variablesParseState); // An attempt to optimize returns the Expression itself. ASSERT_EQUALS(expression, expression->optimize()); } TEST(FieldPath, RemoveOptimizesToMissingValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; intrusive_ptr<ExpressionFieldPath> expression = - ExpressionFieldPath::parse(expCtx, "$$REMOVE", expCtx->variablesParseState); + ExpressionFieldPath::parse(&expCtx, "$$REMOVE", expCtx.variablesParseState); auto optimizedExpr = expression->optimize(); ASSERT_VALUE_EQ( Value(), - optimizedExpr->evaluate(Document(BSON("x" << BSON("y" << 123))), &expCtx->variables)); + optimizedExpr->evaluate(Document(BSON("x" << BSON("y" << 123))), &expCtx.variables)); } TEST(FieldPath, NoOptimizationOnNormalPath) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a"); // An attempt to optimize returns the Expression itself. ASSERT_EQUALS(expression, expression->optimize()); } TEST(FieldPath, OptimizeOnVariableWithConstantScalarValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varId = expCtx->variablesParseState.defineVariable("userVar"); - expCtx->variables.setConstantValue(varId, Value(123)); + auto expCtx = ExpressionContextForTest{}; + auto varId = expCtx.variablesParseState.defineVariable("userVar"); + expCtx.variables.setConstantValue(varId, Value(123)); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar", expCtx->variablesParseState); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar", expCtx.variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); auto optimizedExpr = expr->optimize(); @@ -128,11 +128,11 @@ TEST(FieldPath, OptimizeOnVariableWithConstantScalarValue) { } TEST(FieldPath, OptimizeOnVariableWithConstantArrayValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varId = expCtx->variablesParseState.defineVariable("userVar"); - expCtx->variables.setConstantValue(varId, Value(BSON_ARRAY(1 << 2 << 3))); + auto expCtx = ExpressionContextForTest{}; + auto varId = expCtx.variablesParseState.defineVariable("userVar"); + expCtx.variables.setConstantValue(varId, Value(BSON_ARRAY(1 << 2 << 3))); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar", expCtx->variablesParseState); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar", expCtx.variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); auto optimizedExpr = expr->optimize(); @@ -142,11 +142,11 @@ TEST(FieldPath, OptimizeOnVariableWithConstantArrayValue) { } TEST(FieldPath, OptimizeToEmptyArrayOnNumericalPathComponentAndConstantArrayValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varId = expCtx->variablesParseState.defineVariable("userVar"); - expCtx->variables.setConstantValue(varId, Value(BSON_ARRAY(1 << 2 << 3))); + auto expCtx = ExpressionContextForTest{}; + auto varId = expCtx.variablesParseState.defineVariable("userVar"); + expCtx.variables.setConstantValue(varId, Value(BSON_ARRAY(1 << 2 << 3))); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar.1", expCtx->variablesParseState); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar.1", expCtx.variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); auto optimizedExpr = expr->optimize(); @@ -156,11 +156,11 @@ TEST(FieldPath, OptimizeToEmptyArrayOnNumericalPathComponentAndConstantArrayValu } TEST(FieldPath, OptimizeOnVariableWithConstantValueAndDottedPath) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varId = expCtx->variablesParseState.defineVariable("userVar"); - expCtx->variables.setConstantValue(varId, Value(Document{{"x", Document{{"y", 123}}}})); + auto expCtx = ExpressionContextForTest{}; + auto varId = expCtx.variablesParseState.defineVariable("userVar"); + expCtx.variables.setConstantValue(varId, Value(Document{{"x", Document{{"y", 123}}}})); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar.x.y", expCtx->variablesParseState); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar.x.y", expCtx.variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); auto optimizedExpr = expr->optimize(); @@ -170,10 +170,10 @@ TEST(FieldPath, OptimizeOnVariableWithConstantValueAndDottedPath) { } TEST(FieldPath, NoOptimizationOnVariableWithNoValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - expCtx->variablesParseState.defineVariable("userVar"); + auto expCtx = ExpressionContextForTest{}; + expCtx.variablesParseState.defineVariable("userVar"); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar", expCtx->variablesParseState); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar", expCtx.variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); auto optimizedExpr = expr->optimize(); @@ -181,11 +181,11 @@ TEST(FieldPath, NoOptimizationOnVariableWithNoValue) { } TEST(FieldPath, NoOptimizationOnVariableWithMissingValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varId = expCtx->variablesParseState.defineVariable("userVar"); - expCtx->variables.setValue(varId, Value()); + auto expCtx = ExpressionContextForTest{}; + auto varId = expCtx.variablesParseState.defineVariable("userVar"); + expCtx.variables.setValue(varId, Value()); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar", expCtx->variablesParseState); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar", expCtx.variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); auto optimizedExpr = expr->optimize(); @@ -193,11 +193,11 @@ TEST(FieldPath, NoOptimizationOnVariableWithMissingValue) { } TEST(FieldPath, ScalarVariableWithDottedFieldPathOptimizesToConstantMissingValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varId = expCtx->variablesParseState.defineVariable("userVar"); - expCtx->variables.setConstantValue(varId, Value(123)); + auto expCtx = ExpressionContextForTest{}; + auto varId = expCtx.variablesParseState.defineVariable("userVar"); + expCtx.variables.setConstantValue(varId, Value(123)); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar.x.y", expCtx->variablesParseState); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar.x.y", expCtx.variablesParseState); ASSERT_TRUE(dynamic_cast<ExpressionFieldPath*>(expr.get())); auto optimizedExpr = expr->optimize(); @@ -210,8 +210,8 @@ TEST(FieldPath, ScalarVariableWithDottedFieldPathOptimizesToConstantMissingValue class Dependencies { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); DepsTracker dependencies; expression->addDependencies(&dependencies); ASSERT_EQUALS(1U, dependencies.fields.size()); @@ -225,9 +225,9 @@ public: class Missing { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a"); - assertBinaryEqual(fromjson("{}"), toBson(expression->evaluate({}, &expCtx->variables))); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a"); + assertBinaryEqual(fromjson("{}"), toBson(expression->evaluate({}, &expCtx.variables))); } }; @@ -235,11 +235,11 @@ public: class Present { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a"); assertBinaryEqual( fromjson("{'':123}"), - toBson(expression->evaluate(fromBson(BSON("a" << 123)), &expCtx->variables))); + toBson(expression->evaluate(fromBson(BSON("a" << 123)), &expCtx.variables))); } }; @@ -247,11 +247,11 @@ public: class NestedBelowNull { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{}"), - toBson(expression->evaluate(fromBson(fromjson("{a:null}")), &expCtx->variables))); + toBson(expression->evaluate(fromBson(fromjson("{a:null}")), &expCtx.variables))); } }; @@ -259,11 +259,11 @@ public: class NestedBelowUndefined { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{}"), - toBson(expression->evaluate(fromBson(fromjson("{a:undefined}")), &expCtx->variables))); + toBson(expression->evaluate(fromBson(fromjson("{a:undefined}")), &expCtx.variables))); } }; @@ -271,11 +271,11 @@ public: class NestedBelowMissing { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{}"), - toBson(expression->evaluate(fromBson(fromjson("{z:1}")), &expCtx->variables))); + toBson(expression->evaluate(fromBson(fromjson("{z:1}")), &expCtx.variables))); } }; @@ -283,11 +283,11 @@ public: class NestedBelowInt { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{}"), - toBson(expression->evaluate(fromBson(BSON("a" << 2)), &expCtx->variables))); + toBson(expression->evaluate(fromBson(BSON("a" << 2)), &expCtx.variables))); } }; @@ -295,11 +295,11 @@ public: class NestedValue { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual(BSON("" << 55), toBson(expression->evaluate(fromBson(BSON("a" << BSON("b" << 55))), - &expCtx->variables))); + &expCtx.variables))); } }; @@ -307,11 +307,11 @@ public: class NestedBelowEmptyObject { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{}"), - toBson(expression->evaluate(fromBson(BSON("a" << BSONObj())), &expCtx->variables))); + toBson(expression->evaluate(fromBson(BSON("a" << BSONObj())), &expCtx.variables))); } }; @@ -319,11 +319,11 @@ public: class NestedBelowEmptyArray { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( BSON("" << BSONArray()), - toBson(expression->evaluate(fromBson(BSON("a" << BSONArray())), &expCtx->variables))); + toBson(expression->evaluate(fromBson(BSON("a" << BSONArray())), &expCtx.variables))); } }; @@ -331,11 +331,11 @@ public: class NestedBelowArrayWithNull { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{'':[]}"), - toBson(expression->evaluate(fromBson(fromjson("{a:[null]}")), &expCtx->variables))); + toBson(expression->evaluate(fromBson(fromjson("{a:[null]}")), &expCtx.variables))); } }; @@ -343,11 +343,11 @@ public: class NestedBelowArrayWithUndefined { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); - assertBinaryEqual(fromjson("{'':[]}"), - toBson(expression->evaluate(fromBson(fromjson("{a:[undefined]}")), - &expCtx->variables))); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); + assertBinaryEqual( + fromjson("{'':[]}"), + toBson(expression->evaluate(fromBson(fromjson("{a:[undefined]}")), &expCtx.variables))); } }; @@ -355,11 +355,11 @@ public: class NestedBelowArrayWithInt { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{'':[]}"), - toBson(expression->evaluate(fromBson(fromjson("{a:[1]}")), &expCtx->variables))); + toBson(expression->evaluate(fromBson(fromjson("{a:[1]}")), &expCtx.variables))); } }; @@ -367,11 +367,11 @@ public: class NestedWithinArray { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual( fromjson("{'':[9]}"), - toBson(expression->evaluate(fromBson(fromjson("{a:[{b:9}]}")), &expCtx->variables))); + toBson(expression->evaluate(fromBson(fromjson("{a:[{b:9}]}")), &expCtx.variables))); } }; @@ -379,12 +379,12 @@ public: class MultipleArrayValues { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b"); assertBinaryEqual(fromjson("{'':[9,20]}"), toBson(expression->evaluate( fromBson(fromjson("{a:[{b:9},null,undefined,{g:4},{b:20},{}]}")), - &expCtx->variables))); + &expCtx.variables))); } }; @@ -392,15 +392,15 @@ public: class ExpandNestedArrays { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b.c"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b.c"); assertBinaryEqual(fromjson("{'':[[1,2],3,[4],[[5]],[6,7]]}"), toBson(expression->evaluate(fromBson(fromjson("{a:[{b:[{c:1},{c:2}]}," "{b:{c:3}}," "{b:[{c:4}]}," "{b:[{c:[5]}]}," "{b:{c:[6,7]}}]}")), - &expCtx->variables))); + &expCtx.variables))); } }; @@ -408,8 +408,8 @@ public: class AddToBsonObj { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b.c"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b.c"); assertBinaryEqual(BSON("foo" << "$a.b.c"), BSON("foo" << expression->serialize(false))); @@ -420,8 +420,8 @@ public: class AddToBsonArray { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionFieldPath::create(expCtx, "a.b.c"); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionFieldPath::create(&expCtx, "a.b.c"); BSONArrayBuilder bab; bab << expression->serialize(false); assertBinaryEqual(BSON_ARRAY("$a.b.c"), bab.arr()); diff --git a/src/mongo/db/pipeline/expression_find_internal.h b/src/mongo/db/pipeline/expression_find_internal.h index fe9f4162c89..1b4ec2444e4 100644 --- a/src/mongo/db/pipeline/expression_find_internal.h +++ b/src/mongo/db/pipeline/expression_find_internal.h @@ -44,7 +44,7 @@ namespace mongo { */ class ExpressionInternalFindPositional final : public Expression { public: - ExpressionInternalFindPositional(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionInternalFindPositional(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> preImageExpr, boost::intrusive_ptr<Expression> postImageExpr, FieldPath path, @@ -122,7 +122,7 @@ private: */ class ExpressionInternalFindSlice final : public Expression { public: - ExpressionInternalFindSlice(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionInternalFindSlice(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> postImageExpr, FieldPath path, boost::optional<int> skip, @@ -183,7 +183,7 @@ private: */ class ExpressionInternalFindElemMatch final : public Expression { public: - ExpressionInternalFindElemMatch(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionInternalFindElemMatch(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> child, FieldPath path, CopyableMatchExpression matchExpr) diff --git a/src/mongo/db/pipeline/expression_find_internal_test.cpp b/src/mongo/db/pipeline/expression_find_internal_test.cpp index 62b79968731..2b743d2b661 100644 --- a/src/mongo/db/pipeline/expression_find_internal_test.cpp +++ b/src/mongo/db/pipeline/expression_find_internal_test.cpp @@ -39,8 +39,7 @@ namespace mongo::expression_internal_tests { constexpr auto kProjectionPostImageVarName = projection_executor::ProjectionExecutor::kProjectionPostImageVarName; -auto defineAndSetProjectionPostImageVariable(boost::intrusive_ptr<ExpressionContext> expCtx, - Value postImage) { +auto defineAndSetProjectionPostImageVariable(ExpressionContext* const expCtx, Value postImage) { auto& vps = expCtx->variablesParseState; auto varId = vps.defineVariable(kProjectionPostImageVarName); expCtx->variables.setValue(varId, postImage); @@ -51,14 +50,15 @@ class ExpressionInternalFindPositionalTest : public AggregationContextFixture { protected: auto createExpression(BSONObj matchSpec, const std::string& path) { auto matchExpr = CopyableMatchExpression{matchSpec, - getExpCtx(), + getExpCtxRaw(), std::make_unique<ExtensionsCallbackNoop>(), MatchExpressionParser::kBanAllSpecialFeatures}; auto expr = make_intrusive<ExpressionInternalFindPositional>( - getExpCtx(), - ExpressionFieldPath::parse(getExpCtx(), "$$ROOT", getExpCtx()->variablesParseState), - ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), "$$ROOT", getExpCtx()->variablesParseState), + ExpressionFieldPath::parse(getExpCtxRaw(), + "$$" + kProjectionPostImageVarName, + getExpCtx()->variablesParseState), path, std::move(matchExpr)); return expr; @@ -69,9 +69,10 @@ class ExpressionInternalFindSliceTest : public AggregationContextFixture { protected: auto createExpression(const std::string& path, boost::optional<int> skip, int limit) { auto expr = make_intrusive<ExpressionInternalFindSlice>( - getExpCtx(), - ExpressionFieldPath::parse( - getExpCtx(), "$$" + kProjectionPostImageVarName, getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), + "$$" + kProjectionPostImageVarName, + getExpCtx()->variablesParseState), path, skip, limit); @@ -83,20 +84,20 @@ class ExpressionInternalFindElemMatchTest : public AggregationContextFixture { protected: auto createExpression(BSONObj matchSpec, const std::string& path) { auto matchExpr = CopyableMatchExpression{matchSpec, - getExpCtx(), + getExpCtxRaw(), std::make_unique<ExtensionsCallbackNoop>(), MatchExpressionParser::kBanAllSpecialFeatures}; return make_intrusive<ExpressionInternalFindElemMatch>( - getExpCtx(), - ExpressionFieldPath::parse(getExpCtx(), "$$ROOT", getExpCtx()->variablesParseState), + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), "$$ROOT", getExpCtx()->variablesParseState), path, std::move(matchExpr)); } }; TEST_F(ExpressionInternalFindPositionalTest, AppliesProjectionToPostImage) { - defineAndSetProjectionPostImageVariable(getExpCtx(), + defineAndSetProjectionPostImageVariable(getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression(fromjson("{bar: 1, foo: {$gte: 5}}"), "foo"); @@ -109,7 +110,7 @@ TEST_F(ExpressionInternalFindPositionalTest, AppliesProjectionToPostImage) { TEST_F(ExpressionInternalFindPositionalTest, RecordsProjectionDependencies) { auto varId = defineAndSetProjectionPostImageVariable( - getExpCtx(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); + getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression(fromjson("{bar: 1, foo: {$gte: 5}}"), "foo"); DepsTracker deps; @@ -124,7 +125,7 @@ TEST_F(ExpressionInternalFindPositionalTest, RecordsProjectionDependencies) { } TEST_F(ExpressionInternalFindPositionalTest, AddsArrayUndottedPathToComputedPaths) { - defineAndSetProjectionPostImageVariable(getExpCtx(), + defineAndSetProjectionPostImageVariable(getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression(fromjson("{bar: 1, foo: {$gte: 5}}"), "foo"); @@ -139,7 +140,7 @@ TEST_F(ExpressionInternalFindPositionalTest, AddsArrayUndottedPathToComputedPath TEST_F(ExpressionInternalFindPositionalTest, AddsOnlyTopLevelFieldOfArrayDottedPathToComputedPaths) { - defineAndSetProjectionPostImageVariable(getExpCtx(), + defineAndSetProjectionPostImageVariable(getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression(fromjson("{bar: 1, 'foo.bar': {$gte: 5}}"), "foo.bar"); @@ -153,7 +154,7 @@ TEST_F(ExpressionInternalFindPositionalTest, } TEST_F(ExpressionInternalFindSliceTest, AppliesProjectionToPostImage) { - defineAndSetProjectionPostImageVariable(getExpCtx(), + defineAndSetProjectionPostImageVariable(getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression("foo", 1, 2); @@ -166,7 +167,7 @@ TEST_F(ExpressionInternalFindSliceTest, AppliesProjectionToPostImage) { TEST_F(ExpressionInternalFindSliceTest, RecordsProjectionDependencies) { auto varId = defineAndSetProjectionPostImageVariable( - getExpCtx(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); + getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression("foo", 1, 2); DepsTracker deps; @@ -179,7 +180,7 @@ TEST_F(ExpressionInternalFindSliceTest, RecordsProjectionDependencies) { } TEST_F(ExpressionInternalFindSliceTest, AddsArrayUndottedPathToComputedPaths) { - defineAndSetProjectionPostImageVariable(getExpCtx(), + defineAndSetProjectionPostImageVariable(getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression("foo", 1, 2); @@ -193,7 +194,7 @@ TEST_F(ExpressionInternalFindSliceTest, AddsArrayUndottedPathToComputedPaths) { } TEST_F(ExpressionInternalFindSliceTest, AddsTopLevelFieldOfArrayDottedPathToComputedPaths) { - defineAndSetProjectionPostImageVariable(getExpCtx(), + defineAndSetProjectionPostImageVariable(getExpCtxRaw(), Value{fromjson("{bar: 1, foo: [1,2,6,10]}")}); auto expr = createExpression("foo.bar", 1, 2); diff --git a/src/mongo/db/pipeline/expression_function.cpp b/src/mongo/db/pipeline/expression_function.cpp index 30ac119fab0..8f5074bb1c1 100644 --- a/src/mongo/db/pipeline/expression_function.cpp +++ b/src/mongo/db/pipeline/expression_function.cpp @@ -33,7 +33,7 @@ namespace mongo { REGISTER_EXPRESSION(function, ExpressionFunction::parse); -ExpressionFunction::ExpressionFunction(const boost::intrusive_ptr<ExpressionContext>& expCtx, +ExpressionFunction::ExpressionFunction(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> passedArgs, bool assignFirstArgToThis, std::string funcSource, @@ -60,10 +60,9 @@ void ExpressionFunction::_doAddDependencies(mongo::DepsTracker* deps) const { _children[0]->addDependencies(deps); } -boost::intrusive_ptr<Expression> ExpressionFunction::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +boost::intrusive_ptr<Expression> ExpressionFunction::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(4660800, str::stream() << kExpressionName << " cannot be used inside a validator.", diff --git a/src/mongo/db/pipeline/expression_function.h b/src/mongo/db/pipeline/expression_function.h index d42b0723802..5bad4eb38cc 100644 --- a/src/mongo/db/pipeline/expression_function.h +++ b/src/mongo/db/pipeline/expression_function.h @@ -40,13 +40,12 @@ namespace mongo { */ class ExpressionFunction final : public Expression { public: - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); static boost::intrusive_ptr<ExpressionFunction> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> passedArgs, std::string funcSourceString, std::string lang) { @@ -60,7 +59,7 @@ public: // This method is intended for use when you want to bind obj to an argument for desugaring // $where. static boost::intrusive_ptr<ExpressionFunction> createForWhere( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> passedArgs, std::string funcSourceString, std::string lang) { @@ -80,7 +79,7 @@ public: static constexpr auto kJavaScript = "js"; private: - ExpressionFunction(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionFunction(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> passedArgs, bool assignFirstArgToThis, std::string funcSourceString, diff --git a/src/mongo/db/pipeline/expression_internal_remove_field_tombstones.h b/src/mongo/db/pipeline/expression_internal_remove_field_tombstones.h index 137f52c2a3b..936c316e0cd 100644 --- a/src/mongo/db/pipeline/expression_internal_remove_field_tombstones.h +++ b/src/mongo/db/pipeline/expression_internal_remove_field_tombstones.h @@ -44,9 +44,8 @@ namespace mongo { */ class ExpressionInternalRemoveFieldTombstones final : public Expression { public: - explicit ExpressionInternalRemoveFieldTombstones( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - boost::intrusive_ptr<Expression> child) + explicit ExpressionInternalRemoveFieldTombstones(ExpressionContext* const expCtx, + boost::intrusive_ptr<Expression> child) : Expression{expCtx, {std::move(child)}} {} Value evaluate(const Document& root, Variables* variables) const final { @@ -93,4 +92,4 @@ private: return Value(output.freeze()); } }; -} // namespace mongo
\ No newline at end of file +} // namespace mongo diff --git a/src/mongo/db/pipeline/expression_internal_remove_field_tombstones_test.cpp b/src/mongo/db/pipeline/expression_internal_remove_field_tombstones_test.cpp index 589baa5d577..ff72e8aa4ee 100644 --- a/src/mongo/db/pipeline/expression_internal_remove_field_tombstones_test.cpp +++ b/src/mongo/db/pipeline/expression_internal_remove_field_tombstones_test.cpp @@ -42,8 +42,8 @@ class ExpressionInternalRemoveFieldTombstonesTest : public AggregationContextFix public: auto createExpression() { auto expr = make_intrusive<ExpressionInternalRemoveFieldTombstones>( - getExpCtx(), - ExpressionFieldPath::parse(getExpCtx(), "$$ROOT", getExpCtx()->variablesParseState)); + getExpCtxRaw(), + ExpressionFieldPath::parse(getExpCtxRaw(), "$$ROOT", getExpCtx()->variablesParseState)); return expr; } }; @@ -70,4 +70,4 @@ TEST_F(ExpressionInternalRemoveFieldTombstonesTest, RemovesNestedTombstoneValues expected); } -} // namespace mongo::expression_internal_tests
\ No newline at end of file +} // namespace mongo::expression_internal_tests diff --git a/src/mongo/db/pipeline/expression_javascript_test.cpp b/src/mongo/db/pipeline/expression_javascript_test.cpp index 3df1f10d436..299ee506664 100644 --- a/src/mongo/db/pipeline/expression_javascript_test.cpp +++ b/src/mongo/db/pipeline/expression_javascript_test.cpp @@ -50,9 +50,12 @@ protected: _expCtx->mongoProcessInterface = std::make_shared<StandaloneProcessInterface>(nullptr); } - boost::intrusive_ptr<ExpressionContextForTest>& getExpCtx() { + auto& getExpCtx() { return _expCtx; } + auto getExpCtxRaw() { + return _expCtx.get(); + } const VariablesParseState& getVPS() { return _vps; @@ -88,7 +91,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionProducesExpectedResult) { << "args" << BSON_ARRAY("$a" << 4) << "lang" << ExpressionFunction::kJavaScript)); - auto expr = ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); Value result = expr->evaluate(Document{BSON("a" << 2)}, getVariables()); ASSERT_VALUE_EQ(result, Value(6)); @@ -98,7 +101,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionProducesExpectedResult) { << "function(first, second, third) {return first + second + third;};" << "args" << BSON_ARRAY(1 << 2 << 4) << "lang" << ExpressionFunction::kJavaScript)); - expr = ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + expr = ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); result = expr->evaluate(Document{BSONObj{}}, getVariables()); ASSERT_VALUE_EQ(result, Value(7)); @@ -106,7 +109,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionProducesExpectedResult) { << "function(first) {return first;};" << "args" << BSON_ARRAY(1) << "lang" << ExpressionFunction::kJavaScript)); - expr = ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + expr = ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); result = expr->evaluate(Document{BSONObj{}}, getVariables()); ASSERT_VALUE_EQ(result, Value(1)); } @@ -116,7 +119,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsIfArgsDoesNotEvaluateToArray) { << "function(first, second) {return first + second;};" << "args" << BSON("a" << 1) << "lang" << ExpressionFunction::kJavaScript)); - auto expr = ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); ASSERT_THROWS_CODE(expr->evaluate({}, getVariables()), AssertionException, 31266); } @@ -126,7 +129,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsWithInvalidFunction) { << "INVALID" << "args" << BSON_ARRAY(1 << 2) << "lang" << ExpressionFunction::kJavaScript)); - auto expr = ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); ASSERT_THROWS_CODE( expr->evaluate({}, getVariables()), AssertionException, ErrorCodes::JSInterpreterFailure); @@ -134,7 +137,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsWithInvalidFunction) { TEST_F(MapReduceFixture, ExpressionFunctionFailsIfArgumentIsNotObject) { auto bsonExpr = BSON("expr" << 1); - ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31260); } @@ -142,7 +145,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsIfArgumentIsNotObject) { TEST_F(MapReduceFixture, ExpressionFunctionFailsIfBodyNotSpecified) { auto bsonExpr = BSON( "expr" << BSON("args" << BSON_ARRAY(1 << 2) << "lang" << ExpressionFunction::kJavaScript)); - ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31261); } @@ -150,7 +153,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsIfBodyNotSpecified) { TEST_F(MapReduceFixture, ExpressionFunctionFailsIfBodyIsNotConstantExpression) { auto bsonExpr = BSON("expr" << BSON("body" << BSONObj() << "args" << BSON_ARRAY(1 << 2) << "lang" << ExpressionFunction::kJavaScript)); - ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31432); } @@ -158,7 +161,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsIfBodyIsNotConstantExpression) { TEST_F(MapReduceFixture, ExpressionFunctionFailsIfBodyIsNotCorrectType) { auto bsonExpr = BSON("expr" << BSON("body" << 1 << "args" << BSON_ARRAY(1 << 2) << "lang" << ExpressionFunction::kJavaScript)); - ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31262); } @@ -167,7 +170,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsIfArgsIsNotSpecified) { auto bsonExpr = BSON("expr" << BSON("body" << "function(first) {return first;};" << "lang" << ExpressionFunction::kJavaScript)); - ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31263); } @@ -176,7 +179,7 @@ TEST_F(MapReduceFixture, ExpressionFunctionFailsIfLangIsNotSpecified) { auto bsonExpr = BSON("expr" << BSON("body" << "function(first) {return first;};" << "args" << BSON_ARRAY(1 << 2))); - ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ASSERT_THROWS_CODE(ExpressionFunction::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31418); } @@ -187,7 +190,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitProducesExpectedResult) { << "eval" << "function() {emit(this.a, 1); emit(this.b, 1)};")); - auto expr = ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); Value result = expr->evaluate(Document{BSON("a" << 3 << "b" << 6)}, getVariables()); ASSERT_VALUE_EQ(result, @@ -198,7 +201,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsIfThisArgumentNotSpecified auto bsonExpr = BSON("expr" << BSON("eval" << "function() {emit(this.a, 1); emit(this.b, 1)};")); ASSERT_THROWS_CODE( - ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31223); } @@ -207,7 +210,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsIfThisArgumentIsNotAnObjec auto bsonExpr = BSON("expr" << BSON("this" << 123 << "eval" << "function() {emit(this.a, 1); emit(this.b, 1)};")); - auto expr = ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); ASSERT_THROWS_CODE(expr->evaluate({}, getVariables()), AssertionException, 31225); } @@ -217,7 +220,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsWithInvalidFunction) { << "$$ROOT" << "eval" << "INVALID")); - auto expr = ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); ASSERT_THROWS_CODE( expr->evaluate({}, getVariables()), AssertionException, ErrorCodes::JSInterpreterFailure); @@ -228,7 +231,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsWithInvalidNumberOfEvalArg << "$$ROOT" << "eval" << "function() {emit(this.a);};")); - auto expr = ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); ASSERT_THROWS_CODE( expr->evaluate(Document{BSON("a" << 3)}, getVariables()), AssertionException, 31220); @@ -237,7 +240,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsWithInvalidNumberOfEvalArg TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsIfArgumentIsNotObject) { auto bsonExpr = BSON("expr" << 1); ASSERT_THROWS_CODE( - ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31221); } @@ -246,7 +249,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsIfEvalNotSpecified) { auto bsonExpr = BSON("expr" << BSON("this" << "$$ROOT")); ASSERT_THROWS_CODE( - ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31222); } @@ -256,7 +259,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsEmitFailsIfEvalIsNotCorrectType) { << "$$ROOT" << "eval" << 12.3)); ASSERT_THROWS_CODE( - ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()), + ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()), AssertionException, 31224); } @@ -268,7 +271,7 @@ TEST_F(MapReduceFixture, ExpressionInternalJsErrorsIfProducesTooManyDocumentsFor << "$$ROOT" << "eval" << "function() {for (var i = 0; i < this.val; ++i) {emit(i, 1);}}")); - auto expr = ExpressionInternalJsEmit::parse(getExpCtx(), bsonExpr.firstElement(), getVPS()); + auto expr = ExpressionInternalJsEmit::parse(getExpCtxRaw(), bsonExpr.firstElement(), getVPS()); ASSERT_THROWS_CODE( expr->evaluate(Document{BSON("val" << 1)}, getVariables()), AssertionException, 31292); } diff --git a/src/mongo/db/pipeline/expression_js_emit.cpp b/src/mongo/db/pipeline/expression_js_emit.cpp index 1544b171e26..6340a53e98f 100644 --- a/src/mongo/db/pipeline/expression_js_emit.cpp +++ b/src/mongo/db/pipeline/expression_js_emit.cpp @@ -88,10 +88,9 @@ BSONObj emitFromJS(const BSONObj& args, void* data) { } } // namespace -ExpressionInternalJsEmit::ExpressionInternalJsEmit( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - boost::intrusive_ptr<Expression> thisRef, - std::string funcSource) +ExpressionInternalJsEmit::ExpressionInternalJsEmit(ExpressionContext* const expCtx, + boost::intrusive_ptr<Expression> thisRef, + std::string funcSource) : Expression(expCtx, {std::move(thisRef)}), _emitState{{}, internalQueryMaxJsEmitBytes.load(), 0}, _thisRef(_children[0]), @@ -101,10 +100,9 @@ void ExpressionInternalJsEmit::_doAddDependencies(mongo::DepsTracker* deps) cons _children[0]->addDependencies(deps); } -boost::intrusive_ptr<Expression> ExpressionInternalJsEmit::parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps) { +boost::intrusive_ptr<Expression> ExpressionInternalJsEmit::parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps) { uassert(4660801, str::stream() << kExpressionName << " cannot be used inside a validator.", @@ -142,7 +140,7 @@ Value ExpressionInternalJsEmit::evaluate(const Document& root, Variables* variab // If the scope does not exist and is created by the following call, then make sure to // re-bind emit() and the given function to the new scope. - ExpressionContext* expCtx = getExpressionContext().get(); + ExpressionContext* expCtx = getExpressionContext(); auto jsExec = expCtx->getJsExecWithScope(); // Inject the native "emit" function to be called from the user-defined map function. This diff --git a/src/mongo/db/pipeline/expression_js_emit.h b/src/mongo/db/pipeline/expression_js_emit.h index 61298e50d3f..0d4788b4b4e 100644 --- a/src/mongo/db/pipeline/expression_js_emit.h +++ b/src/mongo/db/pipeline/expression_js_emit.h @@ -42,13 +42,12 @@ class ExpressionInternalJsEmit final : public Expression { public: static constexpr auto kExpressionName = "$_internalJsEmit"_sd; - static boost::intrusive_ptr<Expression> parse( - const boost::intrusive_ptr<ExpressionContext>& expCtx, - BSONElement expr, - const VariablesParseState& vps); + static boost::intrusive_ptr<Expression> parse(ExpressionContext* const expCtx, + BSONElement expr, + const VariablesParseState& vps); static boost::intrusive_ptr<ExpressionInternalJsEmit> create( - const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> thisRef, std::string funcSourceString) { return new ExpressionInternalJsEmit{expCtx, thisRef, std::move(funcSourceString)}; @@ -85,7 +84,7 @@ public: } _emitState; private: - ExpressionInternalJsEmit(const boost::intrusive_ptr<ExpressionContext>& expCtx, + ExpressionInternalJsEmit(ExpressionContext* const expCtx, boost::intrusive_ptr<Expression> thisRef, std::string funcSourceString); diff --git a/src/mongo/db/pipeline/expression_nary_test.cpp b/src/mongo/db/pipeline/expression_nary_test.cpp index 6fa2e6ec07e..3b709c4c7ae 100644 --- a/src/mongo/db/pipeline/expression_nary_test.cpp +++ b/src/mongo/db/pipeline/expression_nary_test.cpp @@ -78,16 +78,15 @@ public: return visitor->visit(this); } - static intrusive_ptr<Testable> create(bool associative, bool commutative) { - return new Testable(associative, commutative); + static intrusive_ptr<Testable> create(ExpressionContext* const expCtx, + bool associative, + bool commutative) { + return new Testable(expCtx, associative, commutative); } private: - Testable(bool isAssociative, bool isCommutative) - : ExpressionNary( - boost::intrusive_ptr<ExpressionContextForTest>(new ExpressionContextForTest())), - _isAssociative(isAssociative), - _isCommutative(isCommutative) {} + Testable(ExpressionContext* const expCtx, bool isAssociative, bool isCommutative) + : ExpressionNary(expCtx), _isAssociative(isAssociative), _isCommutative(isCommutative) {} bool _isAssociative; bool _isCommutative; }; @@ -123,9 +122,11 @@ static BSONObj expressionToBson(const intrusive_ptr<Expression>& expression) { class ExpressionBaseTest : public unittest::Test { public: void addOperand(intrusive_ptr<ExpressionNary> expr, Value arg) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - expr->addOperand(ExpressionConstant::create(expCtx, arg)); + expr->addOperand(ExpressionConstant::create(&expCtx, arg)); } + +protected: + ExpressionContextForTest expCtx; }; class ExpressionNaryTestOneArg : public ExpressionBaseTest { @@ -161,9 +162,9 @@ public: class ExpressionNaryTest : public unittest::Test { public: virtual void setUp() override { - _notAssociativeNorCommutative = Testable::create(false, false); - _associativeOnly = Testable::create(true, false); - _associativeAndCommutative = Testable::create(true, true); + _notAssociativeNorCommutative = Testable::create(&expCtx, false, false); + _associativeOnly = Testable::create(&expCtx, true, false); + _associativeAndCommutative = Testable::create(&expCtx, true, true); } protected: @@ -187,29 +188,27 @@ protected: } void addOperandArrayToExpr(const intrusive_ptr<Testable>& expr, const BSONArray& operands) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + VariablesParseState vps = expCtx.variablesParseState; BSONObjIterator i(operands); while (i.more()) { BSONElement element = i.next(); - expr->addOperand(Expression::parseOperand(expCtx, element, vps)); + expr->addOperand(Expression::parseOperand(&expCtx, element, vps)); } } + ExpressionContextForTest expCtx; intrusive_ptr<Testable> _notAssociativeNorCommutative; intrusive_ptr<Testable> _associativeOnly; intrusive_ptr<Testable> _associativeAndCommutative; }; TEST_F(ExpressionNaryTest, AddedConstantOperandIsSerialized) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(expCtx, Value(9))); + _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(&expCtx, Value(9))); assertContents(_notAssociativeNorCommutative, BSON_ARRAY(9)); } TEST_F(ExpressionNaryTest, AddedFieldPathOperandIsSerialized) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _notAssociativeNorCommutative->addOperand(ExpressionFieldPath::create(expCtx, "ab.c")); + _notAssociativeNorCommutative->addOperand(ExpressionFieldPath::create(&expCtx, "ab.c")); assertContents(_notAssociativeNorCommutative, BSON_ARRAY("$ab.c")); } @@ -218,14 +217,12 @@ TEST_F(ExpressionNaryTest, ValidateEmptyDependencies) { } TEST_F(ExpressionNaryTest, ValidateConstantExpressionDependency) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(expCtx, Value(1))); + _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(&expCtx, Value(1))); assertDependencies(_notAssociativeNorCommutative, BSONArray()); } TEST_F(ExpressionNaryTest, ValidateFieldPathExpressionDependency) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _notAssociativeNorCommutative->addOperand(ExpressionFieldPath::create(expCtx, "ab.c")); + _notAssociativeNorCommutative->addOperand(ExpressionFieldPath::create(&expCtx, "ab.c")); assertDependencies(_notAssociativeNorCommutative, BSON_ARRAY("ab.c")); } @@ -234,26 +231,23 @@ TEST_F(ExpressionNaryTest, ValidateObjectExpressionDependency) { << "$x" << "q" << "$r")); - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); BSONElement specElement = spec.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; + VariablesParseState vps = expCtx.variablesParseState; _notAssociativeNorCommutative->addOperand( - Expression::parseObject(expCtx, specElement.Obj(), vps)); + Expression::parseObject(&expCtx, specElement.Obj(), vps)); assertDependencies(_notAssociativeNorCommutative, BSON_ARRAY("r" << "x")); } TEST_F(ExpressionNaryTest, SerializationToBsonObj) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(expCtx, Value(5))); + _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(&expCtx, Value(5))); ASSERT_BSONOBJ_EQ(BSON("foo" << BSON("$testable" << BSON_ARRAY(BSON("$const" << 5)))), BSON("foo" << _notAssociativeNorCommutative->serialize(false))); } TEST_F(ExpressionNaryTest, SerializationToBsonArr) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(expCtx, Value(5))); + _notAssociativeNorCommutative->addOperand(ExpressionConstant::create(&expCtx, Value(5))); ASSERT_BSONOBJ_EQ(constify(BSON_ARRAY(BSON("$testable" << BSON_ARRAY(5)))), BSON_ARRAY(_notAssociativeNorCommutative->serialize(false))); } @@ -366,7 +360,7 @@ TEST_F(ExpressionNaryTest, FlattenOptimizationNotDoneOnOtherExpressionsForAssoci TEST_F(ExpressionNaryTest, FlattenOptimizationNotDoneOnSameButNotAssociativeExpression) { BSONArrayBuilder specBuilder; - intrusive_ptr<Testable> innerOperand = Testable::create(false, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, false, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1" << 101)); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); @@ -389,7 +383,7 @@ TEST_F(ExpressionNaryTest, FlattenOptimizationNotDoneOnSameButNotAssociativeExpr TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnNotCommutativeNorAssociative) { BSONArrayBuilder specBuilder; - intrusive_ptr<Testable> innerOperand = Testable::create(false, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, false, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1")); specBuilder.append(expressionToBson(innerOperand)); _notAssociativeNorCommutative->addOperand(innerOperand); @@ -413,7 +407,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnNotCommutativeNorAs TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyFrontOperandNoGroup) { BSONArrayBuilder specBuilder; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1")); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); @@ -438,7 +432,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyFron TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyFrontOperandAndGroup) { BSONArrayBuilder specBuilder; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1" << 101)); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); @@ -466,7 +460,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyMidd addOperandArrayToExpr(_associativeOnly, BSON_ARRAY(200 << "$path3")); specBuilder << 200 << "$path3"; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1")); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); @@ -494,7 +488,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyMidd addOperandArrayToExpr(_associativeOnly, BSON_ARRAY(200 << "$path3" << 201)); specBuilder << 200 << "$path3" << 201; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1" << 101)); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); @@ -523,7 +517,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyBack addOperandArrayToExpr(_associativeOnly, BSON_ARRAY(200 << "$path3")); specBuilder << 200 << "$path3"; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1")); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); @@ -548,7 +542,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyBack addOperandArrayToExpr(_associativeOnly, BSON_ARRAY(200 << "$path3" << 201)); specBuilder << 200 << "$path3" << 201; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1" << 101)); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); @@ -571,12 +565,12 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnAssociativeOnlyBack TEST_F(ExpressionNaryTest, FlattenConsecutiveInnerOperandsOptimizationOnAssociativeOnlyNoGroup) { BSONArrayBuilder specBuilder; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1")); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); - intrusive_ptr<Testable> innerOperand2 = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand2 = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand2, BSON_ARRAY(200 << "$path2")); specBuilder.append(expressionToBson(innerOperand2)); _associativeOnly->addOperand(innerOperand2); @@ -598,12 +592,12 @@ TEST_F(ExpressionNaryTest, FlattenConsecutiveInnerOperandsOptimizationOnAssociat TEST_F(ExpressionNaryTest, FlattenConsecutiveInnerOperandsOptimizationOnAssociativeAndGroup) { BSONArrayBuilder specBuilder; - intrusive_ptr<Testable> innerOperand = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1" << 101)); specBuilder.append(expressionToBson(innerOperand)); _associativeOnly->addOperand(innerOperand); - intrusive_ptr<Testable> innerOperand2 = Testable::create(true, false); + intrusive_ptr<Testable> innerOperand2 = Testable::create(&expCtx, true, false); addOperandArrayToExpr(innerOperand2, BSON_ARRAY(200 << "$path2")); specBuilder.append(expressionToBson(innerOperand2)); _associativeOnly->addOperand(innerOperand2); @@ -627,7 +621,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnCommutativeAndAssoc addOperandArrayToExpr(_associativeAndCommutative, BSON_ARRAY(200 << "$path3" << 201)); specBuilder << 200 << "$path3" << 201; - intrusive_ptr<Testable> innerOperand = Testable::create(true, true); + intrusive_ptr<Testable> innerOperand = Testable::create(&expCtx, true, true); addOperandArrayToExpr(innerOperand, BSON_ARRAY(100 << "$path1" << 101)); specBuilder.append(expressionToBson(innerOperand)); _associativeAndCommutative->addOperand(innerOperand); @@ -653,8 +647,7 @@ TEST_F(ExpressionNaryTest, FlattenInnerOperandsOptimizationOnCommutativeAndAssoc class ExpressionTruncOneArgTest : public ExpressionNaryTestOneArg { public: void assertEval(ImplicitValue input, ImplicitValue output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionTrunc(expCtx); + _expr = new ExpressionTrunc(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } }; @@ -662,8 +655,7 @@ public: class ExpressionTruncTwoArgTest : public ExpressionNaryTestTwoArg { public: void assertEval(ImplicitValue input1, ImplicitValue input2, ImplicitValue output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionTrunc(expCtx); + _expr = new ExpressionTrunc(&expCtx); ExpressionNaryTestTwoArg::assertEvaluates(input1, input2, output); } }; @@ -820,8 +812,7 @@ TEST_F(ExpressionTruncTwoArgTest, NullArg2) { class ExpressionSqrtTest : public ExpressionNaryTestOneArg { public: virtual void assertEvaluates(Value input, Value output) override { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionSqrt(expCtx); + _expr = new ExpressionSqrt(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } }; @@ -866,8 +857,7 @@ TEST_F(ExpressionSqrtTest, SqrtNaNArg) { class ExpressionExpTest : public ExpressionNaryTestOneArg { public: virtual void assertEvaluates(Value input, Value output) override { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionExp(expCtx); + _expr = new ExpressionExp(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } @@ -908,8 +898,7 @@ TEST_F(ExpressionExpTest, ExpNaNArg) { class ExpressionCeilTest : public ExpressionNaryTestOneArg { public: virtual void assertEvaluates(Value input, Value output) override { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionCeil(expCtx); + _expr = new ExpressionCeil(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } }; @@ -967,8 +956,7 @@ TEST_F(ExpressionCeilTest, NullArg) { class ExpressionFloorTest : public ExpressionNaryTestOneArg { public: virtual void assertEvaluates(Value input, Value output) override { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionFloor(expCtx); + _expr = new ExpressionFloor(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } }; @@ -1026,8 +1014,7 @@ TEST_F(ExpressionFloorTest, NullArg) { class ExpressionRoundOneArgTest : public ExpressionNaryTestOneArg { public: void assertEval(ImplicitValue input, ImplicitValue output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionRound(expCtx); + _expr = new ExpressionRound(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } }; @@ -1035,8 +1022,7 @@ public: class ExpressionRoundTwoArgTest : public ExpressionNaryTestTwoArg { public: void assertEval(ImplicitValue input1, ImplicitValue input2, ImplicitValue output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionRound(expCtx); + _expr = new ExpressionRound(&expCtx); ExpressionNaryTestTwoArg::assertEvaluates(input1, input2, output); } }; @@ -1196,8 +1182,7 @@ TEST_F(ExpressionRoundTwoArgTest, NullArg2) { class ExpressionBinarySizeTest : public ExpressionNaryTestOneArg { public: void assertEval(ImplicitValue input, ImplicitValue output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionBinarySize(expCtx); + _expr = new ExpressionBinarySize(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } }; @@ -1227,13 +1212,11 @@ TEST_F(ExpressionBinarySizeTest, HandlesNullish) { class ExpressionFirstTest : public ExpressionNaryTestOneArg { public: void assertEval(ImplicitValue input, ImplicitValue output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionFirst(expCtx); + _expr = new ExpressionFirst(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } void assertEvalFails(ImplicitValue input) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionFirst(expCtx); + _expr = new ExpressionFirst(&expCtx); ASSERT_THROWS_CODE(eval(input), DBException, 28689); } }; @@ -1264,13 +1247,11 @@ TEST_F(ExpressionFirstTest, RejectsNonArrays) { class ExpressionLastTest : public ExpressionNaryTestOneArg { public: void assertEval(ImplicitValue input, ImplicitValue output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionLast(expCtx); + _expr = new ExpressionLast(&expCtx); ExpressionNaryTestOneArg::assertEvaluates(input, output); } void assertEvalFails(ImplicitValue input) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - _expr = new ExpressionLast(expCtx); + _expr = new ExpressionLast(&expCtx); ASSERT_THROWS_CODE(eval(input), DBException, 28689); } }; diff --git a/src/mongo/db/pipeline/expression_object_test.cpp b/src/mongo/db/pipeline/expression_object_test.cpp index c0e7e6b2798..5b339bf911b 100644 --- a/src/mongo/db/pipeline/expression_object_test.cpp +++ b/src/mongo/db/pipeline/expression_object_test.cpp @@ -56,27 +56,21 @@ Document literal(T&& value) { return Document{{"$const", Value(std::forward<T>(value))}}; } -template <typename T> -intrusive_ptr<ExpressionConstant> makeConstant(T&& val) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - return ExpressionConstant::create(expCtx, Value(std::forward<T>(val))); -} - // // Parsing. // TEST(ExpressionObjectParse, ShouldAcceptEmptyObject) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto object = ExpressionObject::parse(expCtx, BSONObj(), vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto object = ExpressionObject::parse(&expCtx, BSONObj(), vps); ASSERT_VALUE_EQ(Value(Document{}), object->serialize(false)); } TEST(ExpressionObjectParse, ShouldAcceptLiteralsAsValues) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto object = ExpressionObject::parse(expCtx, + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto object = ExpressionObject::parse(&expCtx, BSON("a" << 5 << "b" << "string" << "c" << BSONNULL), @@ -87,26 +81,26 @@ TEST(ExpressionObjectParse, ShouldAcceptLiteralsAsValues) { } TEST(ExpressionObjectParse, ShouldAccept_idAsFieldName) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto object = ExpressionObject::parse(expCtx, BSON("_id" << 5), vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto object = ExpressionObject::parse(&expCtx, BSON("_id" << 5), vps); auto expectedResult = Value(Document{{"_id", literal(5)}}); ASSERT_VALUE_EQ(expectedResult, object->serialize(false)); } TEST(ExpressionObjectParse, ShouldAcceptFieldNameContainingDollar) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto object = ExpressionObject::parse(expCtx, BSON("a$b" << 5), vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto object = ExpressionObject::parse(&expCtx, BSON("a$b" << 5), vps); auto expectedResult = Value(Document{{"a$b", literal(5)}}); ASSERT_VALUE_EQ(expectedResult, object->serialize(false)); } TEST(ExpressionObjectParse, ShouldAcceptNestedObjects) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; auto object = - ExpressionObject::parse(expCtx, fromjson("{a: {b: 1}, c: {d: {e: 1, f: 1}}}"), vps); + ExpressionObject::parse(&expCtx, fromjson("{a: {b: 1}, c: {d: {e: 1, f: 1}}}"), vps); auto expectedResult = Value(Document{{"a", Document{{"b", literal(1)}}}, {"c", Document{{"d", Document{{"e", literal(1)}, {"f", literal(1)}}}}}}); @@ -114,18 +108,18 @@ TEST(ExpressionObjectParse, ShouldAcceptNestedObjects) { } TEST(ExpressionObjectParse, ShouldAcceptArrays) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto object = ExpressionObject::parse(expCtx, fromjson("{a: [1, 2]}"), vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto object = ExpressionObject::parse(&expCtx, fromjson("{a: [1, 2]}"), vps); auto expectedResult = Value(Document{{"a", vector<Value>{Value(literal(1)), Value(literal(2))}}}); ASSERT_VALUE_EQ(expectedResult, object->serialize(false)); } TEST(ObjectParsing, ShouldAcceptExpressionAsValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto object = ExpressionObject::parse(expCtx, BSON("a" << BSON("$and" << BSONArray())), vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto object = ExpressionObject::parse(&expCtx, BSON("a" << BSON("$and" << BSONArray())), vps); ASSERT_VALUE_EQ(object->serialize(false), Value(Document{{"a", Document{{"$and", BSONArray()}}}})); } @@ -135,43 +129,43 @@ TEST(ObjectParsing, ShouldAcceptExpressionAsValue) { // TEST(ExpressionObjectParse, ShouldRejectDottedFieldNames) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON("a.b" << 1), vps), AssertionException); - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON("c" << 3 << "a.b" << 1), vps), + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("a.b" << 1), vps), AssertionException); + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("c" << 3 << "a.b" << 1), vps), AssertionException); - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON("a.b" << 1 << "c" << 3), vps), + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("a.b" << 1 << "c" << 3), vps), AssertionException); } TEST(ExpressionObjectParse, ShouldRejectDuplicateFieldNames) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON("a" << 1 << "a" << 1), vps), + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("a" << 1 << "a" << 1), vps), AssertionException); - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON("a" << 1 << "b" << 2 << "a" << 1), vps), + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("a" << 1 << "b" << 2 << "a" << 1), vps), AssertionException); ASSERT_THROWS( - ExpressionObject::parse(expCtx, BSON("a" << BSON("c" << 1) << "b" << 2 << "a" << 1), vps), + ExpressionObject::parse(&expCtx, BSON("a" << BSON("c" << 1) << "b" << 2 << "a" << 1), vps), AssertionException); ASSERT_THROWS( - ExpressionObject::parse(expCtx, BSON("a" << 1 << "b" << 2 << "a" << BSON("c" << 1)), vps), + ExpressionObject::parse(&expCtx, BSON("a" << 1 << "b" << 2 << "a" << BSON("c" << 1)), vps), AssertionException); } TEST(ExpressionObjectParse, ShouldRejectInvalidFieldName) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON("$a" << 1), vps), AssertionException); - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON("" << 1), vps), AssertionException); - ASSERT_THROWS(ExpressionObject::parse(expCtx, BSON(std::string("a\0b", 3) << 1), vps), + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("$a" << 1), vps), AssertionException); + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("" << 1), vps), AssertionException); + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON(std::string("a\0b", 3) << 1), vps), AssertionException); } TEST(ExpressionObjectParse, ShouldRejectInvalidFieldPathAsValue) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - ASSERT_THROWS(ExpressionObject::parse(expCtx, + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + ASSERT_THROWS(ExpressionObject::parse(&expCtx, BSON("a" << "$field."), vps), @@ -179,11 +173,11 @@ TEST(ExpressionObjectParse, ShouldRejectInvalidFieldPathAsValue) { } TEST(ParseObject, ShouldRejectExpressionAsTheSecondField) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; ASSERT_THROWS( ExpressionObject::parse( - expCtx, BSON("a" << BSON("$and" << BSONArray()) << "$or" << BSONArray()), vps), + &expCtx, BSON("a" << BSON("$and" << BSONArray()) << "$or" << BSONArray()), vps), AssertionException); } @@ -192,70 +186,74 @@ TEST(ParseObject, ShouldRejectExpressionAsTheSecondField) { // TEST(ExpressionObjectEvaluate, EmptyObjectShouldEvaluateToEmptyDocument) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto object = ExpressionObject::create(expCtx, {}); - ASSERT_VALUE_EQ(Value(Document()), object->evaluate(Document(), &(expCtx->variables))); - ASSERT_VALUE_EQ(Value(Document()), object->evaluate(Document{{"a", 1}}, &(expCtx->variables))); + auto expCtx = ExpressionContextForTest{}; + auto object = ExpressionObject::create(&expCtx, {}); + ASSERT_VALUE_EQ(Value(Document()), object->evaluate(Document(), &(expCtx.variables))); + ASSERT_VALUE_EQ(Value(Document()), object->evaluate(Document{{"a", 1}}, &(expCtx.variables))); ASSERT_VALUE_EQ(Value(Document()), - object->evaluate(Document{{"_id", "ID"_sd}}, &(expCtx->variables))); + object->evaluate(Document{{"_id", "ID"_sd}}, &(expCtx.variables))); } TEST(ExpressionObjectEvaluate, ShouldEvaluateEachField) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto object = - ExpressionObject::create(expCtx, {{"a", makeConstant(1)}, {"b", makeConstant(5)}}); + auto expCtx = ExpressionContextForTest{}; + auto object = ExpressionObject::create(&expCtx, + {{"a", ExpressionConstant::create(&expCtx, Value{1})}, + {"b", ExpressionConstant::create(&expCtx, Value{5})}}); + + ASSERT_VALUE_EQ(Value(Document{{"a", 1}, {"b", 5}}), - object->evaluate(Document(), &(expCtx->variables))); + object->evaluate(Document(), &(expCtx.variables))); ASSERT_VALUE_EQ(Value(Document{{"a", 1}, {"b", 5}}), - object->evaluate(Document{{"a", 1}}, &(expCtx->variables))); + object->evaluate(Document{{"a", 1}}, &(expCtx.variables))); ASSERT_VALUE_EQ(Value(Document{{"a", 1}, {"b", 5}}), - object->evaluate(Document{{"_id", "ID"_sd}}, &(expCtx->variables))); + object->evaluate(Document{{"_id", "ID"_sd}}, &(expCtx.variables))); } TEST(ExpressionObjectEvaluate, OrderOfFieldsInOutputShouldMatchOrderInSpecification) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto object = ExpressionObject::create(expCtx, - {{"a", ExpressionFieldPath::create(expCtx, "a")}, - {"b", ExpressionFieldPath::create(expCtx, "b")}, - {"c", ExpressionFieldPath::create(expCtx, "c")}}); + auto expCtx = ExpressionContextForTest{}; + auto object = ExpressionObject::create(&expCtx, + {{"a", ExpressionFieldPath::create(&expCtx, "a")}, + {"b", ExpressionFieldPath::create(&expCtx, "b")}, + {"c", ExpressionFieldPath::create(&expCtx, "c")}}); ASSERT_VALUE_EQ( Value(Document{{"a", "A"_sd}, {"b", "B"_sd}, {"c", "C"_sd}}), object->evaluate(Document{{"c", "C"_sd}, {"a", "A"_sd}, {"b", "B"_sd}, {"_id", "ID"_sd}}, - &(expCtx->variables))); + &(expCtx.variables))); } TEST(ExpressionObjectEvaluate, ShouldRemoveFieldsThatHaveMissingValues) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto object = ExpressionObject::create(expCtx, - {{"a", ExpressionFieldPath::create(expCtx, "a.b")}, - {"b", ExpressionFieldPath::create(expCtx, "missing")}}); - ASSERT_VALUE_EQ(Value(Document{}), object->evaluate(Document(), &(expCtx->variables))); - ASSERT_VALUE_EQ(Value(Document{}), object->evaluate(Document{{"a", 1}}, &(expCtx->variables))); + auto expCtx = ExpressionContextForTest{}; + auto object = + ExpressionObject::create(&expCtx, + {{"a", ExpressionFieldPath::create(&expCtx, "a.b")}, + {"b", ExpressionFieldPath::create(&expCtx, "missing")}}); + ASSERT_VALUE_EQ(Value(Document{}), object->evaluate(Document(), &(expCtx.variables))); + ASSERT_VALUE_EQ(Value(Document{}), object->evaluate(Document{{"a", 1}}, &(expCtx.variables))); } TEST(ExpressionObjectEvaluate, ShouldEvaluateFieldsWithinNestedObject) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto object = ExpressionObject::create( - expCtx, + &expCtx, {{"a", - ExpressionObject::create( - expCtx, - {{"b", makeConstant(1)}, {"c", ExpressionFieldPath::create(expCtx, "_id")}})}}); + ExpressionObject::create(&expCtx, + {{"b", ExpressionConstant::create(&expCtx, Value{1})}, + {"c", ExpressionFieldPath::create(&expCtx, "_id")}})}}); ASSERT_VALUE_EQ(Value(Document{{"a", Document{{"b", 1}}}}), - object->evaluate(Document(), &(expCtx->variables))); + object->evaluate(Document(), &(expCtx.variables))); ASSERT_VALUE_EQ(Value(Document{{"a", Document{{"b", 1}, {"c", "ID"_sd}}}}), - object->evaluate(Document{{"_id", "ID"_sd}}, &(expCtx->variables))); + object->evaluate(Document{{"_id", "ID"_sd}}, &(expCtx.variables))); } TEST(ExpressionObjectEvaluate, ShouldEvaluateToEmptyDocumentIfAllFieldsAreMissing) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto object = - ExpressionObject::create(expCtx, {{"a", ExpressionFieldPath::create(expCtx, "missing")}}); - ASSERT_VALUE_EQ(Value(Document{}), object->evaluate(Document(), &(expCtx->variables))); + ExpressionObject::create(&expCtx, {{"a", ExpressionFieldPath::create(&expCtx, "missing")}}); + ASSERT_VALUE_EQ(Value(Document{}), object->evaluate(Document(), &(expCtx.variables))); - auto objectWithNestedObject = ExpressionObject::create(expCtx, {{"nested", object}}); + auto objectWithNestedObject = ExpressionObject::create(&expCtx, {{"nested", object}}); ASSERT_VALUE_EQ(Value(Document{{"nested", Document{}}}), - objectWithNestedObject->evaluate(Document(), &(expCtx->variables))); + objectWithNestedObject->evaluate(Document(), &(expCtx.variables))); } // @@ -263,17 +261,18 @@ TEST(ExpressionObjectEvaluate, ShouldEvaluateToEmptyDocumentIfAllFieldsAreMissin // TEST(ExpressionObjectDependencies, ConstantValuesShouldNotBeAddedToDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto object = ExpressionObject::create(expCtx, {{"a", makeConstant(5)}}); + auto expCtx = ExpressionContextForTest{}; + auto object = + ExpressionObject::create(&expCtx, {{"a", ExpressionConstant::create(&expCtx, Value{5})}}); DepsTracker deps; object->addDependencies(&deps); ASSERT_EQ(deps.fields.size(), 0UL); } TEST(ExpressionObjectDependencies, FieldPathsShouldBeAddedToDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto object = - ExpressionObject::create(expCtx, {{"x", ExpressionFieldPath::create(expCtx, "c.d")}}); + ExpressionObject::create(&expCtx, {{"x", ExpressionFieldPath::create(&expCtx, "c.d")}}); DepsTracker deps; object->addDependencies(&deps); ASSERT_EQ(deps.fields.size(), 1UL); @@ -281,9 +280,9 @@ TEST(ExpressionObjectDependencies, FieldPathsShouldBeAddedToDependencies) { }; TEST(ExpressionObjectDependencies, VariablesShouldBeAddedToDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varID = expCtx->variablesParseState.defineVariable("var1"); - auto fieldPath = ExpressionFieldPath::parse(expCtx, "$$var1", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto varID = expCtx.variablesParseState.defineVariable("var1"); + auto fieldPath = ExpressionFieldPath::parse(&expCtx, "$$var1", expCtx.variablesParseState); DepsTracker deps; fieldPath->addDependencies(&deps); ASSERT_EQ(deps.vars.size(), 1UL); @@ -291,24 +290,24 @@ TEST(ExpressionObjectDependencies, VariablesShouldBeAddedToDependencies) { } TEST(ExpressionObjectDependencies, LocalLetVariablesShouldBeFilteredOutOfDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - expCtx->variablesParseState.defineVariable("var1"); + auto expCtx = ExpressionContextForTest{}; + expCtx.variablesParseState.defineVariable("var1"); auto letSpec = BSON("$let" << BSON("vars" << BSON("var2" << "abc") << "in" << BSON("$multiply" << BSON_ARRAY("$$var1" << "$$var2")))); auto expressionLet = - ExpressionLet::parse(expCtx, letSpec.firstElement(), expCtx->variablesParseState); + ExpressionLet::parse(&expCtx, letSpec.firstElement(), expCtx.variablesParseState); DepsTracker deps; expressionLet->addDependencies(&deps); ASSERT_EQ(deps.vars.size(), 1UL); - ASSERT_EQ(expCtx->variablesParseState.getVariable("var1"), *deps.vars.begin()); + ASSERT_EQ(expCtx.variablesParseState.getVariable("var1"), *deps.vars.begin()); } TEST(ExpressionObjectDependencies, LocalMapVariablesShouldBeFilteredOutOfDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - expCtx->variablesParseState.defineVariable("var1"); + auto expCtx = ExpressionContextForTest{}; + expCtx.variablesParseState.defineVariable("var1"); auto mapSpec = BSON("$map" << BSON("input" << "$field1" << "as" @@ -318,16 +317,16 @@ TEST(ExpressionObjectDependencies, LocalMapVariablesShouldBeFilteredOutOfDepende << "$$var2")))); auto expressionMap = - ExpressionMap::parse(expCtx, mapSpec.firstElement(), expCtx->variablesParseState); + ExpressionMap::parse(&expCtx, mapSpec.firstElement(), expCtx.variablesParseState); DepsTracker deps; expressionMap->addDependencies(&deps); ASSERT_EQ(deps.vars.size(), 1UL); - ASSERT_EQ(expCtx->variablesParseState.getVariable("var1"), *deps.vars.begin()); + ASSERT_EQ(expCtx.variablesParseState.getVariable("var1"), *deps.vars.begin()); } TEST(ExpressionObjectDependencies, LocalFilterVariablesShouldBeFilteredOutOfDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - expCtx->variablesParseState.defineVariable("var1"); + auto expCtx = ExpressionContextForTest{}; + expCtx.variablesParseState.defineVariable("var1"); auto filterSpec = BSON("$filter" << BSON("input" << BSON_ARRAY(1 << 2 << 3) << "as" << "var2" << "cond" @@ -335,11 +334,11 @@ TEST(ExpressionObjectDependencies, LocalFilterVariablesShouldBeFilteredOutOfDepe << "$$var2")))); auto expressionFilter = - ExpressionFilter::parse(expCtx, filterSpec.firstElement(), expCtx->variablesParseState); + ExpressionFilter::parse(&expCtx, filterSpec.firstElement(), expCtx.variablesParseState); DepsTracker deps; expressionFilter->addDependencies(&deps); ASSERT_EQ(deps.vars.size(), 1UL); - ASSERT_EQ(expCtx->variablesParseState.getVariable("var1"), *deps.vars.begin()); + ASSERT_EQ(expCtx.variablesParseState.getVariable("var1"), *deps.vars.begin()); } // @@ -348,34 +347,34 @@ TEST(ExpressionObjectDependencies, LocalFilterVariablesShouldBeFilteredOutOfDepe TEST(ExpressionObjectOptimizations, OptimizingAnObjectShouldOptimizeSubExpressions) { // Build up the object {a: {$add: [1, 2]}}. - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; auto addExpression = - ExpressionAdd::parse(expCtx, BSON("$add" << BSON_ARRAY(1 << 2)).firstElement(), vps); - auto object = ExpressionObject::create(expCtx, {{"a", addExpression}}); + ExpressionAdd::parse(&expCtx, BSON("$add" << BSON_ARRAY(1 << 2)).firstElement(), vps); + auto object = ExpressionObject::create(&expCtx, {{"a", addExpression}}); ASSERT_EQ(object->getChildExpressions().size(), 1UL); auto optimized = object->optimize(); auto optimizedObject = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_TRUE(optimizedObject); - ASSERT_VALUE_EQ(optimizedObject->evaluate(Document(), &(expCtx->variables)), + ASSERT_VALUE_EQ(optimizedObject->evaluate(Document(), &(expCtx.variables)), Value(BSON("a" << 3))); }; TEST(ExpressionObjectOptimizations, OptimizingAnObjectWithAllConstantsShouldOptimizeToExpressionConstant) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; // All constants should optimize to ExpressionConstant. - auto objectWithAllConstants = ExpressionObject::parse(expCtx, BSON("b" << 1 << "c" << 1), vps); + auto objectWithAllConstants = ExpressionObject::parse(&expCtx, BSON("b" << 1 << "c" << 1), vps); auto optimizedToAllConstants = objectWithAllConstants->optimize(); auto constants = dynamic_cast<ExpressionConstant*>(optimizedToAllConstants.get()); ASSERT_TRUE(constants); // Not all constants should not optimize to ExpressionConstant. - auto objectNotAllConstants = ExpressionObject::parse(expCtx, + auto objectNotAllConstants = ExpressionObject::parse(&expCtx, BSON("b" << 1 << "input" << "$inputField"), vps); @@ -385,14 +384,14 @@ TEST(ExpressionObjectOptimizations, // Sub expression should optimize to constant expression. auto expressionWithConstantObject = ExpressionObject::parse( - expCtx, + &expCtx, BSON("willBeConstant" << BSON("$add" << BSON_ARRAY(1 << 2)) << "alreadyConstant" << "string"), vps); auto optimizedWithConstant = expressionWithConstantObject->optimize(); auto optimizedObject = dynamic_cast<ExpressionConstant*>(optimizedWithConstant.get()); ASSERT_TRUE(optimizedObject); - ASSERT_VALUE_EQ(optimizedObject->evaluate(Document(), &expCtx->variables), + ASSERT_VALUE_EQ(optimizedObject->evaluate(Document(), &expCtx.variables), Value(BSON("willBeConstant" << 3 << "alreadyConstant" << "string"))); }; diff --git a/src/mongo/db/pipeline/expression_or_test.cpp b/src/mongo/db/pipeline/expression_or_test.cpp index 20b0829c004..ca4f5fdf843 100644 --- a/src/mongo/db/pipeline/expression_or_test.cpp +++ b/src/mongo/db/pipeline/expression_or_test.cpp @@ -96,19 +96,18 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObject = BSON("" << spec()); BSONElement specElement = specObject.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); ASSERT_BSONOBJ_EQ( BSON("" << expectedResult()), - toBson(expression->evaluate(fromBson(BSON("a" << 1)), &expCtx->variables))); + toBson(expression->evaluate(fromBson(BSON("a" << 1)), &expCtx.variables))); intrusive_ptr<Expression> optimized = expression->optimize(); - ASSERT_BSONOBJ_EQ( - BSON("" << expectedResult()), - toBson(optimized->evaluate(fromBson(BSON("a" << 1)), &expCtx->variables))); + ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), + toBson(optimized->evaluate(fromBson(BSON("a" << 1)), &expCtx.variables))); } protected: @@ -120,11 +119,11 @@ class OptimizeBase { public: virtual ~OptimizeBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObject = BSON("" << spec()); BSONElement specElement = specObject.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); intrusive_ptr<Expression> optimized = expression->optimize(); ASSERT_BSONOBJ_EQ(expectedOptimized(), expressionToBson(optimized)); diff --git a/src/mongo/db/pipeline/expression_replace_test.cpp b/src/mongo/db/pipeline/expression_replace_test.cpp index f1f55ad2f91..2cfcd1194b4 100644 --- a/src/mongo/db/pipeline/expression_replace_test.cpp +++ b/src/mongo/db/pipeline/expression_replace_test.cpp @@ -41,11 +41,11 @@ using std::string; using namespace mongo; intrusive_ptr<Expression> parse(const string& expressionName, ImplicitValue operand) { - auto expCtx = make_intrusive<ExpressionContextForTest>(); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; Value operandValue = operand; const BSONObj obj = BSON(expressionName << operandValue); - return Expression::parseExpression(expCtx, obj, vps); + return Expression::parseExpression(&expCtx, obj, vps); } Value eval(const string& expressionName, diff --git a/src/mongo/db/pipeline/expression_test.cpp b/src/mongo/db/pipeline/expression_test.cpp index 9613a4122ef..fcc9e4f5230 100644 --- a/src/mongo/db/pipeline/expression_test.cpp +++ b/src/mongo/db/pipeline/expression_test.cpp @@ -64,11 +64,11 @@ using std::vector; */ static Value evaluateExpression(const string& expressionName, const vector<ImplicitValue>& operands) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; const BSONObj obj = BSON(expressionName << ImplicitValue::convertToValue(operands)); - auto expression = Expression::parseExpression(expCtx, obj, vps); - Value result = expression->evaluate({}, &expCtx->variables); + auto expression = Expression::parseExpression(&expCtx, obj, vps); + Value result = expression->evaluate({}, &expCtx.variables); return result; } @@ -248,10 +248,10 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(expCtx); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(&expCtx); populateOperands(expression); - ASSERT_BSONOBJ_EQ(expectedResult(), toBson(expression->evaluate({}, &expCtx->variables))); + ASSERT_BSONOBJ_EQ(expectedResult(), toBson(expression->evaluate({}, &expCtx.variables))); } protected: @@ -264,10 +264,10 @@ protected: class NullDocument { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(expCtx); - expression->addOperand(ExpressionConstant::create(expCtx, Value(2))); - ASSERT_BSONOBJ_EQ(BSON("" << 2), toBson(expression->evaluate({}, &expCtx->variables))); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(&expCtx); + expression->addOperand(ExpressionConstant::create(&expCtx, Value(2))); + ASSERT_BSONOBJ_EQ(BSON("" << 2), toBson(expression->evaluate({}, &expCtx.variables))); } }; @@ -283,10 +283,10 @@ class NoOperands : public ExpectedResultBase { class String { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(expCtx); - expression->addOperand(ExpressionConstant::create(expCtx, Value("a"_sd))); - ASSERT_THROWS(expression->evaluate({}, &expCtx->variables), AssertionException); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(&expCtx); + expression->addOperand(ExpressionConstant::create(&expCtx, Value("a"_sd))); + ASSERT_THROWS(expression->evaluate({}, &expCtx.variables), AssertionException); } }; @@ -294,23 +294,23 @@ public: class Bool { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(expCtx); - expression->addOperand(ExpressionConstant::create(expCtx, Value(true))); - ASSERT_THROWS(expression->evaluate({}, &expCtx->variables), AssertionException); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<ExpressionNary> expression = new ExpressionAdd(&expCtx); + expression->addOperand(ExpressionConstant::create(&expCtx, Value(true))); + ASSERT_THROWS(expression->evaluate({}, &expCtx.variables), AssertionException); } }; class SingleOperandBase : public ExpectedResultBase { void populateOperands(intrusive_ptr<ExpressionNary>& expression) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - expression->addOperand(ExpressionConstant::create(expCtx, valueFromBson(operand()))); + expression->addOperand(ExpressionConstant::create(&expCtx, valueFromBson(operand()))); } BSONObj expectedResult() { return operand(); } protected: + ExpressionContextForTest expCtx; virtual BSONObj operand() = 0; }; @@ -374,11 +374,11 @@ public: protected: void populateOperands(intrusive_ptr<ExpressionNary>& expression) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; expression->addOperand( - ExpressionConstant::create(expCtx, valueFromBson(_reverse ? operand2() : operand1()))); + ExpressionConstant::create(&expCtx, valueFromBson(_reverse ? operand2() : operand1()))); expression->addOperand( - ExpressionConstant::create(expCtx, valueFromBson(_reverse ? operand1() : operand2()))); + ExpressionConstant::create(&expCtx, valueFromBson(_reverse ? operand1() : operand2()))); } virtual BSONObj operand1() = 0; virtual BSONObj operand2() = 0; @@ -530,10 +530,10 @@ namespace CoerceToBool { class EvaluateTrue { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> nested = ExpressionConstant::create(expCtx, Value(5)); - intrusive_ptr<Expression> expression = ExpressionCoerceToBool::create(expCtx, nested); - ASSERT(expression->evaluate({}, &expCtx->variables).getBool()); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> nested = ExpressionConstant::create(&expCtx, Value(5)); + intrusive_ptr<Expression> expression = ExpressionCoerceToBool::create(&expCtx, nested); + ASSERT(expression->evaluate({}, &expCtx.variables).getBool()); } }; @@ -541,10 +541,10 @@ public: class EvaluateFalse { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> nested = ExpressionConstant::create(expCtx, Value(0)); - intrusive_ptr<Expression> expression = ExpressionCoerceToBool::create(expCtx, nested); - ASSERT(!expression->evaluate({}, &expCtx->variables).getBool()); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> nested = ExpressionConstant::create(&expCtx, Value(0)); + intrusive_ptr<Expression> expression = ExpressionCoerceToBool::create(&expCtx, nested); + ASSERT(!expression->evaluate({}, &expCtx.variables).getBool()); } }; @@ -552,9 +552,9 @@ public: class Dependencies { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> nested = ExpressionFieldPath::create(expCtx, "a.b"); - intrusive_ptr<Expression> expression = ExpressionCoerceToBool::create(expCtx, nested); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> nested = ExpressionFieldPath::create(&expCtx, "a.b"); + intrusive_ptr<Expression> expression = ExpressionCoerceToBool::create(&expCtx, nested); DepsTracker dependencies; expression->addDependencies(&dependencies); ASSERT_EQUALS(1U, dependencies.fields.size()); @@ -568,9 +568,9 @@ public: class AddToBsonObj { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; intrusive_ptr<Expression> expression = - ExpressionCoerceToBool::create(expCtx, ExpressionFieldPath::create(expCtx, "foo")); + ExpressionCoerceToBool::create(&expCtx, ExpressionFieldPath::create(&expCtx, "foo")); // serialized as $and because CoerceToBool isn't an ExpressionNary assertBinaryEqual(fromjson("{field:{$and:['$foo']}}"), toBsonObj(expression)); @@ -586,9 +586,9 @@ private: class AddToBsonArray { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; intrusive_ptr<Expression> expression = - ExpressionCoerceToBool::create(expCtx, ExpressionFieldPath::create(expCtx, "foo")); + ExpressionCoerceToBool::create(&expCtx, ExpressionFieldPath::create(&expCtx, "foo")); // serialized as $and because CoerceToBool isn't an ExpressionNary assertBinaryEqual(BSON_ARRAY(fromjson("{$and:['$foo']}")), toBsonArray(expression)); @@ -613,9 +613,9 @@ namespace Constant { class Create { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionConstant::create(expCtx, Value(5)); - assertBinaryEqual(BSON("" << 5), toBson(expression->evaluate({}, &expCtx->variables))); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionConstant::create(&expCtx, Value(5)); + assertBinaryEqual(BSON("" << 5), toBson(expression->evaluate({}, &expCtx.variables))); } }; @@ -625,13 +625,13 @@ public: void run() { BSONObj spec = BSON("IGNORED_FIELD_NAME" << "foo"); - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONElement specElement = spec.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = ExpressionConstant::parse(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = ExpressionConstant::parse(&expCtx, specElement, vps); assertBinaryEqual(BSON("" << "foo"), - toBson(expression->evaluate({}, &expCtx->variables))); + toBson(expression->evaluate({}, &expCtx.variables))); } }; @@ -639,8 +639,8 @@ public: class Optimize { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionConstant::create(expCtx, Value(5)); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionConstant::create(&expCtx, Value(5)); // An attempt to optimize returns the Expression itself. ASSERT_EQUALS(expression, expression->optimize()); } @@ -650,8 +650,8 @@ public: class Dependencies { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionConstant::create(expCtx, Value(5)); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionConstant::create(&expCtx, Value(5)); DepsTracker dependencies; expression->addDependencies(&dependencies); ASSERT_EQUALS(0U, dependencies.fields.size()); @@ -664,8 +664,8 @@ public: class AddToBsonObj { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionConstant::create(expCtx, Value(5)); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionConstant::create(&expCtx, Value(5)); // The constant is replaced with a $ expression. assertBinaryEqual(BSON("field" << BSON("$const" << 5)), toBsonObj(expression)); } @@ -680,8 +680,8 @@ private: class AddToBsonArray { public: void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionConstant::create(expCtx, Value(5)); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionConstant::create(&expCtx, Value(5)); // The constant is copied out as is. assertBinaryEqual(constify(BSON_ARRAY(5)), toBsonArray(expression)); } @@ -695,16 +695,16 @@ private: }; TEST(ExpressionConstantTest, ConstantOfValueMissingRemovesField) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionConstant::create(expCtx, Value()); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionConstant::create(&expCtx, Value()); assertBinaryEqual( BSONObj(), - toBson(expression->evaluate(Document{{"foo", Value("bar"_sd)}}, &expCtx->variables))); + toBson(expression->evaluate(Document{{"foo", Value("bar"_sd)}}, &expCtx.variables))); } TEST(ExpressionConstantTest, ConstantOfValueMissingSerializesToRemoveSystemVar) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - intrusive_ptr<Expression> expression = ExpressionConstant::create(expCtx, Value()); + auto expCtx = ExpressionContextForTest{}; + intrusive_ptr<Expression> expression = ExpressionConstant::create(&expCtx, Value()); assertBinaryEqual(BSON("field" << "$$REMOVE"), BSON("field" << expression->serialize(false))); @@ -798,15 +798,16 @@ TEST(ExpressionPowTest, LargeExponentValuesWithBaseOfZero) { } TEST(ExpressionPowTest, ThrowsWhenBaseZeroAndExpNegative) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; - const auto expr = Expression::parseExpression(expCtx, BSON("$pow" << BSON_ARRAY(0 << -5)), vps); - ASSERT_THROWS([&] { expr->evaluate({}, &expCtx->variables); }(), AssertionException); + const auto expr = + Expression::parseExpression(&expCtx, BSON("$pow" << BSON_ARRAY(0 << -5)), vps); + ASSERT_THROWS([&] { expr->evaluate({}, &expCtx.variables); }(), AssertionException); const auto exprWithLong = - Expression::parseExpression(expCtx, BSON("$pow" << BSON_ARRAY(0LL << -5LL)), vps); - ASSERT_THROWS([&] { expr->evaluate({}, &expCtx->variables); }(), AssertionException); + Expression::parseExpression(&expCtx, BSON("$pow" << BSON_ARRAY(0LL << -5LL)), vps); + ASSERT_THROWS([&] { expr->evaluate({}, &expCtx.variables); }(), AssertionException); } TEST(ExpressionPowTest, LargeExponentValuesWithBaseOfOne) { @@ -869,13 +870,13 @@ TEST(ExpressionPowTest, LargeBaseSmallPositiveExponent) { } TEST(ExpressionArray, ExpressionArrayWithAllConstantValuesShouldOptimizeToExpressionConstant) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; // ExpressionArray of constant values should optimize to ExpressionConsant. BSONObj bsonarrayOfConstants = BSON("" << BSON_ARRAY(1 << 2 << 3 << 4)); BSONElement elementArray = bsonarrayOfConstants.firstElement(); - auto expressionArr = ExpressionArray::parse(expCtx, elementArray, vps); + auto expressionArr = ExpressionArray::parse(&expCtx, elementArray, vps); auto optimizedToConstant = expressionArr->optimize(); auto exprConstant = dynamic_cast<ExpressionConstant*>(optimizedToConstant.get()); ASSERT_TRUE(exprConstant); @@ -883,15 +884,15 @@ TEST(ExpressionArray, ExpressionArrayWithAllConstantValuesShouldOptimizeToExpres // ExpressionArray with not all constant values should not optimize to ExpressionConstant. BSONObj bsonarray = BSON("" << BSON_ARRAY(1 << "$x" << 3 << 4)); BSONElement elementArrayNotConstant = bsonarray.firstElement(); - auto expressionArrNotConstant = ExpressionArray::parse(expCtx, elementArrayNotConstant, vps); + auto expressionArrNotConstant = ExpressionArray::parse(&expCtx, elementArrayNotConstant, vps); auto notOptimized = expressionArrNotConstant->optimize(); auto notExprConstant = dynamic_cast<ExpressionConstant*>(notOptimized.get()); ASSERT_FALSE(notExprConstant); } TEST(ExpressionArray, ExpressionArrayShouldOptimizeSubExpressionToExpressionConstant) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; // ExpressionArray with constant values and sub expression that evaluates to constant should @@ -900,7 +901,7 @@ TEST(ExpressionArray, ExpressionArrayShouldOptimizeSubExpressionToExpressionCons BSON("" << BSON_ARRAY(1 << BSON("$add" << BSON_ARRAY(1 << 1)) << 3 << 4)); BSONElement elementArrayWithSubExpression = bsonarrayWithSubExpression.firstElement(); auto expressionArrWithSubExpression = - ExpressionArray::parse(expCtx, elementArrayWithSubExpression, vps); + ExpressionArray::parse(&expCtx, elementArrayWithSubExpression, vps); auto optimizedToConstantWithSubExpression = expressionArrWithSubExpression->optimize(); auto constantExpression = dynamic_cast<ExpressionConstant*>(optimizedToConstantWithSubExpression.get()); @@ -908,10 +909,10 @@ TEST(ExpressionArray, ExpressionArrayShouldOptimizeSubExpressionToExpressionCons } TEST(ExpressionIndexOfArray, ExpressionIndexOfArrayShouldOptimizeArguments) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto expIndexOfArray = Expression::parseExpression( - expCtx, // 2, 1, 1 + &expCtx, // 2, 1, 1 BSON("$indexOfArray" << BSON_ARRAY( BSON_ARRAY(BSON("$add" << BSON_ARRAY(1 << 1)) << 1 << 1 << 2) // Value we are searching for = 2. @@ -920,7 +921,7 @@ TEST(ExpressionIndexOfArray, ExpressionIndexOfArrayShouldOptimizeArguments) { << BSON("$add" << BSON_ARRAY(0 << 1)) // End index = 4. << BSON("$add" << BSON_ARRAY(1 << 3)))), - expCtx->variablesParseState); + expCtx.variablesParseState); auto argsOptimizedToConstants = expIndexOfArray->optimize(); auto shouldBeIndexOfArray = dynamic_cast<ExpressionConstant*>(argsOptimizedToConstants.get()); ASSERT_TRUE(shouldBeIndexOfArray); @@ -929,11 +930,11 @@ TEST(ExpressionIndexOfArray, ExpressionIndexOfArrayShouldOptimizeArguments) { TEST(ExpressionIndexOfArray, ExpressionIndexOfArrayShouldOptimizeNullishInputArrayToExpressionConstant) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; auto expIndex = Expression::parseExpression( - expCtx, fromjson("{ $indexOfArray : [ undefined , 1, 1]}"), expCtx->variablesParseState); + &expCtx, fromjson("{ $indexOfArray : [ undefined , 1, 1]}"), expCtx.variablesParseState); auto isExpIndexOfArray = dynamic_cast<ExpressionIndexOfArray*>(expIndex.get()); ASSERT_TRUE(isExpIndexOfArray); @@ -949,87 +950,87 @@ TEST(ExpressionIndexOfArray, TEST(ExpressionIndexOfArray, OptimizedExpressionIndexOfArrayWithConstantArgumentsShouldEvaluateProperly) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto expIndexOfArray = Expression::parseExpression( - expCtx, + &expCtx, // Search for $x. fromjson("{ $indexOfArray : [ [0, 1, 2, 3, 4, 5, 'val'] , '$x'] }"), - expCtx->variablesParseState); + expCtx.variablesParseState); auto optimizedIndexOfArray = expIndexOfArray->optimize(); ASSERT_VALUE_EQ(Value(0), - optimizedIndexOfArray->evaluate(Document{{"x", 0}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 0}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(1), - optimizedIndexOfArray->evaluate(Document{{"x", 1}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 1}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(2), - optimizedIndexOfArray->evaluate(Document{{"x", 2}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 2}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(3), - optimizedIndexOfArray->evaluate(Document{{"x", 3}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 3}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(4), - optimizedIndexOfArray->evaluate(Document{{"x", 4}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 4}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(5), - optimizedIndexOfArray->evaluate(Document{{"x", 5}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 5}}, &expCtx.variables)); ASSERT_VALUE_EQ( Value(6), - optimizedIndexOfArray->evaluate(Document{{"x", string("val")}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", string("val")}}, &expCtx.variables)); auto optimizedIndexNotFound = optimizedIndexOfArray->optimize(); // Should evaluate to -1 if not found. ASSERT_VALUE_EQ(Value(-1), - optimizedIndexNotFound->evaluate(Document{{"x", 10}}, &expCtx->variables)); + optimizedIndexNotFound->evaluate(Document{{"x", 10}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(-1), - optimizedIndexNotFound->evaluate(Document{{"x", 100}}, &expCtx->variables)); + optimizedIndexNotFound->evaluate(Document{{"x", 100}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(-1), - optimizedIndexNotFound->evaluate(Document{{"x", 1000}}, &expCtx->variables)); + optimizedIndexNotFound->evaluate(Document{{"x", 1000}}, &expCtx.variables)); ASSERT_VALUE_EQ( Value(-1), - optimizedIndexNotFound->evaluate(Document{{"x", string("string")}}, &expCtx->variables)); + optimizedIndexNotFound->evaluate(Document{{"x", string("string")}}, &expCtx.variables)); ASSERT_VALUE_EQ(Value(-1), - optimizedIndexNotFound->evaluate(Document{{"x", -1}}, &expCtx->variables)); + optimizedIndexNotFound->evaluate(Document{{"x", -1}}, &expCtx.variables)); } TEST(ExpressionIndexOfArray, OptimizedExpressionIndexOfArrayWithConstantArgumentsShouldEvaluateProperlyWithRange) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto expIndexOfArray = Expression::parseExpression( - expCtx, + &expCtx, // Search for 4 between 3 and 5. fromjson("{ $indexOfArray : [ [0, 1, 2, 3, 4, 5] , '$x', 3, 5] }"), - expCtx->variablesParseState); + expCtx.variablesParseState); auto optimizedIndexOfArray = expIndexOfArray->optimize(); ASSERT_VALUE_EQ(Value(4), - optimizedIndexOfArray->evaluate(Document{{"x", 4}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 4}}, &expCtx.variables)); // Should evaluate to -1 if not found in range. ASSERT_VALUE_EQ(Value(-1), - optimizedIndexOfArray->evaluate(Document{{"x", 0}}, &expCtx->variables)); + optimizedIndexOfArray->evaluate(Document{{"x", 0}}, &expCtx.variables)); } TEST(ExpressionIndexOfArray, OptimizedExpressionIndexOfArrayWithConstantArrayShouldEvaluateProperlyWithDuplicateValues) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto expIndexOfArrayWithDuplicateValues = - Expression::parseExpression(expCtx, + Expression::parseExpression(&expCtx, // Search for 4 between 3 and 5. fromjson("{ $indexOfArray : [ [0, 1, 2, 2, 3, 4, 5] , '$x'] }"), - expCtx->variablesParseState); + expCtx.variablesParseState); auto optimizedIndexOfArrayWithDuplicateValues = expIndexOfArrayWithDuplicateValues->optimize(); ASSERT_VALUE_EQ( Value(2), - optimizedIndexOfArrayWithDuplicateValues->evaluate(Document{{"x", 2}}, &expCtx->variables)); + optimizedIndexOfArrayWithDuplicateValues->evaluate(Document{{"x", 2}}, &expCtx.variables)); // Duplicate Values in a range. auto expIndexInRangeWithhDuplicateValues = Expression::parseExpression( - expCtx, + &expCtx, // Search for 2 between 4 and 6. fromjson("{ $indexOfArray : [ [0, 1, 2, 2, 2, 2, 4, 5] , '$x', 4, 6] }"), - expCtx->variablesParseState); + expCtx.variablesParseState); auto optimizedIndexInRangeWithDuplcateValues = expIndexInRangeWithhDuplicateValues->optimize(); // Should evaluate to 4. ASSERT_VALUE_EQ( Value(4), - optimizedIndexInRangeWithDuplcateValues->evaluate(Document{{"x", 2}}, &expCtx->variables)); + optimizedIndexInRangeWithDuplcateValues->evaluate(Document{{"x", 2}}, &expCtx.variables)); } namespace Parse { @@ -1040,10 +1041,10 @@ namespace Object { * Parses the object given by 'specification', with the options given by 'parseContextOptions'. */ boost::intrusive_ptr<Expression> parseObject(BSONObj specification) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; - return Expression::parseObject(expCtx, specification, vps); + return Expression::parseObject(&expCtx, specification, vps); }; TEST(ParseObject, ShouldAcceptEmptyObject) { @@ -1074,9 +1075,9 @@ using mongo::Expression; * Parses an expression from the given BSON specification. */ boost::intrusive_ptr<Expression> parseExpression(BSONObj specification) { - const boost::intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - return Expression::parseExpression(expCtx, specification, vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + return Expression::parseExpression(&expCtx, specification, vps); } TEST(ParseExpression, ShouldRecognizeConstExpression) { @@ -1180,10 +1181,10 @@ using mongo::Expression; * case the field name would be the name of the expression. */ intrusive_ptr<Expression> parseOperand(BSONObj specification) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONElement specElement = specification.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - return Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + return Expression::parseOperand(&expCtx, specElement, vps); } TEST(ParseOperand, ShouldRecognizeFieldPath) { @@ -1245,7 +1246,7 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; const Document spec = getSpec(); const Value args = spec["input"]; if (!spec["expected"].missing()) { @@ -1254,10 +1255,10 @@ public: const Document::FieldPair field(fields.next()); const Value expected = field.second; const BSONObj obj = BSON(field.first << args); - VariablesParseState vps = expCtx->variablesParseState; + VariablesParseState vps = expCtx.variablesParseState; const intrusive_ptr<Expression> expr = - Expression::parseExpression(expCtx, obj, vps); - Value result = expr->evaluate({}, &expCtx->variables); + Expression::parseExpression(&expCtx, obj, vps); + Value result = expr->evaluate({}, &expCtx.variables); if (result.getType() == Array) { result = sortSet(result); } @@ -1277,14 +1278,14 @@ public: size_t n = asserters.size(); for (size_t i = 0; i < n; i++) { const BSONObj obj = BSON(asserters[i].getString() << args); - VariablesParseState vps = expCtx->variablesParseState; + VariablesParseState vps = expCtx.variablesParseState; ASSERT_THROWS( [&] { // NOTE: parse and evaluatation failures are treated the // same const intrusive_ptr<Expression> expr = - Expression::parseExpression(expCtx, obj, vps); - expr->evaluate({}, &expCtx->variables); + Expression::parseExpression(&expCtx, obj, vps); + expr->evaluate({}, &expCtx.variables); }(), AssertionException); } @@ -1543,14 +1544,14 @@ private: return BSON("$strcasecmp" << BSON_ARRAY(b() << a())); } void assertResult(int expectedResult, const BSONObj& spec) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObj = BSON("" << spec); BSONElement specElement = specObj.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec), expressionToBson(expression)); ASSERT_BSONOBJ_EQ(BSON("" << expectedResult), - toBson(expression->evaluate({}, &expCtx->variables))); + toBson(expression->evaluate({}, &expCtx.variables))); } }; @@ -1670,14 +1671,14 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObj = BSON("" << spec()); BSONElement specElement = specObj.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), - toBson(expression->evaluate({}, &expCtx->variables))); + toBson(expression->evaluate({}, &expCtx.variables))); } protected: @@ -1789,13 +1790,13 @@ class NegativeLength : public ExpectedResultBase { }; TEST(ExpressionSubstrTest, ThrowsWithNegativeStart) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; const auto str = "abcdef"_sd; const auto expr = - Expression::parseExpression(expCtx, BSON("$substrCP" << BSON_ARRAY(str << -5 << 1)), vps); - ASSERT_THROWS([&] { expr->evaluate({}, &expCtx->variables); }(), AssertionException); + Expression::parseExpression(&expCtx, BSON("$substrCP" << BSON_ARRAY(str << -5 << 1)), vps); + ASSERT_THROWS([&] { expr->evaluate({}, &expCtx.variables); }(), AssertionException); } } // namespace SubstrBytes @@ -1803,23 +1804,23 @@ TEST(ExpressionSubstrTest, ThrowsWithNegativeStart) { namespace SubstrCP { TEST(ExpressionSubstrCPTest, DoesThrowWithBadContinuationByte) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; const auto continuationByte = "\x80\x00"_sd; const auto expr = Expression::parseExpression( - expCtx, BSON("$substrCP" << BSON_ARRAY(continuationByte << 0 << 1)), vps); - ASSERT_THROWS([&] { expr->evaluate({}, &expCtx->variables); }(), AssertionException); + &expCtx, BSON("$substrCP" << BSON_ARRAY(continuationByte << 0 << 1)), vps); + ASSERT_THROWS([&] { expr->evaluate({}, &expCtx.variables); }(), AssertionException); } TEST(ExpressionSubstrCPTest, DoesThrowWithInvalidLeadingByte) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; const auto leadingByte = "\xFF\x00"_sd; const auto expr = Expression::parseExpression( - expCtx, BSON("$substrCP" << BSON_ARRAY(leadingByte << 0 << 1)), vps); - ASSERT_THROWS([&] { expr->evaluate({}, &expCtx->variables); }(), AssertionException); + &expCtx, BSON("$substrCP" << BSON_ARRAY(leadingByte << 0 << 1)), vps); + ASSERT_THROWS([&] { expr->evaluate({}, &expCtx.variables); }(), AssertionException); } TEST(ExpressionSubstrCPTest, WithStandardValue) { @@ -2071,27 +2072,27 @@ TEST(BuiltinRemoveVariableTest, LiteralEscapesRemoveVar) { } TEST(BuiltinRemoveVariableTest, RemoveSerializesCorrectly) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto expression = ExpressionFieldPath::parse(expCtx, "$$REMOVE", vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto expression = ExpressionFieldPath::parse(&expCtx, "$$REMOVE", vps); ASSERT_BSONOBJ_EQ(BSON("foo" << "$$REMOVE"), BSON("foo" << expression->serialize(false))); } TEST(BuiltinRemoveVariableTest, RemoveSerializesCorrectlyWithTrailingPath) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto expression = ExpressionFieldPath::parse(expCtx, "$$REMOVE.a.b", vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto expression = ExpressionFieldPath::parse(&expCtx, "$$REMOVE.a.b", vps); ASSERT_BSONOBJ_EQ(BSON("foo" << "$$REMOVE.a.b"), BSON("foo" << expression->serialize(false))); } TEST(BuiltinRemoveVariableTest, RemoveSerializesCorrectlyAfterOptimization) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; - auto expression = ExpressionFieldPath::parse(expCtx, "$$REMOVE.a.b", vps); + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; + auto expression = ExpressionFieldPath::parse(&expCtx, "$$REMOVE.a.b", vps); auto optimizedExpression = expression->optimize(); ASSERT(dynamic_cast<ExpressionConstant*>(optimizedExpression.get())); ASSERT_BSONOBJ_EQ(BSON("foo" @@ -2183,14 +2184,14 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObj = BSON("" << spec()); BSONElement specElement = specObj.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), - toBson(expression->evaluate({}, &expCtx->variables))); + toBson(expression->evaluate({}, &expCtx.variables))); } protected: @@ -2241,14 +2242,14 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj specObj = BSON("" << spec()); BSONElement specElement = specObj.firstElement(); - VariablesParseState vps = expCtx->variablesParseState; - intrusive_ptr<Expression> expression = Expression::parseOperand(expCtx, specElement, vps); + VariablesParseState vps = expCtx.variablesParseState; + intrusive_ptr<Expression> expression = Expression::parseOperand(&expCtx, specElement, vps); ASSERT_BSONOBJ_EQ(constify(spec()), expressionToBson(expression)); ASSERT_BSONOBJ_EQ(BSON("" << expectedResult()), - toBson(expression->evaluate({}, &expCtx->variables))); + toBson(expression->evaluate({}, &expCtx.variables))); } protected: @@ -2298,7 +2299,7 @@ class ExpectedResultBase { public: virtual ~ExpectedResultBase() {} void run() { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; const Document spec = getSpec(); const Value args = spec["input"]; if (!spec["expected"].missing()) { @@ -2307,10 +2308,10 @@ public: const Document::FieldPair field(fields.next()); const Value expected = field.second; const BSONObj obj = BSON(field.first << args); - VariablesParseState vps = expCtx->variablesParseState; + VariablesParseState vps = expCtx.variablesParseState; const intrusive_ptr<Expression> expr = - Expression::parseExpression(expCtx, obj, vps); - const Value result = expr->evaluate({}, &expCtx->variables); + Expression::parseExpression(&expCtx, obj, vps); + const Value result = expr->evaluate({}, &expCtx.variables); if (ValueComparator().evaluate(result != expected)) { string errMsg = str::stream() << "for expression " << field.first.toString() << " with argument " @@ -2327,14 +2328,14 @@ public: size_t n = asserters.size(); for (size_t i = 0; i < n; i++) { const BSONObj obj = BSON(asserters[i].getString() << args); - VariablesParseState vps = expCtx->variablesParseState; + VariablesParseState vps = expCtx.variablesParseState; ASSERT_THROWS( [&] { // NOTE: parse and evaluatation failures are treated the // same const intrusive_ptr<Expression> expr = - Expression::parseExpression(expCtx, obj, vps); - expr->evaluate({}, &expCtx->variables); + Expression::parseExpression(&expCtx, obj, vps); + expr->evaluate({}, &expCtx.variables); }(), AssertionException); } @@ -2400,8 +2401,8 @@ class Null : public ExpectedResultBase { namespace GetComputedPathsTest { TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWhenUsingRemoveBuiltin) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto expr = ExpressionFieldPath::parse(expCtx, "$$REMOVE", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto expr = ExpressionFieldPath::parse(&expCtx, "$$REMOVE", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("a", Variables::kRootId); ASSERT_EQ(computedPaths.paths.size(), 1u); ASSERT_EQ(computedPaths.paths.count("a"), 1u); @@ -2409,8 +2410,8 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWhenUsingRemov } TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWhenOnlyRoot) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto expr = ExpressionFieldPath::parse(expCtx, "$$ROOT", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto expr = ExpressionFieldPath::parse(&expCtx, "$$ROOT", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("a", Variables::kRootId); ASSERT_EQ(computedPaths.paths.size(), 1u); ASSERT_EQ(computedPaths.paths.count("a"), 1u); @@ -2418,9 +2419,9 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWhenOnlyRoot) } TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWithNonMatchingUserVariable) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - expCtx->variablesParseState.defineVariable("userVar"); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar.b", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + expCtx.variablesParseState.defineVariable("userVar"); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar.b", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("a", Variables::kRootId); ASSERT_EQ(computedPaths.paths.size(), 1u); ASSERT_EQ(computedPaths.paths.count("a"), 1u); @@ -2428,8 +2429,8 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWithNonMatchin } TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWhenDotted) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto expr = ExpressionFieldPath::parse(expCtx, "$a.b", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto expr = ExpressionFieldPath::parse(&expCtx, "$a.b", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("c", Variables::kRootId); ASSERT_EQ(computedPaths.paths.size(), 1u); ASSERT_EQ(computedPaths.paths.count("c"), 1u); @@ -2437,8 +2438,8 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesNotCountAsRenameWhenDotted) { } TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRename) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto expr = ExpressionFieldPath::parse(expCtx, "$a", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto expr = ExpressionFieldPath::parse(&expCtx, "$a", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("b", Variables::kRootId); ASSERT(computedPaths.paths.empty()); ASSERT_EQ(computedPaths.renames.size(), 1u); @@ -2446,8 +2447,8 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRename) { } TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRenameWithExplicitRoot) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto expr = ExpressionFieldPath::parse(expCtx, "$$ROOT.a", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto expr = ExpressionFieldPath::parse(&expCtx, "$$ROOT.a", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("b", Variables::kRootId); ASSERT(computedPaths.paths.empty()); ASSERT_EQ(computedPaths.renames.size(), 1u); @@ -2455,8 +2456,8 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRenameWithExplicitRoot) } TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRenameWithExplicitCurrent) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto expr = ExpressionFieldPath::parse(expCtx, "$$CURRENT.a", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto expr = ExpressionFieldPath::parse(&expCtx, "$$CURRENT.a", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("b", Variables::kRootId); ASSERT(computedPaths.paths.empty()); ASSERT_EQ(computedPaths.renames.size(), 1u); @@ -2464,9 +2465,9 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRenameWithExplicitCurre } TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRenameWithMatchingUserVariable) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto varId = expCtx->variablesParseState.defineVariable("userVar"); - auto expr = ExpressionFieldPath::parse(expCtx, "$$userVar.a", expCtx->variablesParseState); + auto expCtx = ExpressionContextForTest{}; + auto varId = expCtx.variablesParseState.defineVariable("userVar"); + auto expr = ExpressionFieldPath::parse(&expCtx, "$$userVar.a", expCtx.variablesParseState); auto computedPaths = expr->getComputedPaths("b", varId); ASSERT(computedPaths.paths.empty()); ASSERT_EQ(computedPaths.renames.size(), 1u); @@ -2474,9 +2475,9 @@ TEST(GetComputedPathsTest, ExpressionFieldPathDoesCountAsRenameWithMatchingUserV } TEST(GetComputedPathsTest, ExpressionObjectCorrectlyReportsComputedPaths) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson("{a: '$b', c: {$add: [1, 3]}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionObject*>(expr.get())); auto computedPaths = expr->getComputedPaths("d"); ASSERT_EQ(computedPaths.paths.size(), 1u); @@ -2486,11 +2487,11 @@ TEST(GetComputedPathsTest, ExpressionObjectCorrectlyReportsComputedPaths) { } TEST(GetComputedPathsTest, ExpressionObjectCorrectlyReportsComputedPathsNested) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson( "{a: {b: '$c'}," "d: {$map: {input: '$e', as: 'iter', in: {f: '$$iter.g'}}}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionObject*>(expr.get())); auto computedPaths = expr->getComputedPaths("h"); ASSERT(computedPaths.paths.empty()); @@ -2500,10 +2501,10 @@ TEST(GetComputedPathsTest, ExpressionObjectCorrectlyReportsComputedPathsNested) } TEST(GetComputedPathsTest, ExpressionMapCorrectlyReportsComputedPaths) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson("{$map: {input: '$a', as: 'iter', in: {b: '$$iter.c', d: {$add: [1, 2]}}}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionMap*>(expr.get())); auto computedPaths = expr->getComputedPaths("e"); ASSERT_EQ(computedPaths.paths.size(), 1u); @@ -2513,9 +2514,9 @@ TEST(GetComputedPathsTest, ExpressionMapCorrectlyReportsComputedPaths) { } TEST(GetComputedPathsTest, ExpressionMapCorrectlyReportsComputedPathsWithDefaultVarName) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson("{$map: {input: '$a', in: {b: '$$this.c', d: {$add: [1, 2]}}}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionMap*>(expr.get())); auto computedPaths = expr->getComputedPaths("e"); ASSERT_EQ(computedPaths.paths.size(), 1u); @@ -2525,9 +2526,9 @@ TEST(GetComputedPathsTest, ExpressionMapCorrectlyReportsComputedPathsWithDefault } TEST(GetComputedPathsTest, ExpressionMapCorrectlyReportsComputedPathsWithNestedExprObject) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson("{$map: {input: '$a', in: {b: {c: '$$this.d'}}}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionMap*>(expr.get())); auto computedPaths = expr->getComputedPaths("e"); ASSERT(computedPaths.paths.empty()); @@ -2536,9 +2537,9 @@ TEST(GetComputedPathsTest, ExpressionMapCorrectlyReportsComputedPathsWithNestedE } TEST(GetComputedPathsTest, ExpressionMapNotConsideredRenameWithWrongRootVariable) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson("{$map: {input: '$a', as: 'iter', in: {b: '$c'}}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionMap*>(expr.get())); auto computedPaths = expr->getComputedPaths("d"); ASSERT_EQ(computedPaths.paths.size(), 1u); @@ -2547,9 +2548,9 @@ TEST(GetComputedPathsTest, ExpressionMapNotConsideredRenameWithWrongRootVariable } TEST(GetComputedPathsTest, ExpressionMapNotConsideredRenameWithWrongVariableNoExpressionObject) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson("{$map: {input: '$a', as: 'iter', in: '$b'}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionMap*>(expr.get())); auto computedPaths = expr->getComputedPaths("d"); ASSERT_EQ(computedPaths.paths.size(), 1u); @@ -2558,9 +2559,9 @@ TEST(GetComputedPathsTest, ExpressionMapNotConsideredRenameWithWrongVariableNoEx } TEST(GetComputedPathsTest, ExpressionMapNotConsideredRenameWithDottedInputPath) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto specObject = fromjson("{$map: {input: '$a.b', as: 'iter', in: {c: '$$iter.d'}}}}"); - auto expr = Expression::parseObject(expCtx, specObject, expCtx->variablesParseState); + auto expr = Expression::parseObject(&expCtx, specObject, expCtx.variablesParseState); ASSERT(dynamic_cast<ExpressionMap*>(expr.get())); auto computedPaths = expr->getComputedPaths("e"); ASSERT_EQ(computedPaths.paths.size(), 1u); @@ -2572,115 +2573,115 @@ TEST(GetComputedPathsTest, ExpressionMapNotConsideredRenameWithDottedInputPath) namespace expression_meta_test { TEST(ExpressionMetaTest, ExpressionMetaSearchScore) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; BSONObj expr = fromjson("{$meta: \"searchScore\"}"); - auto expressionMeta = ExpressionMeta::parse(expCtx, expr.firstElement(), vps); + auto expressionMeta = ExpressionMeta::parse(&expCtx, expr.firstElement(), vps); MutableDocument doc; doc.metadata().setSearchScore(1.234); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_EQ(val.getDouble(), 1.234); } TEST(ExpressionMetaTest, ExpressionMetaSearchHighlights) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; BSONObj expr = fromjson("{$meta: \"searchHighlights\"}"); - auto expressionMeta = ExpressionMeta::parse(expCtx, expr.firstElement(), vps); + auto expressionMeta = ExpressionMeta::parse(&expCtx, expr.firstElement(), vps); MutableDocument doc; Document highlights = DOC("this part" << 1 << "is opaque to the server" << 1); doc.metadata().setSearchHighlights(Value(highlights)); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_DOCUMENT_EQ(val.getDocument(), highlights); } TEST(ExpressionMetaTest, ExpressionMetaGeoNearDistance) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj expr = fromjson("{$meta: \"geoNearDistance\"}"); auto expressionMeta = - ExpressionMeta::parse(expCtx, expr.firstElement(), expCtx->variablesParseState); + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); MutableDocument doc; doc.metadata().setGeoNearDistance(1.23); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_EQ(val.getDouble(), 1.23); } TEST(ExpressionMetaTest, ExpressionMetaGeoNearPoint) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj expr = fromjson("{$meta: \"geoNearPoint\"}"); auto expressionMeta = - ExpressionMeta::parse(expCtx, expr.firstElement(), expCtx->variablesParseState); + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); MutableDocument doc; Document pointDoc = Document{fromjson("{some: 'document'}")}; doc.metadata().setGeoNearPoint(Value(pointDoc)); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_DOCUMENT_EQ(val.getDocument(), pointDoc); } TEST(ExpressionMetaTest, ExpressionMetaIndexKey) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj expr = fromjson("{$meta: \"indexKey\"}"); auto expressionMeta = - ExpressionMeta::parse(expCtx, expr.firstElement(), expCtx->variablesParseState); + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); MutableDocument doc; BSONObj ixKey = fromjson("{'': 1, '': 'string'}"); doc.metadata().setIndexKey(ixKey); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_DOCUMENT_EQ(val.getDocument(), Document(ixKey)); } TEST(ExpressionMetaTest, ExpressionMetaRecordId) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj expr = fromjson("{$meta: \"recordId\"}"); auto expressionMeta = - ExpressionMeta::parse(expCtx, expr.firstElement(), expCtx->variablesParseState); + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); MutableDocument doc; doc.metadata().setRecordId(RecordId(123LL)); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_EQ(val.getLong(), 123LL); } TEST(ExpressionMetaTest, ExpressionMetaRandVal) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj expr = fromjson("{$meta: \"randVal\"}"); auto expressionMeta = - ExpressionMeta::parse(expCtx, expr.firstElement(), expCtx->variablesParseState); + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); MutableDocument doc; doc.metadata().setRandVal(1.23); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_EQ(val.getDouble(), 1.23); } TEST(ExpressionMetaTest, ExpressionMetaSortKey) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj expr = fromjson("{$meta: \"sortKey\"}"); auto expressionMeta = - ExpressionMeta::parse(expCtx, expr.firstElement(), expCtx->variablesParseState); + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); MutableDocument doc; Value sortKey = Value(std::vector<Value>{Value(1), Value(2)}); doc.metadata().setSortKey(sortKey, /* isSingleElementSortKey = */ false); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_VALUE_EQ(val, Value(std::vector<Value>{Value(1), Value(2)})); } TEST(ExpressionMetaTest, ExpressionMetaTextScore) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; BSONObj expr = fromjson("{$meta: \"textScore\"}"); auto expressionMeta = - ExpressionMeta::parse(expCtx, expr.firstElement(), expCtx->variablesParseState); + ExpressionMeta::parse(&expCtx, expr.firstElement(), expCtx.variablesParseState); MutableDocument doc; doc.metadata().setTextScore(1.23); - Value val = expressionMeta->evaluate(doc.freeze(), &expCtx->variables); + Value val = expressionMeta->evaluate(doc.freeze(), &expCtx.variables); ASSERT_EQ(val.getDouble(), 1.23); } } // namespace expression_meta_test @@ -2690,8 +2691,8 @@ namespace ExpressionRegexTest { class ExpressionRegexTest { public: template <typename ExpressionRegexSubClass> - static intrusive_ptr<Expression> generateOptimizedExpression( - const BSONObj& input, intrusive_ptr<ExpressionContextForTest> expCtx) { + static intrusive_ptr<Expression> generateOptimizedExpression(const BSONObj& input, + ExpressionContextForTest* expCtx) { auto expression = ExpressionRegexSubClass::parse( expCtx, input.firstElement(), expCtx->variablesParseState); @@ -2702,30 +2703,30 @@ public: bool optimized, const std::vector<Value>& expectedFindAllOutput) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; { // For $regexFindAll. - auto expression = generateOptimizedExpression<ExpressionRegexFindAll>(input, expCtx); + auto expression = generateOptimizedExpression<ExpressionRegexFindAll>(input, &expCtx); auto regexFindAllExpr = dynamic_cast<ExpressionRegexFindAll*>(expression.get()); ASSERT_EQ(regexFindAllExpr->hasConstantRegex(), optimized); - Value output = expression->evaluate({}, &expCtx->variables); + Value output = expression->evaluate({}, &expCtx.variables); ASSERT_VALUE_EQ(output, Value(expectedFindAllOutput)); } { // For $regexFind. - auto expression = generateOptimizedExpression<ExpressionRegexFind>(input, expCtx); + auto expression = generateOptimizedExpression<ExpressionRegexFind>(input, &expCtx); auto regexFindExpr = dynamic_cast<ExpressionRegexFind*>(expression.get()); ASSERT_EQ(regexFindExpr->hasConstantRegex(), optimized); - Value output = expression->evaluate({}, &expCtx->variables); + Value output = expression->evaluate({}, &expCtx.variables); ASSERT_VALUE_EQ( output, expectedFindAllOutput.empty() ? Value(BSONNULL) : expectedFindAllOutput[0]); } { // For $regexMatch. - auto expression = generateOptimizedExpression<ExpressionRegexMatch>(input, expCtx); + auto expression = generateOptimizedExpression<ExpressionRegexMatch>(input, &expCtx); auto regexMatchExpr = dynamic_cast<ExpressionRegexMatch*>(expression.get()); ASSERT_EQ(regexMatchExpr->hasConstantRegex(), optimized); - Value output = expression->evaluate({}, &expCtx->variables); + Value output = expression->evaluate({}, &expCtx.variables); ASSERT_VALUE_EQ(output, expectedFindAllOutput.empty() ? Value(false) : Value(true)); } } @@ -2915,37 +2916,37 @@ OldStyleSuiteInitializer<All> myAll; namespace NowAndClusterTime { TEST(NowAndClusterTime, BasicTest) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; // $$NOW is the Date type. { - auto expression = ExpressionFieldPath::parse(expCtx, "$$NOW", expCtx->variablesParseState); - Value result = expression->evaluate(Document(), &(expCtx->variables)); + auto expression = ExpressionFieldPath::parse(&expCtx, "$$NOW", expCtx.variablesParseState); + Value result = expression->evaluate(Document(), &expCtx.variables); ASSERT_EQ(result.getType(), Date); } // $$CLUSTER_TIME is the timestamp type. { auto expression = - ExpressionFieldPath::parse(expCtx, "$$CLUSTER_TIME", expCtx->variablesParseState); - Value result = expression->evaluate(Document(), &(expCtx->variables)); + ExpressionFieldPath::parse(&expCtx, "$$CLUSTER_TIME", expCtx.variablesParseState); + Value result = expression->evaluate(Document(), &expCtx.variables); ASSERT_EQ(result.getType(), bsonTimestamp); } // Multiple references to $$NOW must return the same value. { auto expression = Expression::parseExpression( - expCtx, fromjson("{$eq: [\"$$NOW\", \"$$NOW\"]}"), expCtx->variablesParseState); - Value result = expression->evaluate(Document(), &(expCtx->variables)); + &expCtx, fromjson("{$eq: [\"$$NOW\", \"$$NOW\"]}"), expCtx.variablesParseState); + Value result = expression->evaluate(Document(), &expCtx.variables); ASSERT_VALUE_EQ(result, Value{true}); } // Same is true for the $$CLUSTER_TIME. { auto expression = - Expression::parseExpression(expCtx, + Expression::parseExpression(&expCtx, fromjson("{$eq: [\"$$CLUSTER_TIME\", \"$$CLUSTER_TIME\"]}"), - expCtx->variablesParseState); - Value result = expression->evaluate(Document(), &(expCtx->variables)); + expCtx.variablesParseState); + Value result = expression->evaluate(Document(), &expCtx.variables); ASSERT_VALUE_EQ(result, Value{true}); } diff --git a/src/mongo/db/pipeline/expression_trigonometric.cpp b/src/mongo/db/pipeline/expression_trigonometric.cpp index 8a39259df7e..0ee9eeb84b1 100644 --- a/src/mongo/db/pipeline/expression_trigonometric.cpp +++ b/src/mongo/db/pipeline/expression_trigonometric.cpp @@ -39,7 +39,7 @@ namespace mongo { class Expression##className final \ : public ExpressionBoundedTrigonometric<Expression##className, boundType> { \ public: \ - explicit Expression##className(const boost::intrusive_ptr<ExpressionContext>& expCtx) \ + explicit Expression##className(ExpressionContext* const expCtx) \ : ExpressionBoundedTrigonometric(expCtx) {} \ double getLowerBound() const final { \ return lowerBound; \ @@ -106,29 +106,29 @@ CREATE_BOUNDED_TRIGONOMETRIC_CLASS(Tangent, /* ----------------------- Unbounded Trigonometric Functions ---------------------------- */ -#define CREATE_TRIGONOMETRIC_CLASS(className, funcName) \ - class Expression##className final \ - : public ExpressionUnboundedTrigonometric<Expression##className> { \ - public: \ - explicit Expression##className(const boost::intrusive_ptr<ExpressionContext>& expCtx) \ - : ExpressionUnboundedTrigonometric(expCtx) {} \ - \ - double doubleFunc(double arg) const final { \ - return std::funcName(arg); \ - } \ - \ - Decimal128 decimalFunc(Decimal128 arg) const final { \ - return arg.funcName(); \ - } \ - \ - const char* getOpName() const final { \ - return "$" #funcName; \ - } \ - \ - void acceptVisitor(ExpressionVisitor* visitor) final { \ - return visitor->visit(this); \ - } \ - }; \ +#define CREATE_TRIGONOMETRIC_CLASS(className, funcName) \ + class Expression##className final \ + : public ExpressionUnboundedTrigonometric<Expression##className> { \ + public: \ + explicit Expression##className(ExpressionContext* const expCtx) \ + : ExpressionUnboundedTrigonometric(expCtx) {} \ + \ + double doubleFunc(double arg) const final { \ + return std::funcName(arg); \ + } \ + \ + Decimal128 decimalFunc(Decimal128 arg) const final { \ + return arg.funcName(); \ + } \ + \ + const char* getOpName() const final { \ + return "$" #funcName; \ + } \ + \ + void acceptVisitor(ExpressionVisitor* visitor) final { \ + return visitor->visit(this); \ + } \ + }; \ REGISTER_EXPRESSION(funcName, Expression##className::parse); CREATE_TRIGONOMETRIC_CLASS(ArcTangent, atan); @@ -144,7 +144,7 @@ CREATE_TRIGONOMETRIC_CLASS(HyperbolicTangent, tanh); class ExpressionArcTangent2 final : public ExpressionTwoNumericArgs<ExpressionArcTangent2> { public: - explicit ExpressionArcTangent2(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionArcTangent2(ExpressionContext* const expCtx) : ExpressionTwoNumericArgs(expCtx) {} Value evaluateNumericArgs(const Value& numericArg1, const Value& numericArg2) const final { @@ -199,7 +199,7 @@ static Value doDegreeRadiansConversion(const Value& numericArg, class ExpressionDegreesToRadians final : public ExpressionSingleNumericArg<ExpressionDegreesToRadians> { public: - explicit ExpressionDegreesToRadians(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionDegreesToRadians(ExpressionContext* const expCtx) : ExpressionSingleNumericArg(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final { @@ -220,7 +220,7 @@ REGISTER_EXPRESSION(degreesToRadians, ExpressionDegreesToRadians::parse); class ExpressionRadiansToDegrees final : public ExpressionSingleNumericArg<ExpressionRadiansToDegrees> { public: - explicit ExpressionRadiansToDegrees(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionRadiansToDegrees(ExpressionContext* const expCtx) : ExpressionSingleNumericArg(expCtx) {} Value evaluateNumericArg(const Value& numericArg) const final { diff --git a/src/mongo/db/pipeline/expression_trigonometric.h b/src/mongo/db/pipeline/expression_trigonometric.h index cc8ca852f8b..1c4236e7ccc 100644 --- a/src/mongo/db/pipeline/expression_trigonometric.h +++ b/src/mongo/db/pipeline/expression_trigonometric.h @@ -103,7 +103,7 @@ struct ExclusiveBoundType { template <typename BoundedTrigType, typename BoundType> class ExpressionBoundedTrigonometric : public ExpressionSingleNumericArg<BoundedTrigType> { public: - explicit ExpressionBoundedTrigonometric(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionBoundedTrigonometric(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<BoundedTrigType>(expCtx) {} std::string toString(double d) const { @@ -198,7 +198,7 @@ public: template <typename TrigType> class ExpressionUnboundedTrigonometric : public ExpressionSingleNumericArg<TrigType> { public: - explicit ExpressionUnboundedTrigonometric(const boost::intrusive_ptr<ExpressionContext>& expCtx) + explicit ExpressionUnboundedTrigonometric(ExpressionContext* const expCtx) : ExpressionSingleNumericArg<TrigType>(expCtx) {} /** diff --git a/src/mongo/db/pipeline/expression_trigonometric_test.cpp b/src/mongo/db/pipeline/expression_trigonometric_test.cpp index dac735bd242..5a37a78a21a 100644 --- a/src/mongo/db/pipeline/expression_trigonometric_test.cpp +++ b/src/mongo/db/pipeline/expression_trigonometric_test.cpp @@ -54,11 +54,11 @@ static void assertApproxEq(const Value& evaluated, const Value& expected) { // A testing class for testing approximately equal results for one argument numeric expressions. static void assertEvaluates(const std::string& expressionName, Value input, Value output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto obj = BSON(expressionName << BSON_ARRAY(input)); - auto vps = expCtx->variablesParseState; - auto expression = Expression::parseExpression(expCtx, obj, vps); - Value result = expression->evaluate({}, &expCtx->variables); + auto vps = expCtx.variablesParseState; + auto expression = Expression::parseExpression(&expCtx, obj, vps); + Value result = expression->evaluate({}, &expCtx.variables); ASSERT_EQUALS(result.getType(), output.getType()); assertApproxEq(result, output); } @@ -69,11 +69,11 @@ static void assertEvaluates(const std::string& expressionName, Value input1, Value input2, Value output) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto obj = BSON(expressionName << BSON_ARRAY(input1 << input2)); - auto vps = expCtx->variablesParseState; - auto expression = Expression::parseExpression(expCtx, obj, vps); - Value result = expression->evaluate({}, &expCtx->variables); + auto vps = expCtx.variablesParseState; + auto expression = Expression::parseExpression(&expCtx, obj, vps); + Value result = expression->evaluate({}, &expCtx.variables); ASSERT_EQUALS(result.getType(), output.getType()); assertApproxEq(result, output); } diff --git a/src/mongo/db/pipeline/expression_trim_test.cpp b/src/mongo/db/pipeline/expression_trim_test.cpp index a54ee025014..620b371c5f7 100644 --- a/src/mongo/db/pipeline/expression_trim_test.cpp +++ b/src/mongo/db/pipeline/expression_trim_test.cpp @@ -53,67 +53,67 @@ using std::string; * and returns the result. */ static Value evaluateNamedArgExpression(const string& expressionName, const Document& operand) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - VariablesParseState vps = expCtx->variablesParseState; + auto expCtx = ExpressionContextForTest{}; + VariablesParseState vps = expCtx.variablesParseState; const BSONObj obj = BSON(expressionName << operand); - auto expression = Expression::parseExpression(expCtx, obj, vps); - Value result = expression->evaluate({}, &expCtx->variables); + auto expression = Expression::parseExpression(&expCtx, obj, vps); + Value result = expression->evaluate({}, &expCtx.variables); return result; } namespace Trim { TEST(ExpressionTrimParsingTest, ThrowsIfSpecIsNotAnObject) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; ASSERT_THROWS( - Expression::parseExpression(expCtx, BSON("$trim" << 1), expCtx->variablesParseState), + Expression::parseExpression(&expCtx, BSON("$trim" << 1), expCtx.variablesParseState), AssertionException); ASSERT_THROWS(Expression::parseExpression( - expCtx, BSON("$trim" << BSON_ARRAY(1 << 2)), expCtx->variablesParseState), + &expCtx, BSON("$trim" << BSON_ARRAY(1 << 2)), expCtx.variablesParseState), AssertionException); ASSERT_THROWS(Expression::parseExpression( - expCtx, BSON("$ltrim" << BSONNULL), expCtx->variablesParseState), + &expCtx, BSON("$ltrim" << BSONNULL), expCtx.variablesParseState), AssertionException); - ASSERT_THROWS(Expression::parseExpression(expCtx, + ASSERT_THROWS(Expression::parseExpression(&expCtx, BSON("$rtrim" << "string"), - expCtx->variablesParseState), + expCtx.variablesParseState), AssertionException); } TEST(ExpressionTrimParsingTest, ThrowsIfSpecDoesNotSpecifyInput) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; ASSERT_THROWS(Expression::parseExpression( - expCtx, BSON("$trim" << BSONObj()), expCtx->variablesParseState), + &expCtx, BSON("$trim" << BSONObj()), expCtx.variablesParseState), AssertionException); - ASSERT_THROWS(Expression::parseExpression(expCtx, + ASSERT_THROWS(Expression::parseExpression(&expCtx, BSON("$ltrim" << BSON("chars" << "xyz")), - expCtx->variablesParseState), + expCtx.variablesParseState), AssertionException); } TEST(ExpressionTrimParsingTest, ThrowsIfSpecContainsUnrecognizedField) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; ASSERT_THROWS(Expression::parseExpression( - expCtx, BSON("$trim" << BSON("other" << 1)), expCtx->variablesParseState), + &expCtx, BSON("$trim" << BSON("other" << 1)), expCtx.variablesParseState), AssertionException); - ASSERT_THROWS(Expression::parseExpression(expCtx, + ASSERT_THROWS(Expression::parseExpression(&expCtx, BSON("$ltrim" << BSON("chars" << "xyz" << "other" << 1)), - expCtx->variablesParseState), + expCtx.variablesParseState), AssertionException); - ASSERT_THROWS(Expression::parseExpression(expCtx, + ASSERT_THROWS(Expression::parseExpression(&expCtx, BSON("$rtrim" << BSON("input" << "$x" << "chars" << "xyz" << "other" << 1)), - expCtx->variablesParseState), + expCtx.variablesParseState), AssertionException); } @@ -446,19 +446,19 @@ TEST(ExpressionTrimTest, DoesNotTrimAnyThingWithEmptyChars) { } TEST(ExpressionTrimTest, TrimComparisonsShouldNotRespectCollation) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; auto caseInsensitive = std::make_unique<CollatorInterfaceMock>(CollatorInterfaceMock::MockType::kToLowerString); - expCtx->setCollator(std::move(caseInsensitive)); + expCtx.setCollator(std::move(caseInsensitive)); - auto trim = Expression::parseExpression(expCtx, + auto trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << "xxXXxx" << "chars" << "x")), - expCtx->variablesParseState); + expCtx.variablesParseState); - ASSERT_VALUE_EQ(trim->evaluate({}, &expCtx->variables), Value("XX"_sd)); + ASSERT_VALUE_EQ(trim->evaluate({}, &expCtx.variables), Value("XX"_sd)); } TEST(ExpressionTrimTest, ShouldRejectInvalidUTFInCharsArgument) { @@ -590,11 +590,11 @@ TEST(ExpressionTrimTest, ShouldReturnNullIfBothCharsAndCharsAreNullish) { } TEST(ExpressionTrimTest, DoesOptimizeToConstantWithNoChars) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto trim = Expression::parseExpression(expCtx, + auto expCtx = ExpressionContextForTest{}; + auto trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << " abc ")), - expCtx->variablesParseState); + expCtx.variablesParseState); auto optimized = trim->optimize(); auto constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_TRUE(constant); @@ -602,10 +602,10 @@ TEST(ExpressionTrimTest, DoesOptimizeToConstantWithNoChars) { // Test that it optimizes to a constant if the input also optimizes to a constant. trim = Expression::parseExpression( - expCtx, + &expCtx, BSON("$trim" << BSON("input" << BSON("$concat" << BSON_ARRAY(" " << "abc ")))), - expCtx->variablesParseState); + expCtx.variablesParseState); optimized = trim->optimize(); constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_TRUE(constant); @@ -613,13 +613,13 @@ TEST(ExpressionTrimTest, DoesOptimizeToConstantWithNoChars) { } TEST(ExpressionTrimTest, DoesOptimizeToConstantWithCustomChars) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); - auto trim = Expression::parseExpression(expCtx, + auto expCtx = ExpressionContextForTest{}; + auto trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << " abc " << "chars" << " ")), - expCtx->variablesParseState); + expCtx.variablesParseState); auto optimized = trim->optimize(); auto constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_TRUE(constant); @@ -627,11 +627,11 @@ TEST(ExpressionTrimTest, DoesOptimizeToConstantWithCustomChars) { // Test that it optimizes to a constant if the chars argument optimizes to a constant. trim = Expression::parseExpression( - expCtx, + &expCtx, BSON("$trim" << BSON("input" << " abc " << "chars" << BSON("$substrCP" << BSON_ARRAY(" " << 1 << 1)))), - expCtx->variablesParseState); + expCtx.variablesParseState); optimized = trim->optimize(); constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_TRUE(constant); @@ -639,12 +639,12 @@ TEST(ExpressionTrimTest, DoesOptimizeToConstantWithCustomChars) { // Test that it optimizes to a constant if both arguments optimize to a constant. trim = Expression::parseExpression( - expCtx, + &expCtx, BSON("$trim" << BSON("input" << BSON("$concat" << BSON_ARRAY(" " << "abc ")) << "chars" << BSON("$substrCP" << BSON_ARRAY(" " << 1 << 1)))), - expCtx->variablesParseState); + expCtx.variablesParseState); optimized = trim->optimize(); constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_TRUE(constant); @@ -652,47 +652,47 @@ TEST(ExpressionTrimTest, DoesOptimizeToConstantWithCustomChars) { } TEST(ExpressionTrimTest, DoesNotOptimizeToConstantWithFieldPaths) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; // 'input' is field path. - auto trim = Expression::parseExpression(expCtx, + auto trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << "$inputField")), - expCtx->variablesParseState); + expCtx.variablesParseState); auto optimized = trim->optimize(); auto constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_FALSE(constant); // 'chars' is field path. - trim = Expression::parseExpression(expCtx, + trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << " abc " << "chars" << "$secondInput")), - expCtx->variablesParseState); + expCtx.variablesParseState); optimized = trim->optimize(); constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_FALSE(constant); // Both are field paths. - trim = Expression::parseExpression(expCtx, + trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << "$inputField" << "chars" << "$secondInput")), - expCtx->variablesParseState); + expCtx.variablesParseState); optimized = trim->optimize(); constant = dynamic_cast<ExpressionConstant*>(optimized.get()); ASSERT_FALSE(constant); } TEST(ExpressionTrimTest, DoesAddInputDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; - auto trim = Expression::parseExpression(expCtx, + auto trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << "$inputField")), - expCtx->variablesParseState); + expCtx.variablesParseState); DepsTracker deps; trim->addDependencies(&deps); ASSERT_EQ(deps.fields.count("inputField"), 1u); @@ -700,14 +700,14 @@ TEST(ExpressionTrimTest, DoesAddInputDependencies) { } TEST(ExpressionTrimTest, DoesAddCharsDependencies) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; - auto trim = Expression::parseExpression(expCtx, + auto trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << "$inputField" << "chars" << "$$CURRENT.a")), - expCtx->variablesParseState); + expCtx.variablesParseState); DepsTracker deps; trim->addDependencies(&deps); ASSERT_EQ(deps.fields.count("inputField"), 1u); @@ -716,12 +716,12 @@ TEST(ExpressionTrimTest, DoesAddCharsDependencies) { } TEST(ExpressionTrimTest, DoesSerializeCorrectly) { - intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); + auto expCtx = ExpressionContextForTest{}; - auto trim = Expression::parseExpression(expCtx, + auto trim = Expression::parseExpression(&expCtx, BSON("$trim" << BSON("input" << " abc ")), - expCtx->variablesParseState); + expCtx.variablesParseState); ASSERT_VALUE_EQ(trim->serialize(false), trim->serialize(true)); ASSERT_VALUE_EQ( trim->serialize(false), @@ -729,25 +729,25 @@ TEST(ExpressionTrimTest, DoesSerializeCorrectly) { // Make sure we can re-parse it and evaluate it. auto reparsedTrim = Expression::parseExpression( - expCtx, trim->serialize(false).getDocument().toBson(), expCtx->variablesParseState); - ASSERT_VALUE_EQ(reparsedTrim->evaluate({}, &expCtx->variables), Value("abc"_sd)); + &expCtx, trim->serialize(false).getDocument().toBson(), expCtx.variablesParseState); + ASSERT_VALUE_EQ(reparsedTrim->evaluate({}, &expCtx.variables), Value("abc"_sd)); // Use $ltrim, and specify the 'chars' option. - trim = Expression::parseExpression(expCtx, + trim = Expression::parseExpression(&expCtx, BSON("$ltrim" << BSON("input" << "$inputField" << "chars" << "$$CURRENT.a")), - expCtx->variablesParseState); + expCtx.variablesParseState); ASSERT_VALUE_EQ( trim->serialize(false), Value(Document{{"$ltrim", Document{{"input", "$inputField"_sd}, {"chars", "$a"_sd}}}})); // Make sure we can re-parse it and evaluate it. reparsedTrim = Expression::parseExpression( - expCtx, trim->serialize(false).getDocument().toBson(), expCtx->variablesParseState); + &expCtx, trim->serialize(false).getDocument().toBson(), expCtx.variablesParseState); ASSERT_VALUE_EQ(reparsedTrim->evaluate(Document{{"inputField", " , 4"_sd}, {"a", " ,"_sd}}, - &expCtx->variables), + &expCtx.variables), Value("4"_sd)); } } // namespace Trim diff --git a/src/mongo/db/pipeline/expression_walker_test.cpp b/src/mongo/db/pipeline/expression_walker_test.cpp index 4c409a468b6..60185ad9834 100644 --- a/src/mongo/db/pipeline/expression_walker_test.cpp +++ b/src/mongo/db/pipeline/expression_walker_test.cpp @@ -58,7 +58,7 @@ protected: auto parseExpression(std::string expressionString) { return Expression::parseExpression( - getExpCtx(), fromjson(expressionString), getExpCtx()->variablesParseState); + getExpCtxRaw(), fromjson(expressionString), getExpCtx()->variablesParseState); } }; diff --git a/src/mongo/db/pipeline/make_js_function.cpp b/src/mongo/db/pipeline/make_js_function.cpp index 531f0bbab74..8cb1e0d32aa 100644 --- a/src/mongo/db/pipeline/make_js_function.cpp +++ b/src/mongo/db/pipeline/make_js_function.cpp @@ -35,8 +35,7 @@ namespace mongo { // Given a function represented as a string, constructs a JS execution context and attempts to parse // it as a JS function. -ScriptingFunction makeJsFunc(boost::intrusive_ptr<ExpressionContext> expCtx, - const std::string& func) { +ScriptingFunction makeJsFunc(ExpressionContext* const expCtx, const std::string& func) { auto jsExec = expCtx->getJsExecWithScope(); // default arg forceLoadOfStoredProcedures is false here. ScriptingFunction parsedFunc = jsExec->getScope()->createFunction(func.c_str()); diff --git a/src/mongo/db/pipeline/make_js_function.h b/src/mongo/db/pipeline/make_js_function.h index 7ae894256dc..9b36b23d9a6 100644 --- a/src/mongo/db/pipeline/make_js_function.h +++ b/src/mongo/db/pipeline/make_js_function.h @@ -37,7 +37,6 @@ namespace mongo { /** * Parses and returns an executable Javascript function. */ -ScriptingFunction makeJsFunc(boost::intrusive_ptr<ExpressionContext> expCtx, - const std::string& func); +ScriptingFunction makeJsFunc(ExpressionContext* const expCtx, const std::string& func); } // namespace mongo diff --git a/src/mongo/db/pipeline/sharded_union_test.cpp b/src/mongo/db/pipeline/sharded_union_test.cpp index 8756cb0c119..a3c0ad65af8 100644 --- a/src/mongo/db/pipeline/sharded_union_test.cpp +++ b/src/mongo/db/pipeline/sharded_union_test.cpp @@ -202,13 +202,14 @@ TEST_F(ShardedUnionTest, CorrectlySplitsSubPipelineIfRefreshedDistributionRequir auto&& parser = AccumulationStatement::getParser("$sum", boost::none); auto accumulatorArg = BSON("" << 1); auto sumStatement = - parser(expCtx(), accumulatorArg.firstElement(), expCtx()->variablesParseState); + parser(expCtx().get(), accumulatorArg.firstElement(), expCtx()->variablesParseState); AccumulationStatement countStatement{"count", sumStatement}; auto pipeline = Pipeline::create( {DocumentSourceMatch::create(fromjson("{_id: {$gte: 0}}"), expCtx()), - DocumentSourceGroup::create( - expCtx(), ExpressionConstant::create(expCtx(), Value(BSONNULL)), {countStatement})}, - expCtx()); + DocumentSourceGroup::create(expCtx(), + ExpressionConstant::create(expCtx().get(), Value(BSONNULL)), + {countStatement})}, + expCtx().get()); auto unionWith = DocumentSourceUnionWith(expCtx(), std::move(pipeline)); expCtx()->mongoProcessInterface = std::make_shared<ShardServerProcessInterface>(executor()); auto queue = DocumentSourceQueue::create(expCtx()); @@ -290,12 +291,13 @@ TEST_F(ShardedUnionTest, AvoidsSplittingSubPipelineIfRefreshedDistributionDoesNo auto&& parser = AccumulationStatement::getParser("$sum", boost::none); auto accumulatorArg = BSON("" << 1); auto sumStatement = - parser(expCtx(), accumulatorArg.firstElement(), expCtx()->variablesParseState); + parser(expCtx().get(), accumulatorArg.firstElement(), expCtx()->variablesParseState); AccumulationStatement countStatement{"count", sumStatement}; auto pipeline = Pipeline::create( - {DocumentSourceGroup::create( - expCtx(), ExpressionConstant::create(expCtx(), Value(BSONNULL)), {countStatement})}, - expCtx()); + {DocumentSourceGroup::create(expCtx(), + ExpressionConstant::create(expCtx().get(), Value(BSONNULL)), + {countStatement})}, + expCtx().get()); auto unionWith = DocumentSourceUnionWith(expCtx(), std::move(pipeline)); expCtx()->mongoProcessInterface = std::make_shared<ShardServerProcessInterface>(executor()); auto queue = DocumentSourceQueue::create(expCtx()); @@ -423,12 +425,13 @@ TEST_F(ShardedUnionTest, ForwardsReadConcernToRemotes) { auto&& parser = AccumulationStatement::getParser("$sum", boost::none); auto accumulatorArg = BSON("" << 1); auto sumExpression = - parser(expCtx(), accumulatorArg.firstElement(), expCtx()->variablesParseState); + parser(expCtx().get(), accumulatorArg.firstElement(), expCtx()->variablesParseState); AccumulationStatement countStatement{"count", sumExpression}; auto pipeline = Pipeline::create( - {DocumentSourceGroup::create( - expCtx(), ExpressionConstant::create(expCtx(), Value(BSONNULL)), {countStatement})}, - expCtx()); + {DocumentSourceGroup::create(expCtx(), + ExpressionConstant::create(expCtx().get(), Value(BSONNULL)), + {countStatement})}, + expCtx().get()); auto unionWith = DocumentSourceUnionWith(expCtx(), std::move(pipeline)); expCtx()->mongoProcessInterface = std::make_shared<ShardServerProcessInterface>(executor()); auto queue = DocumentSourceQueue::create(expCtx()); diff --git a/src/mongo/db/pipeline/variables.cpp b/src/mongo/db/pipeline/variables.cpp index 060bcda8fc4..b64ec45db00 100644 --- a/src/mongo/db/pipeline/variables.cpp +++ b/src/mongo/db/pipeline/variables.cpp @@ -239,7 +239,7 @@ BSONObj Variables::serializeLetParameters(const VariablesParseState& vps) const bob << kIdToBuiltinVarName.at(id) << value; return bob.appendElements(vps.serialize(*this)).obj(); } -void Variables::seedVariablesWithLetParameters(boost::intrusive_ptr<ExpressionContext> expCtx, +void Variables::seedVariablesWithLetParameters(ExpressionContext* const expCtx, const BSONObj letParams) { for (auto&& elem : letParams) { Variables::validateNameForUserWrite(elem.fieldName()); diff --git a/src/mongo/db/pipeline/variables.h b/src/mongo/db/pipeline/variables.h index b6ff28110d1..b868f51f4e0 100644 --- a/src/mongo/db/pipeline/variables.h +++ b/src/mongo/db/pipeline/variables.h @@ -169,7 +169,7 @@ public: /** * Seed let parameters with the given BSONObj. */ - void seedVariablesWithLetParameters(boost::intrusive_ptr<ExpressionContext> expCtx, + void seedVariablesWithLetParameters(ExpressionContext* const expCtx, const BSONObj letParameters); bool hasValue(Variables::Id id) const { diff --git a/src/mongo/db/query/canonical_query.h b/src/mongo/db/query/canonical_query.h index ca5199e3502..39a6ac8ec47 100644 --- a/src/mongo/db/query/canonical_query.h +++ b/src/mongo/db/query/canonical_query.h @@ -208,9 +208,12 @@ public: return _canHaveNoopMatchNodes; } - const boost::intrusive_ptr<ExpressionContext>& getExpCtx() const { + auto& getExpCtx() const { return _expCtx; } + auto getExpCtxRaw() const { + return _expCtx.get(); + } private: // You must go through canonicalize to create a CanonicalQuery. diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index dbbecb419b5..9a512acafdb 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -385,7 +385,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, "Collection {ns} does not exist. Using EOF plan: {canonicalQuery_Short}", "ns"_attr = ns, "canonicalQuery_Short"_attr = redact(canonicalQuery->toStringShort())); - root = std::make_unique<EOFStage>(canonicalQuery->getExpCtx().get()); + root = std::make_unique<EOFStage>(canonicalQuery->getExpCtxRaw()); return PrepareExecutionResult(std::move(canonicalQuery), nullptr, std::move(root)); } @@ -411,12 +411,12 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, "canonicalQuery_Short"_attr = redact(canonicalQuery->toStringShort())); root = std::make_unique<IDHackStage>( - canonicalQuery->getExpCtx().get(), canonicalQuery.get(), ws, descriptor); + canonicalQuery->getExpCtxRaw(), canonicalQuery.get(), ws, descriptor); // Might have to filter out orphaned docs. if (plannerParams.options & QueryPlannerParams::INCLUDE_SHARD_FILTER) { root = std::make_unique<ShardFilterStage>( - canonicalQuery->getExpCtx().get(), + canonicalQuery->getExpCtxRaw(), CollectionShardingState::get(opCtx, canonicalQuery->nss()) ->getOwnershipFilter( opCtx, @@ -430,7 +430,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, // Add a SortKeyGeneratorStage if the query requested sortKey metadata. if (canonicalQuery->metadataDeps()[DocumentMetadataFields::kSortKey]) { root = std::make_unique<SortKeyGeneratorStage>( - canonicalQuery->getExpCtx().get(), + canonicalQuery->getExpCtxRaw(), std::move(root), ws, canonicalQuery->getQueryRequest().getSort()); @@ -442,7 +442,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, // the exception the $meta sortKey projection, which can be used along with the // returnKey. root = std::make_unique<ReturnKeyStage>( - canonicalQuery->getExpCtx().get(), + canonicalQuery->getExpCtxRaw(), cqProjection ? QueryPlannerCommon::extractSortKeyMetaFieldsFromProjection(*cqProjection) : std::vector<FieldPath>{}, @@ -462,7 +462,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, std::move(root)); } else { root = std::make_unique<ProjectionStageSimple>( - canonicalQuery->getExpCtx().get(), + canonicalQuery->getExpCtxRaw(), canonicalQuery->getQueryRequest().getProj(), canonicalQuery->getProj(), ws, @@ -518,7 +518,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, // 'decisionWorks' is used to determine whether the existing cache entry should // be evicted, and the query replanned. auto cachedPlanStage = - std::make_unique<CachedPlanStage>(canonicalQuery->getExpCtx().get(), + std::make_unique<CachedPlanStage>(canonicalQuery->getExpCtxRaw(), collection, ws, canonicalQuery.get(), @@ -540,7 +540,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, "canonicalQuery_Short"_attr = redact(canonicalQuery->toStringShort())); root = std::make_unique<SubplanStage>( - canonicalQuery->getExpCtx().get(), collection, ws, plannerParams, canonicalQuery.get()); + canonicalQuery->getExpCtxRaw(), collection, ws, plannerParams, canonicalQuery.get()); return PrepareExecutionResult(std::move(canonicalQuery), nullptr, std::move(root)); } @@ -593,7 +593,7 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, // Many solutions. Create a MultiPlanStage to pick the best, update the cache, // and so on. The working set will be shared by all candidate plans. auto multiPlanStage = std::make_unique<MultiPlanStage>( - canonicalQuery->getExpCtx().get(), collection, canonicalQuery.get()); + canonicalQuery->getExpCtxRaw(), collection, canonicalQuery.get()); for (size_t ix = 0; ix < solutions.size(); ++ix) { if (solutions[ix]->cacheData.get()) { @@ -870,7 +870,7 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorDelete( invariant(root); root = std::make_unique<DeleteStage>( - cq->getExpCtx().get(), std::move(deleteStageParams), ws.get(), collection, root.release()); + cq->getExpCtxRaw(), std::move(deleteStageParams), ws.get(), collection, root.release()); if (projection) { root = std::make_unique<ProjectionStageDefault>( @@ -1037,12 +1037,11 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorUpdate( updateStageParams.canonicalQuery = cq.get(); const bool isUpsert = updateStageParams.request->isUpsert(); - root = - (isUpsert - ? std::make_unique<UpsertStage>( - cq->getExpCtx().get(), updateStageParams, ws.get(), collection, root.release()) - : std::make_unique<UpdateStage>( - cq->getExpCtx().get(), updateStageParams, ws.get(), collection, root.release())); + root = (isUpsert + ? std::make_unique<UpsertStage>( + cq->getExpCtxRaw(), updateStageParams, ws.get(), collection, root.release()) + : std::make_unique<UpdateStage>( + cq->getExpCtxRaw(), updateStageParams, ws.get(), collection, root.release())); if (projection) { root = std::make_unique<ProjectionStageDefault>( diff --git a/src/mongo/db/query/projection_parser.cpp b/src/mongo/db/query/projection_parser.cpp index 5d7d2517287..54f050b7353 100644 --- a/src/mongo/db/query/projection_parser.cpp +++ b/src/mongo/db/query/projection_parser.cpp @@ -295,7 +295,7 @@ bool attemptToParseGenericExpression(ParseContext* parseCtx, } auto expr = Expression::parseExpression( - parseCtx->expCtx, subObj, parseCtx->expCtx->variablesParseState); + parseCtx->expCtx.get(), subObj, parseCtx->expCtx->variablesParseState); addNodeAtPath(parent, path, std::make_unique<ExpressionASTNode>(expr)); parseCtx->hasMeta = parseCtx->hasMeta || isMeta; return true; @@ -468,7 +468,7 @@ void parseExclusion(ParseContext* ctx, BSONElement elem, ProjectionPathASTNode* void parseLiteral(ParseContext* ctx, BSONElement elem, ProjectionPathASTNode* parent) { verifyComputedFieldsAllowed(ctx->policies); - auto expr = Expression::parseOperand(ctx->expCtx, elem, ctx->expCtx->variablesParseState); + auto expr = Expression::parseOperand(ctx->expCtx.get(), elem, ctx->expCtx->variablesParseState); FieldPath pathFromParent(elem.fieldNameStringData()); addNodeAtPath(parent, pathFromParent, std::make_unique<ExpressionASTNode>(expr)); diff --git a/src/mongo/db/query/sort_pattern.cpp b/src/mongo/db/query/sort_pattern.cpp index 99590ba1275..a7fff3f9061 100644 --- a/src/mongo/db/query/sort_pattern.cpp +++ b/src/mongo/db/query/sort_pattern.cpp @@ -64,8 +64,8 @@ SortPattern::SortPattern(const BSONObj& obj, } else { uasserted(31138, str::stream() << "Illegal $meta sort: " << metaElem); } - patternPart.expression = - static_cast<ExpressionMeta*>(ExpressionMeta::parse(pExpCtx, metaElem, vps).get()); + patternPart.expression = static_cast<ExpressionMeta*>( + ExpressionMeta::parse(pExpCtx.get(), metaElem, vps).get()); // If sorting by textScore, sort highest scores first. If sorting by randVal, order // doesn't matter, so just always use descending. diff --git a/src/mongo/db/query/stage_builder.cpp b/src/mongo/db/query/stage_builder.cpp index 3b9dad99a0f..4434c97d928 100644 --- a/src/mongo/db/query/stage_builder.cpp +++ b/src/mongo/db/query/stage_builder.cpp @@ -74,7 +74,7 @@ std::unique_ptr<PlanStage> buildStages(OperationContext* opCtx, const QuerySolution& qsol, const QuerySolutionNode* root, WorkingSet* ws) { - auto* const expCtx = cq.getExpCtx().get(); + auto* const expCtx = cq.getExpCtxRaw(); switch (root->getType()) { case STAGE_COLLSCAN: { const CollectionScanNode* csn = static_cast<const CollectionScanNode*>(root); @@ -171,7 +171,7 @@ std::unique_ptr<PlanStage> buildStages(OperationContext* opCtx, case STAGE_PROJECTION_COVERED: { auto pn = static_cast<const ProjectionNodeCovered*>(root); auto childStage = buildStages(opCtx, collection, cq, qsol, pn->children[0], ws); - return std::make_unique<ProjectionStageCovered>(cq.getExpCtx().get(), + return std::make_unique<ProjectionStageCovered>(cq.getExpCtxRaw(), cq.getQueryRequest().getProj(), cq.getProj(), ws, @@ -181,7 +181,7 @@ std::unique_ptr<PlanStage> buildStages(OperationContext* opCtx, case STAGE_PROJECTION_SIMPLE: { auto pn = static_cast<const ProjectionNodeSimple*>(root); auto childStage = buildStages(opCtx, collection, cq, qsol, pn->children[0], ws); - return std::make_unique<ProjectionStageSimple>(cq.getExpCtx().get(), + return std::make_unique<ProjectionStageSimple>(cq.getExpCtxRaw(), cq.getQueryRequest().getProj(), cq.getProj(), ws, diff --git a/src/mongo/dbtests/query_plan_executor.cpp b/src/mongo/dbtests/query_plan_executor.cpp index fd7b3f6a111..15c069c04d8 100644 --- a/src/mongo/dbtests/query_plan_executor.cpp +++ b/src/mongo/dbtests/query_plan_executor.cpp @@ -116,7 +116,7 @@ public: // Make the stage. unique_ptr<PlanStage> root( - new CollectionScan(cq->getExpCtx().get(), coll, csparams, ws.get(), cq.get()->root())); + new CollectionScan(cq->getExpCtxRaw(), coll, csparams, ws.get(), cq.get()->root())); // Hand the plan off to the executor. auto statusWithPlanExecutor = |