diff options
author | James Wahlin <james@mongodb.com> | 2017-05-25 16:34:41 -0400 |
---|---|---|
committer | James Wahlin <james@mongodb.com> | 2017-06-05 15:19:44 -0400 |
commit | cc6f3af6e1361c62f04a10596e86e651e1226525 (patch) | |
tree | 412eb486170f5dd3e009aa136994cabfde4736cc /src/mongo/db/pipeline/document_source_lookup_test.cpp | |
parent | 2daa02b7294412f2d5f2b7f224ef94f290f12f12 (diff) | |
download | mongo-cc6f3af6e1361c62f04a10596e86e651e1226525.tar.gz |
SERVER-29073 Allow variable definition within $lookup
Diffstat (limited to 'src/mongo/db/pipeline/document_source_lookup_test.cpp')
-rw-r--r-- | src/mongo/db/pipeline/document_source_lookup_test.cpp | 106 |
1 files changed, 104 insertions, 2 deletions
diff --git a/src/mongo/db/pipeline/document_source_lookup_test.cpp b/src/mongo/db/pipeline/document_source_lookup_test.cpp index e43d8efb5b6..9398473da5a 100644 --- a/src/mongo/db/pipeline/document_source_lookup_test.cpp +++ b/src/mongo/db/pipeline/document_source_lookup_test.cpp @@ -117,6 +117,29 @@ TEST_F(DocumentSourceLookUpTest, AcceptsPipelineSyntax) { ASSERT_TRUE(lookup->wasConstructedWithPipelineSyntax()); } +TEST_F(DocumentSourceLookUpTest, AcceptsPipelineWithLetSyntax) { + auto expCtx = getExpCtx(); + NamespaceString fromNs("test", "coll"); + expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + + auto docSource = DocumentSourceLookUp::createFromBson( + BSON("$lookup" << BSON("from" + << "coll" + << "let" + << BSON("var1" + << "$x") + << "pipeline" + << BSON_ARRAY(BSON("$project" << BSON("hasX" + << "$$var1")) + << BSON("$match" << BSON("$hasX" << true))) + << "as" + << "as")) + .firstElement(), + expCtx); + auto lookup = static_cast<DocumentSourceLookUp*>(docSource.get()); + ASSERT_TRUE(lookup->wasConstructedWithPipelineSyntax()); +} + TEST_F(DocumentSourceLookUpTest, RejectsLocalFieldForeignFieldWhenPipelineIsSpecified) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); @@ -142,10 +165,83 @@ TEST_F(DocumentSourceLookUpTest, RejectsLocalFieldForeignFieldWhenPipelineIsSpec << lookupStage->getSourceName() << " stage to uassert on mix of localField/foreignField and pipeline options"); } catch (const UserException& ex) { - ASSERT_EQ(40450, ex.getCode()); + ASSERT_EQ(ErrorCodes::FailedToParse, ex.getCode()); } } +TEST_F(DocumentSourceLookUpTest, RejectsLocalFieldForeignFieldWhenLetIsSpecified) { + auto expCtx = getExpCtx(); + NamespaceString fromNs("test", "coll"); + expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + + ASSERT_THROWS_CODE(DocumentSourceLookUp::createFromBson(BSON("$lookup" << BSON("from" + << "coll" + << "let" + << BSON("var1" + << "$a") + << "localField" + << "a" + << "foreignField" + << "b" + << "as" + << "as")) + .firstElement(), + expCtx), + UserException, + ErrorCodes::FailedToParse); +} + +TEST_F(DocumentSourceLookUpTest, RejectsInvalidLetVariableName) { + auto expCtx = getExpCtx(); + NamespaceString fromNs("test", "coll"); + expCtx->setResolvedNamespace(fromNs, {fromNs, std::vector<BSONObj>{}}); + + ASSERT_THROWS_CODE(DocumentSourceLookUp::createFromBson( + BSON("$lookup" << BSON("from" + << "coll" + << "let" + << BSON("" // Empty variable name. + << "$a") + << "pipeline" + << BSON_ARRAY(BSON("$match" << BSON("x" << 1))) + << "as" + << "as")) + .firstElement(), + expCtx), + UserException, + 16866); + + ASSERT_THROWS_CODE(DocumentSourceLookUp::createFromBson( + BSON("$lookup" << BSON("from" + << "coll" + << "let" + << BSON("^invalidFirstChar" + << "$a") + << "pipeline" + << BSON_ARRAY(BSON("$match" << BSON("x" << 1))) + << "as" + << "as")) + .firstElement(), + expCtx), + UserException, + 16867); + + ASSERT_THROWS_CODE(DocumentSourceLookUp::createFromBson( + BSON("$lookup" << BSON("from" + << "coll" + << "let" + << BSON("contains.invalidChar" + << "$a") + << "pipeline" + << BSON_ARRAY(BSON("$match" << BSON("x" << 1))) + << "as" + << "as")) + .firstElement(), + expCtx), + UserException, + 16868); +} + TEST_F(DocumentSourceLookUpTest, ShouldBeAbleToReParseSerializedStage) { auto expCtx = getExpCtx(); NamespaceString fromNs("test", "coll"); @@ -154,6 +250,9 @@ TEST_F(DocumentSourceLookUpTest, ShouldBeAbleToReParseSerializedStage) { auto lookupStage = DocumentSourceLookUp::createFromBson( BSON("$lookup" << BSON("from" << "coll" + << "let" + << BSON("local_x" + << "$x") << "pipeline" << BSON_ARRAY(BSON("$match" << BSON("x" << 1))) << "as" @@ -174,10 +273,13 @@ TEST_F(DocumentSourceLookUpTest, ShouldBeAbleToReParseSerializedStage) { ASSERT_EQ(serializedDoc["$lookup"].getType(), BSONType::Object); auto serializedStage = serializedDoc["$lookup"].getDocument(); - ASSERT_EQ(serializedStage.size(), 3UL); + ASSERT_EQ(serializedStage.size(), 4UL); ASSERT_VALUE_EQ(serializedStage["from"], Value(std::string("coll"))); ASSERT_VALUE_EQ(serializedStage["as"], Value(std::string("as"))); + ASSERT_DOCUMENT_EQ(serializedStage["let"].getDocument(), + Document(fromjson("{local_x: \"$x\"}"))); + ASSERT_EQ(serializedStage["pipeline"].getType(), BSONType::Array); ASSERT_EQ(serializedStage["pipeline"].getArrayLength(), 1UL); |