summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline
diff options
context:
space:
mode:
authorGeorge Wangensteen <george.wangensteen@10gen.com>2019-07-08 13:19:22 -0400
committerGeorge Wangensteen <george.wangensteen@10gen.com>2019-07-24 17:44:23 -0400
commitf4399fceab41c4dfaad6b846b94e1366f67d93cd (patch)
tree11f0fd253c9fd9cc1670725bb037e160efc47017 /src/mongo/db/pipeline
parente09a81707daf75e8965cc10d909282db158bc809 (diff)
downloadmongo-f4399fceab41c4dfaad6b846b94e1366f67d93cd.tar.gz
SERVER-42017 make stage names in error messages match name used
Diffstat (limited to 'src/mongo/db/pipeline')
-rw-r--r--src/mongo/db/pipeline/document_source_add_fields.cpp15
-rw-r--r--src/mongo/db/pipeline/document_source_project.cpp28
-rw-r--r--src/mongo/db/pipeline/document_source_project.h4
-rw-r--r--src/mongo/db/pipeline/document_source_project_test.cpp57
-rw-r--r--src/mongo/db/pipeline/document_source_replace_root.cpp33
-rw-r--r--src/mongo/db/pipeline/document_source_replace_root.h8
-rw-r--r--src/mongo/db/pipeline/parsed_add_fields.cpp2
-rw-r--r--src/mongo/db/pipeline/parsed_aggregation_projection.cpp16
-rw-r--r--src/mongo/db/pipeline/parsed_aggregation_projection.h7
-rw-r--r--src/mongo/db/pipeline/pipeline_test.cpp12
10 files changed, 117 insertions, 65 deletions
diff --git a/src/mongo/db/pipeline/document_source_add_fields.cpp b/src/mongo/db/pipeline/document_source_add_fields.cpp
index 319ef9776c6..8784a5ebf16 100644
--- a/src/mongo/db/pipeline/document_source_add_fields.cpp
+++ b/src/mongo/db/pipeline/document_source_add_fields.cpp
@@ -50,14 +50,23 @@ REGISTER_DOCUMENT_SOURCE(set,
DocumentSourceAddFields::createFromBson);
intrusive_ptr<DocumentSource> DocumentSourceAddFields::create(
- BSONObj addFieldsSpec, const intrusive_ptr<ExpressionContext>& expCtx, StringData stageName) {
+ BSONObj addFieldsSpec,
+ const intrusive_ptr<ExpressionContext>& expCtx,
+ StringData userSpecifiedName) {
const bool isIndependentOfAnyCollection = false;
intrusive_ptr<DocumentSourceSingleDocumentTransformation> addFields(
new DocumentSourceSingleDocumentTransformation(
expCtx,
- ParsedAddFields::create(expCtx, addFieldsSpec),
- stageName.toString(),
+ [&]() {
+ try {
+ return ParsedAddFields::create(expCtx, addFieldsSpec);
+ } catch (DBException& ex) {
+ ex.addContext("Invalid " + userSpecifiedName.toString());
+ throw;
+ }
+ }(),
+ userSpecifiedName.toString(),
isIndependentOfAnyCollection));
return addFields;
}
diff --git a/src/mongo/db/pipeline/document_source_project.cpp b/src/mongo/db/pipeline/document_source_project.cpp
index 50c6f3defb6..419351b20e5 100644
--- a/src/mongo/db/pipeline/document_source_project.cpp
+++ b/src/mongo/db/pipeline/document_source_project.cpp
@@ -62,15 +62,26 @@ BSONObj buildExclusionProjectionSpecification(const std::vector<BSONElement>& un
} // namespace
intrusive_ptr<DocumentSource> DocumentSourceProject::create(
- BSONObj projectSpec, const intrusive_ptr<ExpressionContext>& expCtx) {
+ BSONObj projectSpec, const intrusive_ptr<ExpressionContext>& expCtx, StringData specifiedName) {
const bool isIndependentOfAnyCollection = false;
intrusive_ptr<DocumentSource> project(new DocumentSourceSingleDocumentTransformation(
expCtx,
- ParsedAggregationProjection::create(
- expCtx,
- projectSpec,
- {ProjectionPolicies::DefaultIdPolicy::kIncludeId,
- ProjectionPolicies::ArrayRecursionPolicy::kRecurseNestedArrays}),
+ [&]() {
+ // The ParsedAggregationProjection will internally perform a check to see if the
+ // provided specification is valid, and throw an exception if it was not. The exception
+ // is caught here so we can add the name that was actually specified by the user, be it
+ // $project or an alias.
+ try {
+ return ParsedAggregationProjection::create(
+ expCtx,
+ projectSpec,
+ {ProjectionPolicies::DefaultIdPolicy::kIncludeId,
+ ProjectionPolicies::ArrayRecursionPolicy::kRecurseNestedArrays});
+ } catch (DBException& ex) {
+ ex.addContext("Invalid " + specifiedName.toString());
+ throw;
+ }
+ }(),
DocumentSourceProject::kStageName.rawData(),
isIndependentOfAnyCollection));
return project;
@@ -80,7 +91,7 @@ intrusive_ptr<DocumentSource> DocumentSourceProject::createFromBson(
BSONElement elem, const intrusive_ptr<ExpressionContext>& expCtx) {
if (elem.fieldNameStringData() == kStageName) {
uassert(15969, "$project specification must be an object", elem.type() == BSONType::Object);
- return DocumentSourceProject::create(elem.Obj(), expCtx);
+ return DocumentSourceProject::create(elem.Obj(), expCtx, elem.fieldNameStringData());
}
invariant(elem.fieldNameStringData() == kAliasNameUnset);
@@ -99,7 +110,8 @@ intrusive_ptr<DocumentSource> DocumentSourceProject::createFromBson(
std::all_of(unsetSpec.cbegin(), unsetSpec.cend(), [](BSONElement elem) {
return elem.type() == BSONType::String;
}));
- return DocumentSourceProject::create(buildExclusionProjectionSpecification(unsetSpec), expCtx);
+ return DocumentSourceProject::create(
+ buildExclusionProjectionSpecification(unsetSpec), expCtx, elem.fieldNameStringData());
}
} // namespace mongo
diff --git a/src/mongo/db/pipeline/document_source_project.h b/src/mongo/db/pipeline/document_source_project.h
index d1e556e8ccc..43ee90fce0f 100644
--- a/src/mongo/db/pipeline/document_source_project.h
+++ b/src/mongo/db/pipeline/document_source_project.h
@@ -48,7 +48,9 @@ public:
* Convenience method to create a $project stage from 'projectSpec'.
*/
static boost::intrusive_ptr<DocumentSource> create(
- BSONObj projectSpec, const boost::intrusive_ptr<ExpressionContext>& expCtx);
+ BSONObj projectSpec,
+ const boost::intrusive_ptr<ExpressionContext>& expCtx,
+ StringData specifiedName);
/**
* Parses a $project stage from the user-supplied BSON.
diff --git a/src/mongo/db/pipeline/document_source_project_test.cpp b/src/mongo/db/pipeline/document_source_project_test.cpp
index 1b7696adad6..4f8f800c79d 100644
--- a/src/mongo/db/pipeline/document_source_project_test.cpp
+++ b/src/mongo/db/pipeline/document_source_project_test.cpp
@@ -61,8 +61,8 @@ using ProjectStageTest = AggregationContextFixture;
using UnsetTest = AggregationContextFixture;
TEST_F(ProjectStageTest, InclusionProjectionShouldRemoveUnspecifiedFields) {
- auto project =
- DocumentSourceProject::create(BSON("a" << true << "c" << BSON("d" << true)), getExpCtx());
+ auto project = DocumentSourceProject::create(
+ BSON("a" << true << "c" << BSON("d" << true)), getExpCtx(), "$project"_sd);
auto source = DocumentSourceMock::createForTest("{_id: 0, a: 1, b: 1, c: {d: 1}}");
project->setSource(source.get());
// The first result exists and is as expected.
@@ -78,7 +78,9 @@ TEST_F(ProjectStageTest, InclusionProjectionShouldRemoveUnspecifiedFields) {
TEST_F(ProjectStageTest, ShouldOptimizeInnerExpressions) {
auto project = DocumentSourceProject::create(
- BSON("a" << BSON("$and" << BSON_ARRAY(BSON("$const" << true)))), getExpCtx());
+ BSON("a" << BSON("$and" << BSON_ARRAY(BSON("$const" << true)))),
+ getExpCtx(),
+ "$project"_sd);
project->optimize();
// The $and should have been replaced with its only argument.
vector<Value> serializedArray;
@@ -100,7 +102,7 @@ TEST_F(ProjectStageTest, ShouldErrorOnNonObjectSpec) {
* projection.
*/
TEST_F(ProjectStageTest, InclusionShouldBeAbleToProcessMultipleDocuments) {
- auto project = DocumentSourceProject::create(BSON("a" << true), getExpCtx());
+ auto project = DocumentSourceProject::create(BSON("a" << true), getExpCtx(), "$project"_sd);
auto source = DocumentSourceMock::createForTest({"{a: 1, b: 2}", "{a: 3, b: 4}"});
project->setSource(source.get());
auto next = project->getNext();
@@ -123,7 +125,7 @@ TEST_F(ProjectStageTest, InclusionShouldBeAbleToProcessMultipleDocuments) {
* projection.
*/
TEST_F(ProjectStageTest, ExclusionShouldBeAbleToProcessMultipleDocuments) {
- auto project = DocumentSourceProject::create(BSON("a" << false), getExpCtx());
+ auto project = DocumentSourceProject::create(BSON("a" << false), getExpCtx(), "$project"_sd);
auto source = DocumentSourceMock::createForTest({"{a: 1, b: 2}", "{a: 3, b: 4}"});
project->setSource(source.get());
auto next = project->getNext();
@@ -142,7 +144,7 @@ TEST_F(ProjectStageTest, ExclusionShouldBeAbleToProcessMultipleDocuments) {
}
TEST_F(ProjectStageTest, ShouldPropagatePauses) {
- auto project = DocumentSourceProject::create(BSON("a" << false), getExpCtx());
+ auto project = DocumentSourceProject::create(BSON("a" << false), getExpCtx(), "$project"_sd);
auto source =
DocumentSourceMock::createForTest({Document(),
DocumentSource::GetNextResult::makePauseExecution(),
@@ -167,7 +169,8 @@ TEST_F(ProjectStageTest, ShouldPropagatePauses) {
TEST_F(ProjectStageTest, InclusionShouldAddDependenciesOfIncludedAndComputedFields) {
auto project = DocumentSourceProject::create(
fromjson("{a: true, x: '$b', y: {$and: ['$c','$d']}, z: {$meta: 'textScore'}}"),
- getExpCtx());
+ getExpCtx(),
+ "$project"_sd);
DepsTracker dependencies(DepsTracker::MetadataAvailable::kTextScore);
ASSERT_EQUALS(DepsTracker::State::EXHAUSTIVE_FIELDS, project->getDependencies(&dependencies));
ASSERT_EQUALS(5U, dependencies.fields.size());
@@ -189,7 +192,8 @@ TEST_F(ProjectStageTest, InclusionShouldAddDependenciesOfIncludedAndComputedFiel
}
TEST_F(ProjectStageTest, ExclusionShouldNotAddDependencies) {
- auto project = DocumentSourceProject::create(fromjson("{a: false, 'b.c': false}"), getExpCtx());
+ auto project = DocumentSourceProject::create(
+ fromjson("{a: false, 'b.c': false}"), getExpCtx(), "$project"_sd);
DepsTracker dependencies;
ASSERT_EQUALS(DepsTracker::State::SEE_NEXT, project->getDependencies(&dependencies));
@@ -202,7 +206,8 @@ TEST_F(ProjectStageTest, ExclusionShouldNotAddDependencies) {
TEST_F(ProjectStageTest, InclusionProjectionReportsIncludedPathsFromGetModifiedPaths) {
auto project = DocumentSourceProject::create(
fromjson("{a: true, 'b.c': {d: true}, e: {f: {g: true}}, h: {i: {$literal: true}}}"),
- getExpCtx());
+ getExpCtx(),
+ "$project"_sd);
auto modifiedPaths = project->getModifiedPaths();
ASSERT(modifiedPaths.type == DocumentSource::GetModPathsReturn::Type::kAllExcept);
@@ -216,7 +221,8 @@ TEST_F(ProjectStageTest, InclusionProjectionReportsIncludedPathsFromGetModifiedP
TEST_F(ProjectStageTest, InclusionProjectionReportsIncludedPathsButExcludesId) {
auto project = DocumentSourceProject::create(
fromjson("{_id: false, 'b.c': {d: true}, e: {f: {g: true}}, h: {i: {$literal: true}}}"),
- getExpCtx());
+ getExpCtx(),
+ "$project"_sd);
auto modifiedPaths = project->getModifiedPaths();
ASSERT(modifiedPaths.type == DocumentSource::GetModPathsReturn::Type::kAllExcept);
@@ -227,7 +233,7 @@ TEST_F(ProjectStageTest, InclusionProjectionReportsIncludedPathsButExcludesId) {
TEST_F(ProjectStageTest, ExclusionProjectionReportsExcludedPathsAsModifiedPaths) {
auto project = DocumentSourceProject::create(
- fromjson("{a: false, 'b.c': {d: false}, e: {f: {g: false}}}"), getExpCtx());
+ fromjson("{a: false, 'b.c': {d: false}, e: {f: {g: false}}}"), getExpCtx(), "$project"_sd);
auto modifiedPaths = project->getModifiedPaths();
ASSERT(modifiedPaths.type == DocumentSource::GetModPathsReturn::Type::kFiniteSet);
@@ -239,7 +245,9 @@ TEST_F(ProjectStageTest, ExclusionProjectionReportsExcludedPathsAsModifiedPaths)
TEST_F(ProjectStageTest, ExclusionProjectionReportsExcludedPathsWithIdExclusion) {
auto project = DocumentSourceProject::create(
- fromjson("{_id: false, 'b.c': {d: false}, e: {f: {g: false}}}"), getExpCtx());
+ fromjson("{_id: false, 'b.c': {d: false}, e: {f: {g: false}}}"),
+ getExpCtx(),
+ "$project"_sd);
auto modifiedPaths = project->getModifiedPaths();
ASSERT(modifiedPaths.type == DocumentSource::GetModPathsReturn::Type::kFiniteSet);
@@ -251,7 +259,9 @@ TEST_F(ProjectStageTest, ExclusionProjectionReportsExcludedPathsWithIdExclusion)
TEST_F(ProjectStageTest, CanUseRemoveSystemVariableToConditionallyExcludeProjectedField) {
auto project = DocumentSourceProject::create(
- fromjson("{a: 1, b: {$cond: [{$eq: ['$b', 4]}, '$$REMOVE', '$b']}}"), getExpCtx());
+ fromjson("{a: 1, b: {$cond: [{$eq: ['$b', 4]}, '$$REMOVE', '$b']}}"),
+ getExpCtx(),
+ "$project"_sd);
auto source = DocumentSourceMock::createForTest({"{a: 2, b: 2}", "{a: 3, b: 4}"});
project->setSource(source.get());
auto next = project->getNext();
@@ -268,7 +278,8 @@ TEST_F(ProjectStageTest, CanUseRemoveSystemVariableToConditionallyExcludeProject
}
TEST_F(ProjectStageTest, ProjectionCorrectlyReportsRenamesForwards) {
- auto project = DocumentSourceProject::create(fromjson("{'renamedB' : '$b'}"), getExpCtx());
+ auto project =
+ DocumentSourceProject::create(fromjson("{'renamedB' : '$b'}"), getExpCtx(), "$project"_sd);
auto renames =
semantic_analysis::renamedPaths({"b"}, *project, semantic_analysis::Direction::kForward);
// renamedPaths should return a mapping of old name->new name for each path in interestingPaths
@@ -281,7 +292,8 @@ TEST_F(ProjectStageTest, ProjectionCorrectlyReportsRenamesForwards) {
}
TEST_F(ProjectStageTest, ProjectionCorrectlyReportsRenamesBackwards) {
- auto project = DocumentSourceProject::create(fromjson("{'renamedB' : '$b'}"), getExpCtx());
+ auto project =
+ DocumentSourceProject::create(fromjson("{'renamedB' : '$b'}"), getExpCtx(), "$project"_sd);
auto renames = semantic_analysis::renamedPaths(
{"renamedB"}, *project, semantic_analysis::Direction::kBackward);
auto single_rename = renames->extract("renamedB");
@@ -306,7 +318,9 @@ BSONObj makeProjectForNestedDocument(size_t depth) {
TEST_F(ProjectStageTest, CanAddNestedDocumentExactlyAtDepthLimit) {
auto project = DocumentSourceProject::create(
- makeProjectForNestedDocument(BSONDepth::getMaxAllowableDepth()), getExpCtx());
+ makeProjectForNestedDocument(BSONDepth::getMaxAllowableDepth()),
+ getExpCtx(),
+ "$project"_sd);
auto mock = DocumentSourceMock::createForTest(Document{{"_id", 1}});
project->setSource(mock.get());
@@ -315,11 +329,12 @@ TEST_F(ProjectStageTest, CanAddNestedDocumentExactlyAtDepthLimit) {
}
TEST_F(ProjectStageTest, CannotAddNestedDocumentExceedingDepthLimit) {
- ASSERT_THROWS_CODE(
- DocumentSourceProject::create(
- makeProjectForNestedDocument(BSONDepth::getMaxAllowableDepth() + 1), getExpCtx()),
- AssertionException,
- ErrorCodes::Overflow);
+ ASSERT_THROWS_CODE(DocumentSourceProject::create(
+ makeProjectForNestedDocument(BSONDepth::getMaxAllowableDepth() + 1),
+ getExpCtx(),
+ "$project"_sd),
+ AssertionException,
+ ErrorCodes::Overflow);
}
TEST_F(UnsetTest, AcceptsValidUnsetSpecWithArray) {
diff --git a/src/mongo/db/pipeline/document_source_replace_root.cpp b/src/mongo/db/pipeline/document_source_replace_root.cpp
index deefe509bb7..e494fe1ea2a 100644
--- a/src/mongo/db/pipeline/document_source_replace_root.cpp
+++ b/src/mongo/db/pipeline/document_source_replace_root.cpp
@@ -46,15 +46,28 @@ Document ReplaceRootTransformation::applyTransformation(const Document& input) {
// Extract subdocument in the form of a Value.
Value newRoot = _newRoot->evaluate(input, &_expCtx->variables);
+ // To ensure an accurate user-facing message, any user-facing syntax that uses this stage
+ // internally must provide an message opener that complies with its documentation.
+ StringData msgOpener = [&]() {
+ switch (_specifiedName) {
+ case UserSpecifiedName::kReplaceRoot:
+ return "'newRoot' expression "_sd;
+ case UserSpecifiedName::kReplaceWith:
+ return "'replacement document' "_sd;
+ default:
+ MONGO_UNREACHABLE;
+ }
+ }();
+
// The newRoot expression, if it exists, must evaluate to an object.
uassert(40228,
- str::stream()
- << "'newRoot' expression must evaluate to an object, but resulting value was: "
- << newRoot.toString()
- << ". Type of resulting value: '"
- << typeName(newRoot.getType())
- << "'. Input document: "
- << input.toString(),
+ str::stream() << msgOpener.toString()
+ << "must evaluate to an object, but resulting value was: "
+ << newRoot.toString()
+ << ". Type of resulting value: '"
+ << typeName(newRoot.getType())
+ << "'. Input document: "
+ << input.toString(),
newRoot.getType() == BSONType::Object);
// Turn the value into a document.
@@ -104,7 +117,11 @@ intrusive_ptr<DocumentSource> DocumentSourceReplaceRoot::createFromBson(
const bool isIndependentOfAnyCollection = false;
return new DocumentSourceSingleDocumentTransformation(
expCtx,
- std::make_unique<ReplaceRootTransformation>(expCtx, newRootExpression),
+ std::make_unique<ReplaceRootTransformation>(
+ expCtx,
+ newRootExpression,
+ (stageName == kStageName) ? ReplaceRootTransformation::UserSpecifiedName::kReplaceRoot
+ : ReplaceRootTransformation::UserSpecifiedName::kReplaceWith),
kStageName.toString(),
isIndependentOfAnyCollection);
}
diff --git a/src/mongo/db/pipeline/document_source_replace_root.h b/src/mongo/db/pipeline/document_source_replace_root.h
index 290919615bc..917b221e20c 100644
--- a/src/mongo/db/pipeline/document_source_replace_root.h
+++ b/src/mongo/db/pipeline/document_source_replace_root.h
@@ -40,9 +40,12 @@ namespace mongo {
*/
class ReplaceRootTransformation final : public TransformerInterface {
public:
+ enum class UserSpecifiedName { kReplaceRoot, kReplaceWith };
+
ReplaceRootTransformation(const boost::intrusive_ptr<ExpressionContext>& expCtx,
- boost::intrusive_ptr<Expression> newRootExpression)
- : _expCtx(expCtx), _newRoot(std::move(newRootExpression)) {}
+ boost::intrusive_ptr<Expression> newRootExpression,
+ UserSpecifiedName specifiedName)
+ : _expCtx(expCtx), _newRoot(std::move(newRootExpression)), _specifiedName(specifiedName) {}
TransformerType getType() const final {
return TransformerType::kReplaceRoot;
@@ -79,6 +82,7 @@ public:
private:
const boost::intrusive_ptr<ExpressionContext> _expCtx;
boost::intrusive_ptr<Expression> _newRoot;
+ UserSpecifiedName _specifiedName;
};
/*
diff --git a/src/mongo/db/pipeline/parsed_add_fields.cpp b/src/mongo/db/pipeline/parsed_add_fields.cpp
index 2e2a1602414..d756c444fa7 100644
--- a/src/mongo/db/pipeline/parsed_add_fields.cpp
+++ b/src/mongo/db/pipeline/parsed_add_fields.cpp
@@ -42,7 +42,7 @@ namespace parsed_aggregation_projection {
std::unique_ptr<ParsedAddFields> ParsedAddFields::create(
const boost::intrusive_ptr<ExpressionContext>& expCtx, const BSONObj& spec) {
// Verify that we don't have conflicting field paths, etc.
- ProjectionSpecValidator::uassertValid(spec, "$addFields");
+ ProjectionSpecValidator::uassertValid(spec);
std::unique_ptr<ParsedAddFields> parsedAddFields = std::make_unique<ParsedAddFields>(expCtx);
// Actually parse the specification.
diff --git a/src/mongo/db/pipeline/parsed_aggregation_projection.cpp b/src/mongo/db/pipeline/parsed_aggregation_projection.cpp
index 3f283079ac4..058e20b6d0b 100644
--- a/src/mongo/db/pipeline/parsed_aggregation_projection.cpp
+++ b/src/mongo/db/pipeline/parsed_aggregation_projection.cpp
@@ -55,13 +55,8 @@ using expression::isPathPrefixOf;
// ProjectionSpecValidator
//
-void ProjectionSpecValidator::uassertValid(const BSONObj& spec, StringData stageName) {
- try {
- ProjectionSpecValidator(spec).validate();
- } catch (DBException& ex) {
- ex.addContext("Invalid " + stageName.toString());
- throw;
- }
+void ProjectionSpecValidator::uassertValid(const BSONObj& spec) {
+ ProjectionSpecValidator(spec).validate();
}
void ProjectionSpecValidator::ensurePathDoesNotConflictOrThrow(const std::string& path) {
@@ -314,11 +309,8 @@ std::unique_ptr<ParsedAggregationProjection> ParsedAggregationProjection::create
const boost::intrusive_ptr<ExpressionContext>& expCtx,
const BSONObj& spec,
ProjectionPolicies policies) {
- // Check that the specification was valid. Status returned is unspecific because validate()
- // is used by the $addFields stage as well as $project.
- // If there was an error, uassert with a $project-specific message.
- ProjectionSpecValidator::uassertValid(spec, "$project");
-
+ // Checks that the specification was valid, and throws if it is not.
+ ProjectionSpecValidator::uassertValid(spec);
// Check for any conflicting specifications, and determine the type of the projection.
auto projectionType = ProjectTypeParser::parse(spec, policies);
// kComputed is a projection type reserved for $addFields, and should never be detected by the
diff --git a/src/mongo/db/pipeline/parsed_aggregation_projection.h b/src/mongo/db/pipeline/parsed_aggregation_projection.h
index 0542847e9ba..25a6dc025cb 100644
--- a/src/mongo/db/pipeline/parsed_aggregation_projection.h
+++ b/src/mongo/db/pipeline/parsed_aggregation_projection.h
@@ -55,10 +55,11 @@ namespace parsed_aggregation_projection {
class ProjectionSpecValidator {
public:
/**
- * Throws if the specification is not valid for a projection. The stageName is used to provide a
- * more helpful error message.
+ * Throws if the specification is not valid for a projection. Because this validator is meant to
+ * be generic, the error thrown is generic. Callers at the DocumentSource level should modify
+ * the error message if they want to include information specific to the stage name used.
*/
- static void uassertValid(const BSONObj& spec, StringData stageName);
+ static void uassertValid(const BSONObj& spec);
private:
ProjectionSpecValidator(const BSONObj& spec) : _rawObj(spec) {}
diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp
index 3d59eff1dfa..18e149ab0c1 100644
--- a/src/mongo/db/pipeline/pipeline_test.cpp
+++ b/src/mongo/db/pipeline/pipeline_test.cpp
@@ -3326,12 +3326,12 @@ TEST(PipelineRenameTracking, CanHandleBackAndForthRename) {
TEST(InvolvedNamespacesTest, NoInvolvedNamespacesForMatchSortProject) {
boost::intrusive_ptr<ExpressionContext> expCtx(new ExpressionContextForTest());
- auto pipeline = unittest::assertGet(
- Pipeline::create({DocumentSourceMock::createForTest(),
- DocumentSourceMatch::create(BSON("x" << 1), expCtx),
- DocumentSourceSort::create(expCtx, BSON("y" << -1)),
- DocumentSourceProject::create(BSON("x" << 1 << "y" << 1), expCtx)},
- expCtx));
+ auto pipeline = unittest::assertGet(Pipeline::create(
+ {DocumentSourceMock::createForTest(),
+ DocumentSourceMatch::create(BSON("x" << 1), expCtx),
+ DocumentSourceSort::create(expCtx, BSON("y" << -1)),
+ DocumentSourceProject::create(BSON("x" << 1 << "y" << 1), expCtx, "$project"_sd)},
+ expCtx));
auto involvedNssSet = pipeline->getInvolvedCollections();
ASSERT(involvedNssSet.empty());
}