diff options
author | Jacob Evans <jacob.evans@mongodb.com> | 2019-10-15 02:21:45 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-10-15 02:21:45 +0000 |
commit | fd3a1af42439bce510688051e0c820de13c7166f (patch) | |
tree | b4cd127268ba2184bede1db8915f0dc650c958fd /src | |
parent | d819272026fd1c21b9fb18ae692648cfa590aa68 (diff) | |
download | mongo-fd3a1af42439bce510688051e0c820de13c7166f.tar.gz |
SERVER-43796 Fix unittests and compile
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/pipeline/accumulator_js_test.cpp | 77 | ||||
-rw-r--r-- | src/mongo/db/pipeline/accumulator_test.cpp | 71 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_group_test.cpp | 47 |
3 files changed, 93 insertions, 102 deletions
diff --git a/src/mongo/db/pipeline/accumulator_js_test.cpp b/src/mongo/db/pipeline/accumulator_js_test.cpp index 7637388ca4b..8efb460cf27 100644 --- a/src/mongo/db/pipeline/accumulator_js_test.cpp +++ b/src/mongo/db/pipeline/accumulator_js_test.cpp @@ -75,25 +75,22 @@ void MapReduceFixture::tearDown() { namespace InternalJsReduce { -static void assertProcessFailsWithCode(std::string accumulatorName, - const boost::intrusive_ptr<ExpressionContext>& expCtx, +template <typename AccName> +static void assertProcessFailsWithCode(const boost::intrusive_ptr<ExpressionContext>& expCtx, Value processArgument, int code) { - auto factory = AccumulationStatement::getFactory(accumulatorName); - boost::intrusive_ptr<Accumulator> accum(factory(expCtx)); + auto accum = AccName::create(expCtx); ASSERT_THROWS_CODE(accum->process(processArgument, false), AssertionException, code); } -static void assertExpectedResults(std::string accumulatorName, - const boost::intrusive_ptr<ExpressionContext>& expCtx, +template <typename AccName> +static void assertExpectedResults(const boost::intrusive_ptr<ExpressionContext>& expCtx, std::string eval, std::vector<Value> data, Value expectedResult) { - auto factory = AccumulationStatement::getFactory(accumulatorName); - // Asserts that result equals expected result when not sharded. { - boost::intrusive_ptr<Accumulator> accum(factory(expCtx)); + auto accum = AccName::create(expCtx); for (auto&& val : data) { auto input = Value(DOC("eval" << eval << "data" << val)); accum->process(input, false); @@ -105,8 +102,8 @@ static void assertExpectedResults(std::string accumulatorName, // Asserts that result equals expected result when all input is on one shard. { - boost::intrusive_ptr<Accumulator> accum(factory(expCtx)); - boost::intrusive_ptr<Accumulator> shard(factory(expCtx)); + auto accum = AccName::create(expCtx); + auto shard = AccName::create(expCtx); for (auto&& val : data) { auto input = Value(DOC("eval" << eval << "data" << val)); shard->process(input, false); @@ -119,10 +116,10 @@ static void assertExpectedResults(std::string accumulatorName, // Asserts that result equals expected result when each input is on a separate shard. { - boost::intrusive_ptr<Accumulator> accum(factory(expCtx)); + auto accum = AccName::create(expCtx); for (auto&& val : data) { auto input = Value(DOC("eval" << eval << "data" << val)); - boost::intrusive_ptr<Accumulator> shard(factory(expCtx)); + auto shard = AccName::create(expCtx); shard->process(input, false); accum->process(shard->getValue(true), true); } @@ -134,23 +131,22 @@ static void assertExpectedResults(std::string accumulatorName, TEST_F(MapReduceFixture, InternalJsReduceProducesExpectedResults) { // Null value. - assertExpectedResults("$_internalJsReduce", - getExpCtx(), - "function(key, value) { return null; };", - {Value(DOC("k" << 1 << "v" << Value(BSONNULL)))}, - Value(BSONNULL)); + assertExpectedResults<AccumulatorInternalJsReduce>( + getExpCtx(), + "function(key, value) { return null; };", + {Value(DOC("k" << 1 << "v" << Value(BSONNULL)))}, + Value(BSONNULL)); // Multiple inputs. - assertExpectedResults("$_internalJsReduce", - getExpCtx(), - "function(key, values) { return Array.sum(values); };", - {Value(DOC("k" << std::string("foo") << "v" << Value(2))), - Value(DOC("k" << std::string("foo") << "v" << Value(5)))}, - Value(7.0)); + assertExpectedResults<AccumulatorInternalJsReduce>( + getExpCtx(), + "function(key, values) { return Array.sum(values); };", + {Value(DOC("k" << std::string("foo") << "v" << Value(2))), + Value(DOC("k" << std::string("foo") << "v" << Value(5)))}, + Value(7.0)); // Multiple inputs, numeric key. - assertExpectedResults( - "$_internalJsReduce", + assertExpectedResults<AccumulatorInternalJsReduce>( getExpCtx(), "function(key, values) { return Array.sum(values); };", {Value(DOC("k" << 1 << "v" << Value(2))), Value(DOC("k" << 1 << "v" << Value(5)))}, @@ -158,9 +154,7 @@ TEST_F(MapReduceFixture, InternalJsReduceProducesExpectedResults) { } TEST_F(MapReduceFixture, InternalJsReduceIdempotentOnlyWhenJSFunctionIsIdempotent) { - - auto factory = AccumulationStatement::getFactory("$_internalJsReduce"); - boost::intrusive_ptr<Accumulator> accum(factory(getExpCtx())); + auto accum = AccumulatorInternalJsReduce::create(getExpCtx()); // A non-idempotent Javascript function will produce non-idempotent results. In this case a // single document reduce causes a change in value. @@ -177,11 +171,9 @@ TEST_F(MapReduceFixture, InternalJsReduceIdempotentOnlyWhenJSFunctionIsIdempoten } TEST_F(MapReduceFixture, InternalJsReduceFailsWhenEvalContainsInvalidJavascript) { - auto factory = AccumulationStatement::getFactory("$_internalJsReduce"); - // Multiple source documents. { - boost::intrusive_ptr<Accumulator> accum(factory(getExpCtx())); + auto accum = AccumulatorInternalJsReduce::create(getExpCtx()); auto input = Value(DOC("eval" << std::string("INVALID_JAVASCRIPT") << "data" << Value(DOC("k" << Value(1) << "v" << Value(2))))); @@ -193,7 +185,7 @@ TEST_F(MapReduceFixture, InternalJsReduceFailsWhenEvalContainsInvalidJavascript) // Single source document. { - boost::intrusive_ptr<Accumulator> accum(factory(getExpCtx())); + auto accum = AccumulatorInternalJsReduce::create(getExpCtx()); auto input = Value(DOC("eval" << std::string("INVALID_JAVASCRIPT") << "data" << Value(DOC("k" << Value(1) << "v" << Value(2))))); @@ -206,24 +198,24 @@ TEST_F(MapReduceFixture, InternalJsReduceFailsWhenEvalContainsInvalidJavascript) TEST_F(MapReduceFixture, InternalJsReduceFailsIfArgumentNotDocument) { auto argument = Value(2); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31242); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31242); } TEST_F(MapReduceFixture, InternalJsReduceFailsIfEvalAndDataArgumentsNotProvided) { // Data argument missing. auto argument = Value(DOC("eval" << std::string("function(key, values) { return Array.sum(values); };"))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31243); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31243); // Eval argument missing. argument = Value(DOC("data" << Value(DOC("k" << Value(1) << "v" << Value(2))))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31243); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31243); } TEST_F(MapReduceFixture, InternalJsReduceFailsIfEvalArgumentNotOfTypeStringOrCode) { auto argument = Value( DOC("eval" << 1 << "data" << Value(DOC("k" << std::string("foo") << "v" << Value(2))))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31244); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31244); // MapReduce does not accept JavaScript function of BSON type CodeWScope. BSONObjBuilder objBuilder; @@ -231,14 +223,15 @@ TEST_F(MapReduceFixture, InternalJsReduceFailsIfEvalArgumentNotOfTypeStringOrCod "eval", "function(key, values) { return Array.sum(values); };", BSONObj()); objBuilder.append("data", BSON("k" << std::string("foo") << "v" << Value(2))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), Value(objBuilder.obj()), 31244); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>( + getExpCtx(), Value(objBuilder.obj()), 31244); } TEST_F(MapReduceFixture, InternalJsReduceFailsIfDataArgumentNotDocument) { auto argument = Value(DOC("eval" << std::string("function(key, values) { return Array.sum(values); };") << "data" << Value(2))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31245); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31245); } TEST_F(MapReduceFixture, InternalJsReduceFailsIfDataArgumentDoesNotContainExpectedFields) { @@ -246,19 +239,19 @@ TEST_F(MapReduceFixture, InternalJsReduceFailsIfDataArgumentDoesNotContainExpect auto argument = Value( DOC("eval" << std::string("function(key, values) { return Array.sum(values); };") << "data" << Value(DOC("foo" << std::string("keyVal") << "v" << Value(2))))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31251); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31251); // No "v" field. argument = Value( DOC("eval" << std::string("function(key, values) { return Array.sum(values); };") << "data" << Value(DOC("k" << std::string("keyVal") << "bar" << Value(2))))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31251); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31251); // Both "k" and "v" fields missing. argument = Value(DOC("eval" << std::string("function(key, values) { return Array.sum(values); };") << "data" << Value(Document()))); - assertProcessFailsWithCode("$_internalJsReduce", getExpCtx(), argument, 31251); + assertProcessFailsWithCode<AccumulatorInternalJsReduce>(getExpCtx(), argument, 31251); } } // namespace InternalJsReduce diff --git a/src/mongo/db/pipeline/accumulator_test.cpp b/src/mongo/db/pipeline/accumulator_test.cpp index ec4b88eae37..14f9f74eda8 100644 --- a/src/mongo/db/pipeline/accumulator_test.cpp +++ b/src/mongo/db/pipeline/accumulator_test.cpp @@ -46,20 +46,19 @@ using std::numeric_limits; using std::string; /** - * Takes the name of an Accumulator as its first argument and a list of pairs of arguments and + * Takes the name of an Accumulator as its template argument and a list of pairs of arguments and * expected results as its second argument, and asserts that for the given Accumulator the arguments * evaluate to the expected results. */ +template <typename AccName> static void assertExpectedResults( - std::string accumulatorName, const intrusive_ptr<ExpressionContext>& expCtx, std::initializer_list<std::pair<std::vector<Value>, Value>> operations) { - auto factory = AccumulationStatement::getFactory(accumulatorName); for (auto&& op : operations) { try { // Asserts that result equals expected result when not sharded. { - boost::intrusive_ptr<Accumulator> accum(factory(expCtx)); + auto accum = AccName::create(expCtx); for (auto&& val : op.first) { accum->process(val, false); } @@ -70,8 +69,8 @@ static void assertExpectedResults( // Asserts that result equals expected result when all input is on one shard. { - boost::intrusive_ptr<Accumulator> accum(factory(expCtx)); - boost::intrusive_ptr<Accumulator> shard(factory(expCtx)); + auto accum = AccName::create(expCtx); + auto shard = AccName::create(expCtx); for (auto&& val : op.first) { shard->process(val, false); } @@ -83,9 +82,9 @@ static void assertExpectedResults( // Asserts that result equals expected result when each input is on a separate shard. { - boost::intrusive_ptr<Accumulator> accum(factory(expCtx)); + auto accum = AccName::create(expCtx); for (auto&& val : op.first) { - boost::intrusive_ptr<Accumulator> shard(factory(expCtx)); + auto shard = AccName::create(expCtx); shard->process(val, false); accum->process(shard->getValue(true), true); } @@ -102,8 +101,7 @@ static void assertExpectedResults( TEST(Accumulators, Avg) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults( - "$avg", + assertExpectedResults<AccumulatorAvg>( expCtx, { // No documents evaluated. @@ -158,8 +156,7 @@ TEST(Accumulators, Avg) { TEST(Accumulators, First) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults( - "$first", + assertExpectedResults<AccumulatorFirst>( expCtx, {// No documents evaluated. {{}, Value()}, @@ -177,8 +174,7 @@ TEST(Accumulators, First) { TEST(Accumulators, Last) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults( - "$last", + assertExpectedResults<AccumulatorLast>( expCtx, {// No documents evaluated. {{}, Value()}, @@ -196,8 +192,7 @@ TEST(Accumulators, Last) { TEST(Accumulators, Min) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults( - "$min", + assertExpectedResults<AccumulatorMin>( expCtx, {// No documents evaluated. {{}, Value(BSONNULL)}, @@ -217,13 +212,13 @@ TEST(Accumulators, MinRespectsCollation) { intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); expCtx->setCollator(&collator); - assertExpectedResults("$min", expCtx, {{{Value("abc"_sd), Value("cba"_sd)}, Value("cba"_sd)}}); + assertExpectedResults<AccumulatorMin>(expCtx, + {{{Value("abc"_sd), Value("cba"_sd)}, Value("cba"_sd)}}); } TEST(Accumulators, Max) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults( - "$max", + assertExpectedResults<AccumulatorMax>( expCtx, {// No documents evaluated. {{}, Value(BSONNULL)}, @@ -243,13 +238,13 @@ TEST(Accumulators, MaxRespectsCollation) { intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); expCtx->setCollator(&collator); - assertExpectedResults("$max", expCtx, {{{Value("abc"_sd), Value("cba"_sd)}, Value("abc"_sd)}}); + assertExpectedResults<AccumulatorMax>(expCtx, + {{{Value("abc"_sd), Value("cba"_sd)}, Value("abc"_sd)}}); } TEST(Accumulators, Sum) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults( - "$sum", + assertExpectedResults<AccumulatorSum>( expCtx, {// No documents evaluated. {{}, Value(0)}, @@ -340,48 +335,42 @@ TEST(Accumulators, AddToSetRespectsCollation) { intrusive_ptr<ExpressionContextForTest> expCtx(new ExpressionContextForTest()); CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual); expCtx->setCollator(&collator); - assertExpectedResults("$addToSet", - expCtx, - {{{Value("a"_sd), Value("b"_sd), Value("c"_sd)}, - Value(std::vector<Value>{Value("a"_sd)})}}); + assertExpectedResults<AccumulatorAddToSet>(expCtx, + {{{Value("a"_sd), Value("b"_sd), Value("c"_sd)}, + Value(std::vector<Value>{Value("a"_sd)})}}); } /* ------------------------- AccumulatorMergeObjects -------------------------- */ -namespace AccumulatorMergeObjects { - TEST(AccumulatorMergeObjects, MergingZeroObjectsShouldReturnEmptyDocument) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults("$mergeObjects", expCtx, {{{}, {Value(Document({}))}}}); + assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{}, {Value(Document({}))}}}); } TEST(AccumulatorMergeObjects, MergingWithSingleObjectShouldLeaveUnchanged) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); - assertExpectedResults("$mergeObjects", expCtx, {{{}, {Value(Document({}))}}}); + assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{}, {Value(Document({}))}}}); auto doc = Value(Document({{"a", 1}, {"b", 1}})); - assertExpectedResults("$mergeObjects", expCtx, {{{doc}, doc}}); + assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{doc}, doc}}); } TEST(AccumulatorMergeObjects, MergingDisjointObjectsShouldIncludeAllFields) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); auto first = Value(Document({{"a", 1}, {"b", 1}})); auto second = Value(Document({{"c", 1}})); - assertExpectedResults("$mergeObjects", - expCtx, - {{{first, second}, Value(Document({{"a", 1}, {"b", 1}, {"c", 1}}))}}); + assertExpectedResults<AccumulatorMergeObjects>( + expCtx, {{{first, second}, Value(Document({{"a", 1}, {"b", 1}, {"c", 1}}))}}); } TEST(AccumulatorMergeObjects, MergingIntersectingObjectsShouldOverrideInOrderReceived) { intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest()); auto first = Value(Document({{"a", "oldValue"_sd}, {"b", 0}, {"c", 1}})); auto second = Value(Document({{"a", "newValue"_sd}})); - assertExpectedResults( - "$mergeObjects", - expCtx, - {{{first, second}, Value(Document({{"a", "newValue"_sd}, {"b", 0}, {"c", 1}}))}}); + assertExpectedResults<AccumulatorMergeObjects>( + expCtx, {{{first, second}, Value(Document({{"a", "newValue"_sd}, {"b", 0}, {"c", 1}}))}}); } TEST(AccumulatorMergeObjects, MergingIntersectingEmbeddedObjectsShouldOverrideInOrderReceived) { @@ -391,7 +380,7 @@ TEST(AccumulatorMergeObjects, MergingIntersectingEmbeddedObjectsShouldOverrideIn auto first = Value(Document({{"d", 1}, {"subDoc", firstSubDoc}})); auto second = Value(Document({{"subDoc", secondSubDoc}})); auto expected = Value(Document({{"d", 1}, {"subDoc", secondSubDoc}})); - assertExpectedResults("$mergeObjects", expCtx, {{{first, second}, expected}}); + assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{first, second}, expected}}); } TEST(AccumulatorMergeObjects, MergingWithEmptyDocumentShouldIgnore) { @@ -399,9 +388,7 @@ TEST(AccumulatorMergeObjects, MergingWithEmptyDocumentShouldIgnore) { 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("$mergeObjects", expCtx, {{{first, second}, expected}}); + assertExpectedResults<AccumulatorMergeObjects>(expCtx, {{{first, second}, expected}}); } -} // namespace AccumulatorMergeObjects - } // namespace AccumulatorTests diff --git a/src/mongo/db/pipeline/document_source_group_test.cpp b/src/mongo/db/pipeline/document_source_group_test.cpp index e2fdfe4f107..a2ed4358248 100644 --- a/src/mongo/db/pipeline/document_source_group_test.cpp +++ b/src/mongo/db/pipeline/document_source_group_test.cpp @@ -73,9 +73,11 @@ TEST_F(DocumentSourceGroupTest, ShouldBeAbleToPauseLoading) { auto expCtx = getExpCtx(); expCtx->inMongos = true; // Disallow external sort. // This is the only way to do this in a debug build. - AccumulationStatement countStatement{"count", - ExpressionConstant::create(expCtx, Value(1)), - AccumulationStatement::getFactory("$sum")}; + auto&& parser = AccumulationStatement::getParser("$sum"); + auto accumulatorArg = BSON("" << 1); + auto [expression, factory] = + parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + AccumulationStatement countStatement{"count", expression, factory}; auto group = DocumentSourceGroup::create( expCtx, ExpressionConstant::create(expCtx, Value(BSONNULL)), {countStatement}); auto mock = @@ -108,11 +110,14 @@ TEST_F(DocumentSourceGroupTest, ShouldBeAbleToPauseLoadingWhileSpilled) { expCtx->allowDiskUse = true; const size_t maxMemoryUsageBytes = 1000; - VariablesParseState vps = expCtx->variablesParseState; - AccumulationStatement pushStatement{"spaceHog", - ExpressionFieldPath::parse(expCtx, "$largeStr", vps), - AccumulationStatement::getFactory("$push")}; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$_id", vps); + auto&& parser = AccumulationStatement::getParser("$push"); + auto accumulatorArg = BSON("" + << "$largeStr"); + auto [expression, factory] = + parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + AccumulationStatement pushStatement{"spaceHog", expression, factory}; + auto groupByExpression = + ExpressionFieldPath::parse(expCtx, "$_id", expCtx->variablesParseState); auto group = DocumentSourceGroup::create( expCtx, groupByExpression, {pushStatement}, maxMemoryUsageBytes); @@ -148,11 +153,14 @@ TEST_F(DocumentSourceGroupTest, ShouldErrorIfNotAllowedToSpillToDiskAndResultSet expCtx->inMongos = true; // Disallow external sort. // This is the only way to do this in a debug build. - VariablesParseState vps = expCtx->variablesParseState; - AccumulationStatement pushStatement{"spaceHog", - ExpressionFieldPath::parse(expCtx, "$largeStr", vps), - AccumulationStatement::getFactory("$push")}; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$_id", vps); + auto&& parser = AccumulationStatement::getParser("$push"); + auto accumulatorArg = BSON("" + << "$largeStr"); + auto [expression, factory] = + parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + AccumulationStatement pushStatement{"spaceHog", expression, factory}; + auto groupByExpression = + ExpressionFieldPath::parse(expCtx, "$_id", expCtx->variablesParseState); auto group = DocumentSourceGroup::create( expCtx, groupByExpression, {pushStatement}, maxMemoryUsageBytes); @@ -170,11 +178,14 @@ TEST_F(DocumentSourceGroupTest, ShouldCorrectlyTrackMemoryUsageBetweenPauses) { expCtx->inMongos = true; // Disallow external sort. // This is the only way to do this in a debug build. - VariablesParseState vps = expCtx->variablesParseState; - AccumulationStatement pushStatement{"spaceHog", - ExpressionFieldPath::parse(expCtx, "$largeStr", vps), - AccumulationStatement::getFactory("$push")}; - auto groupByExpression = ExpressionFieldPath::parse(expCtx, "$_id", vps); + auto&& parser = AccumulationStatement::getParser("$push"); + auto accumulatorArg = BSON("" + << "$largeStr"); + auto [expression, factory] = + parser(expCtx, accumulatorArg.firstElement(), expCtx->variablesParseState); + AccumulationStatement pushStatement{"spaceHog", expression, factory}; + auto groupByExpression = + ExpressionFieldPath::parse(expCtx, "$_id", expCtx->variablesParseState); auto group = DocumentSourceGroup::create( expCtx, groupByExpression, {pushStatement}, maxMemoryUsageBytes); |