diff options
Diffstat (limited to 'src/mongo/db/pipeline/pipeline_test.cpp')
-rw-r--r-- | src/mongo/db/pipeline/pipeline_test.cpp | 210 |
1 files changed, 114 insertions, 96 deletions
diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index 41cd6e567d3..dba575017ce 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -39,7 +39,7 @@ #include "mongo/db/pipeline/document_source.h" #include "mongo/db/pipeline/document_source_mock.h" #include "mongo/db/pipeline/document_value_test_util.h" -#include "mongo/db/pipeline/expression_context.h" +#include "mongo/db/pipeline/expression_context_for_test.h" #include "mongo/db/pipeline/field_path.h" #include "mongo/db/pipeline/pipeline.h" #include "mongo/db/query/collation/collator_interface_mock.h" @@ -86,7 +86,14 @@ public: rawPipeline.push_back(stageElem.embeddedObject()); } AggregationRequest request(NamespaceString("a.collection"), rawPipeline); - intrusive_ptr<ExpressionContext> ctx = new ExpressionContext(&_opCtx, request); + intrusive_ptr<ExpressionContextForTest> ctx = + new ExpressionContextForTest(&_opCtx, request); + + // For $graphLookup and $lookup, we have to populate the resolvedNamespaces so that the + // operations will be able to have a resolved view definition. + NamespaceString lookupCollNs("a", "lookupColl"); + ctx->setResolvedNamespace(lookupCollNs, {lookupCollNs, std::vector<BSONObj>{}}); + auto outputPipe = uassertStatusOK(Pipeline::parse(request.getPipeline(), ctx)); outputPipe->optimizePipeline(); @@ -240,17 +247,17 @@ class MoveMatchBeforeSort : public Base { class LookupShouldCoalesceWithUnwindOnAs : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same'}}" "]"; } string outputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right', unwinding: {preserveNullAndEmptyArrays: false}}}]"; } string serializedPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same'}}" "]"; @@ -259,17 +266,17 @@ class LookupShouldCoalesceWithUnwindOnAs : public Base { class LookupShouldCoalesceWithUnwindOnAsWithPreserveEmpty : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same', preserveNullAndEmptyArrays: true}}" "]"; } string outputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right', unwinding: {preserveNullAndEmptyArrays: true}}}]"; } string serializedPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same', preserveNullAndEmptyArrays: true}}" "]"; @@ -278,18 +285,18 @@ class LookupShouldCoalesceWithUnwindOnAsWithPreserveEmpty : public Base { class LookupShouldCoalesceWithUnwindOnAsWithIncludeArrayIndex : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same', includeArrayIndex: 'index'}}" "]"; } string outputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right', unwinding: {preserveNullAndEmptyArrays: false, includeArrayIndex: " "'index'}}}]"; } string serializedPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same', includeArrayIndex: 'index'}}" "]"; @@ -298,13 +305,13 @@ class LookupShouldCoalesceWithUnwindOnAsWithIncludeArrayIndex : public Base { class LookupShouldNotCoalesceWithUnwindNotOnAs : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$from'}}" "]"; } string outputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$from'}}" "]"; @@ -313,51 +320,59 @@ class LookupShouldNotCoalesceWithUnwindNotOnAs : public Base { class LookupShouldSwapWithMatch : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$match: {'independent': 0}}]"; } string outputPipeJson() { return "[{$match: {independent: 0}}, " - " {$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}]"; + " {$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}]"; } }; class LookupShouldSplitMatch : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$match: {'independent': 0, asField: {$eq: 3}}}]"; } string outputPipeJson() { return "[{$match: {independent: {$eq: 0}}}, " - " {$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + " {$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$match: {asField: {$eq: 3}}}]"; } }; class LookupShouldNotAbsorbMatchOnAs : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$match: {'asField.subfield': 0}}]"; } string outputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$match: {'asField.subfield': 0}}]"; } }; class LookupShouldAbsorbUnwindMatch : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " "{$unwind: '$asField'}, " "{$match: {'asField.subfield': {$eq: 1}}}]"; } string outputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z', " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: 'z', " " unwinding: {preserveNullAndEmptyArrays: false}, " " matching: {subfield: {$eq: 1}}}}]"; } string serializedPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " "{$unwind: {path: '$asField'}}, " "{$match: {'asField.subfield': {$eq: 1}}}]"; } @@ -365,14 +380,15 @@ class LookupShouldAbsorbUnwindMatch : public Base { class LookupShouldAbsorbUnwindAndSplitAndAbsorbMatch : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: '$asField'}, " " {$match: {'asField.subfield': {$eq: 1}, independentField: {$gt: 2}}}]"; } string outputPipeJson() { return "[{$match: {independentField: {$gt: 2}}}, " " {$lookup: { " - " from: 'foo', " + " from: 'lookupColl', " " as: 'asField', " " localField: 'y', " " foreignField: 'z', " @@ -386,7 +402,8 @@ class LookupShouldAbsorbUnwindAndSplitAndAbsorbMatch : public Base { } string serializedPipeJson() { return "[{$match: {independentField: {$gt: 2}}}, " - " {$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + " {$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: {path: '$asField'}}, " " {$match: {'asField.subfield': {$eq: 1}}}]"; } @@ -397,19 +414,21 @@ class LookupShouldNotSplitIndependentAndDependentOrClauses : public Base { // the $lookup, and if any child of the $or is independent of the 'asField', then the $match // cannot be absorbed by the $lookup. string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: '$asField'}, " " {$match: {$or: [{'independent': {$gt: 4}}, " " {'asField.dependent': {$elemMatch: {a: {$eq: 1}}}}]}}]"; } string outputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z', " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: 'z', " " unwinding: {preserveNullAndEmptyArrays: false}}}, " " {$match: {$or: [{'independent': {$gt: 4}}, " " {'asField.dependent': {$elemMatch: {a: {$eq: 1}}}}]}}]"; } string serializedPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: {path: '$asField'}}, " " {$match: {$or: [{'independent': {$gt: 4}}, " " {'asField.dependent': {$elemMatch: {a: {$eq: 1}}}}]}}]"; @@ -418,14 +437,15 @@ class LookupShouldNotSplitIndependentAndDependentOrClauses : public Base { class LookupWithMatchOnArrayIndexFieldShouldNotCoalesce : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: {path: '$asField', includeArrayIndex: 'index'}}, " " {$match: {index: 0, 'asField.value': {$gt: 0}, independent: 1}}]"; } string outputPipeJson() { return "[{$match: {independent: {$eq: 1}}}, " " {$lookup: { " - " from: 'foo', " + " from: 'lookupColl', " " as: 'asField', " " localField: 'y', " " foreignField: 'z', " @@ -438,7 +458,8 @@ class LookupWithMatchOnArrayIndexFieldShouldNotCoalesce : public Base { } string serializedPipeJson() { return "[{$match: {independent: {$eq: 1}}}, " - " {$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + " {$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: {path: '$asField', includeArrayIndex: 'index'}}, " " {$match: {$and: [{index: {$eq: 0}}, {'asField.value': {$gt: 0}}]}}]"; } @@ -446,14 +467,15 @@ class LookupWithMatchOnArrayIndexFieldShouldNotCoalesce : public Base { class LookupWithUnwindPreservingNullAndEmptyArraysShouldNotCoalesce : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: {path: '$asField', preserveNullAndEmptyArrays: true}}, " " {$match: {'asField.value': {$gt: 0}, independent: 1}}]"; } string outputPipeJson() { return "[{$match: {independent: {$eq: 1}}}, " " {$lookup: { " - " from: 'foo', " + " from: 'lookupColl', " " as: 'asField', " " localField: 'y', " " foreignField: 'z', " @@ -465,7 +487,8 @@ class LookupWithUnwindPreservingNullAndEmptyArraysShouldNotCoalesce : public Bas } string serializedPipeJson() { return "[{$match: {independent: {$eq: 1}}}, " - " {$lookup: {from: 'foo', as: 'asField', localField: 'y', foreignField: 'z'}}, " + " {$lookup: {from: 'lookupColl', as: 'asField', localField: 'y', foreignField: " + "'z'}}, " " {$unwind: {path: '$asField', preserveNullAndEmptyArrays: true}}, " " {$match: {'asField.value': {$gt: 0}}}]"; } @@ -473,13 +496,13 @@ class LookupWithUnwindPreservingNullAndEmptyArraysShouldNotCoalesce : public Bas class LookupDoesNotAbsorbElemMatch : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}, " " {$unwind: '$x'}, " " {$match: {x: {$elemMatch: {a: 1}}}}]"; } string outputPipeJson() { return "[{$lookup: { " - " from: 'foo', " + " from: 'lookupColl', " " as: 'x', " " localField: 'y', " " foreignField: 'z', " @@ -491,7 +514,7 @@ class LookupDoesNotAbsorbElemMatch : public Base { " {$match: {x: {$elemMatch: {a: 1}}}}]"; } string serializedPipeJson() { - return "[{$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}, " " {$unwind: {path: '$x'}}, " " {$match: {x: {$elemMatch: {a: 1}}}}]"; } @@ -499,35 +522,35 @@ class LookupDoesNotAbsorbElemMatch : public Base { class LookupDoesSwapWithMatchOnLocalField : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}, " " {$match: {y: {$eq: 3}}}]"; } string outputPipeJson() { return "[{$match: {y: {$eq: 3}}}, " - " {$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}]"; + " {$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}]"; } }; class LookupDoesSwapWithMatchOnFieldWithSameNameAsForeignField : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}, " " {$match: {z: {$eq: 3}}}]"; } string outputPipeJson() { return "[{$match: {z: {$eq: 3}}}, " - " {$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}]"; + " {$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}]"; } }; class LookupDoesNotAbsorbUnwindOnSubfieldOfAsButStillMovesMatch : public Base { string inputPipeJson() { - return "[{$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}, " + return "[{$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}, " " {$unwind: {path: '$x.subfield'}}, " " {$match: {'independent': 2, 'x.dependent': 2}}]"; } string outputPipeJson() { return "[{$match: {'independent': {$eq: 2}}}, " - " {$lookup: {from: 'foo', as: 'x', localField: 'y', foreignField: 'z'}}, " + " {$lookup: {from: 'lookupColl', as: 'x', localField: 'y', foreignField: 'z'}}, " " {$match: {'x.dependent': {$eq: 2}}}, " " {$unwind: {path: '$x.subfield'}}]"; } @@ -639,58 +662,61 @@ class UnwindBeforeDoubleMatchShouldRepeatedlyOptimize : public Base { class GraphLookupShouldCoalesceWithUnwindOnAs : public Base { string inputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d'}}, " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d'}}, " " {$unwind: '$out'}]"; } string outputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d', unwinding: {preserveNullAndEmptyArrays: " - "false}}}]"; + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d', " + " unwinding: {preserveNullAndEmptyArrays: false}}}]"; } string serializedPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d'}}, " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d'}}, " " {$unwind: {path: '$out'}}]"; } }; class GraphLookupShouldCoalesceWithUnwindOnAsWithPreserveEmpty : public Base { string inputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d'}}, " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d'}}, " " {$unwind: {path: '$out', preserveNullAndEmptyArrays: true}}]"; } string outputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d', unwinding: {preserveNullAndEmptyArrays: true}}}]"; + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d', " + " unwinding: {preserveNullAndEmptyArrays: true}}}]"; } string serializedPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d'}}, " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d'}}, " " {$unwind: {path: '$out', preserveNullAndEmptyArrays: true}}]"; } }; class GraphLookupShouldCoalesceWithUnwindOnAsWithIncludeArrayIndex : public Base { string inputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d'}}, " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d'}}, " " {$unwind: {path: '$out', includeArrayIndex: 'index'}}]"; } string outputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d', unwinding: {preserveNullAndEmptyArrays: false, " - " includeArrayIndex: 'index'}}}]"; + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d', " + " unwinding: {preserveNullAndEmptyArrays: false, " + " includeArrayIndex: 'index'}}}]"; } string serializedPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', " " startWith: '$d'}}, " " {$unwind: {path: '$out', includeArrayIndex: 'index'}}]"; } @@ -698,14 +724,14 @@ class GraphLookupShouldCoalesceWithUnwindOnAsWithIncludeArrayIndex : public Base class GraphLookupShouldNotCoalesceWithUnwindNotOnAs : public Base { string inputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d'}}, " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d'}}, " " {$unwind: '$nottherightthing'}]"; } string outputPipeJson() final { - return "[{$graphLookup: {from: 'a', as: 'out', connectToField: 'b', connectFromField: 'c', " - " startWith: '$d'}}, " + return "[{$graphLookup: {from: 'lookupColl', as: 'out', connectToField: 'b', " + " connectFromField: 'c', startWith: '$d'}}, " " {$unwind: {path: '$nottherightthing'}}]"; } }; @@ -713,7 +739,7 @@ class GraphLookupShouldNotCoalesceWithUnwindNotOnAs : public Base { class GraphLookupShouldSwapWithMatch : public Base { string inputPipeJson() { return "[{$graphLookup: {" - " from: 'coll2'," + " from: 'lookupColl'," " as: 'results'," " connectToField: 'to'," " connectFromField: 'from'," @@ -725,7 +751,7 @@ class GraphLookupShouldSwapWithMatch : public Base { string outputPipeJson() { return "[{$match: {independent: 'x'}}," " {$graphLookup: {" - " from: 'coll2'," + " from: 'lookupColl'," " as: 'results'," " connectToField: 'to'," " connectFromField: 'from'," @@ -863,7 +889,14 @@ public: rawPipeline.push_back(stageElem.embeddedObject()); } AggregationRequest request(NamespaceString("a.collection"), rawPipeline); - intrusive_ptr<ExpressionContext> ctx = new ExpressionContext(&_opCtx, request); + intrusive_ptr<ExpressionContextForTest> ctx = + new ExpressionContextForTest(&_opCtx, request); + + // For $graphLookup and $lookup, we have to populate the resolvedNamespaces so that the + // operations will be able to have a resolved view definition. + NamespaceString lookupCollNs("a", "lookupColl"); + ctx->setResolvedNamespace(lookupCollNs, {lookupCollNs, std::vector<BSONObj>{}}); + mergePipe = uassertStatusOK(Pipeline::parse(request.getPipeline(), ctx)); mergePipe->optimizePipeline(); @@ -1057,7 +1090,7 @@ namespace coalesceLookUpAndUnwind { class ShouldCoalesceUnwindOnAs : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same'}}" "]"; @@ -1066,14 +1099,14 @@ class ShouldCoalesceUnwindOnAs : public Base { return "[]"; } string mergePipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right', unwinding: {preserveNullAndEmptyArrays: false}}}]"; } }; class ShouldCoalesceUnwindOnAsWithPreserveEmpty : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same', preserveNullAndEmptyArrays: true}}" "]"; @@ -1082,14 +1115,14 @@ class ShouldCoalesceUnwindOnAsWithPreserveEmpty : public Base { return "[]"; } string mergePipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right', unwinding: {preserveNullAndEmptyArrays: true}}}]"; } }; class ShouldCoalesceUnwindOnAsWithIncludeArrayIndex : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$same', includeArrayIndex: 'index'}}" "]"; @@ -1098,7 +1131,7 @@ class ShouldCoalesceUnwindOnAsWithIncludeArrayIndex : public Base { return "[]"; } string mergePipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right', unwinding: {preserveNullAndEmptyArrays: false, includeArrayIndex: " "'index'}}}]"; } @@ -1106,7 +1139,7 @@ class ShouldCoalesceUnwindOnAsWithIncludeArrayIndex : public Base { class ShouldNotCoalesceUnwindNotOnAs : public Base { string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$from'}}" "]"; @@ -1115,7 +1148,7 @@ class ShouldNotCoalesceUnwindNotOnAs : public Base { return "[]"; } string mergePipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}" ",{$unwind: {path: '$from'}}" "]"; @@ -1170,14 +1203,14 @@ class LookUp : public needsPrimaryShardMergerBase { return true; } string inputPipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}]"; } string shardPipeJson() { return "[]"; } string mergePipeJson() { - return "[{$lookup: {from : 'coll2', as : 'same', localField: 'left', foreignField: " + return "[{$lookup: {from : 'lookupColl', as : 'same', localField: 'left', foreignField: " "'right'}}]"; } }; @@ -1192,7 +1225,7 @@ TEST(PipelineInitialSource, GeoNearInitialQuery) { OperationContextNoop _opCtx; const std::vector<BSONObj> rawPipeline = { fromjson("{$geoNear: {distanceField: 'd', near: [0, 0], query: {a: 1}}}")}; - intrusive_ptr<ExpressionContext> ctx = new ExpressionContext( + intrusive_ptr<ExpressionContextForTest> ctx = new ExpressionContextForTest( &_opCtx, AggregationRequest(NamespaceString("a.collection"), rawPipeline)); auto pipe = uassertStatusOK(Pipeline::parse(rawPipeline, ctx)); ASSERT_BSONOBJ_EQ(pipe->getInitialQuery(), BSON("a" << 1)); @@ -1201,28 +1234,13 @@ TEST(PipelineInitialSource, GeoNearInitialQuery) { TEST(PipelineInitialSource, MatchInitialQuery) { OperationContextNoop _opCtx; const std::vector<BSONObj> rawPipeline = {fromjson("{$match: {'a': 4}}")}; - intrusive_ptr<ExpressionContext> ctx = new ExpressionContext( + intrusive_ptr<ExpressionContextForTest> ctx = new ExpressionContextForTest( &_opCtx, AggregationRequest(NamespaceString("a.collection"), rawPipeline)); auto pipe = uassertStatusOK(Pipeline::parse(rawPipeline, ctx)); ASSERT_BSONOBJ_EQ(pipe->getInitialQuery(), BSON("a" << 4)); } -TEST(PipelineInitialSource, ParseCollation) { - QueryTestServiceContext serviceContext; - auto opCtx = serviceContext.makeOperationContext(); - - const BSONObj inputBson = - fromjson("{pipeline: [{$match: {a: 'abc'}}], collation: {locale: 'reverse'}}"); - auto request = AggregationRequest::parseFromBSON(NamespaceString("a.collection"), inputBson); - ASSERT_OK(request.getStatus()); - - intrusive_ptr<ExpressionContext> ctx = new ExpressionContext(opCtx.get(), request.getValue()); - ASSERT(ctx->getCollator()); - CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString); - ASSERT_TRUE(CollatorInterface::collatorsMatch(ctx->getCollator(), &collator)); -} - namespace Dependencies { using PipelineDependenciesTest = AggregationContextFixture; |