diff options
author | Ted Tuckman <ted.tuckman@mongodb.com> | 2020-02-27 14:44:11 -0500 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-02-28 17:57:51 +0000 |
commit | 314d315015c1c25ed23c470aaa2c4b2a59382b5a (patch) | |
tree | 6bff58f639ddb28a1404c3a99d4ed459ca21266e /src | |
parent | d656e185f2ca18f3963581c5bd0279ca69c256f9 (diff) | |
download | mongo-314d315015c1c25ed23c470aaa2c4b2a59382b5a.tar.gz |
SERVER-46110 Expose $out functionality
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/db/commands/mr_common.cpp | 2 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out.cpp | 70 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out.h | 32 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out_test.cpp | 10 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline_test.cpp | 2 |
5 files changed, 33 insertions, 83 deletions
diff --git a/src/mongo/db/commands/mr_common.cpp b/src/mongo/db/commands/mr_common.cpp index 7343a63ac89..26540980227 100644 --- a/src/mongo/db/commands/mr_common.cpp +++ b/src/mongo/db/commands/mr_common.cpp @@ -168,7 +168,7 @@ auto translateFinalize(boost::intrusive_ptr<ExpressionContext> expCtx, auto translateOutReplace(boost::intrusive_ptr<ExpressionContext> expCtx, NamespaceString targetNss) { - return DocumentSourceOut::createAndAllowDifferentDB(std::move(targetNss), expCtx); + return DocumentSourceOut::create(std::move(targetNss), expCtx); } auto translateOutMerge(boost::intrusive_ptr<ExpressionContext> expCtx, diff --git a/src/mongo/db/pipeline/document_source_out.cpp b/src/mongo/db/pipeline/document_source_out.cpp index f5d2388cae3..ec78b9084d3 100644 --- a/src/mongo/db/pipeline/document_source_out.cpp +++ b/src/mongo/db/pipeline/document_source_out.cpp @@ -53,9 +53,6 @@ MONGO_FAIL_POINT_DEFINE(outWaitAfterTempCollectionCreation); REGISTER_DOCUMENT_SOURCE(out, DocumentSourceOut::LiteParsed::parse, DocumentSourceOut::createFromBson); -REGISTER_DOCUMENT_SOURCE(internalOutToDifferentDB, - DocumentSourceOut::LiteParsed::parseToDifferentDB, - DocumentSourceOut::createFromBsonToDifferentDB); DocumentSourceOut::~DocumentSourceOut() { DESTRUCTOR_GUARD( @@ -76,35 +73,32 @@ DocumentSourceOut::~DocumentSourceOut() { }); } -std::unique_ptr<DocumentSourceOut::LiteParsed> DocumentSourceOut::LiteParsed::parseToDifferentDB( - const NamespaceString& nss, const BSONElement& spec) { - - auto specObj = spec.Obj(); - auto dbElem = specObj["db"]; - auto collElem = specObj["coll"]; - uassert(16994, - str::stream() << kStageName << " must have db and coll string arguments", - dbElem.type() == BSONType::String && collElem.type() == BSONType::String); - NamespaceString targetNss{dbElem.String(), collElem.String()}; - uassert(ErrorCodes::InvalidNamespace, - "Invalid {} target namespace, {}"_format(kStageName, targetNss.ns()), - targetNss.isValid()); - - return std::make_unique<DocumentSourceOut::LiteParsed>(spec.fieldName(), std::move(targetNss)); +NamespaceString DocumentSourceOut::parseNsFromElem(const BSONElement& spec, + const StringData& defaultDB) { + if (spec.type() == BSONType::String) { + return NamespaceString(defaultDB, spec.valueStringData()); + } else if (spec.type() == BSONType::Object) { + auto nsObj = spec.Obj(); + uassert(16994, + str::stream() << kStageName << " $out must have only db and coll string arguments", + nsObj.nFields() == 2 && nsObj.hasField("coll") && nsObj.hasField("db")); + return NamespaceString(nsObj["db"].String(), nsObj["coll"].String()); + } else { + uassert(16990, + "{} only supports a string or object argument, but found {}"_format( + kStageName, typeName(spec.type())), + spec.type() == BSONType::String); + } + MONGO_UNREACHABLE; } std::unique_ptr<DocumentSourceOut::LiteParsed> DocumentSourceOut::LiteParsed::parse( const NamespaceString& nss, const BSONElement& spec) { - uassert(16990, - "{} only supports a string argument, but found {}"_format(kStageName, - typeName(spec.type())), - spec.type() == BSONType::String); - NamespaceString targetNss{nss.db(), spec.valueStringData()}; + NamespaceString targetNss = parseNsFromElem(spec, nss.db()); uassert(ErrorCodes::InvalidNamespace, "Invalid {} target namespace, {}"_format(kStageName, targetNss.ns()), targetNss.isValid()); - return std::make_unique<DocumentSourceOut::LiteParsed>(spec.fieldName(), std::move(targetNss)); } @@ -188,16 +182,6 @@ void DocumentSourceOut::finalize() { boost::intrusive_ptr<DocumentSource> DocumentSourceOut::create( NamespaceString outputNs, const boost::intrusive_ptr<ExpressionContext>& expCtx) { - // TODO (SERVER-36832): Allow this combination. - uassert(50939, - "{} is not supported when the output collection is in a different " - "database"_format(kStageName), - outputNs.db() == expCtx->ns.db()); - return createAndAllowDifferentDB(outputNs, expCtx); -} - -boost::intrusive_ptr<DocumentSource> DocumentSourceOut::createAndAllowDifferentDB( - NamespaceString outputNs, const boost::intrusive_ptr<ExpressionContext>& expCtx) { uassert(ErrorCodes::OperationNotSupportedInTransaction, "{} cannot be used in a transaction"_format(kStageName), !expCtx->inMultiDocumentTransaction); @@ -219,24 +203,12 @@ boost::intrusive_ptr<DocumentSource> DocumentSourceOut::createAndAllowDifferentD boost::intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) { - uassert(31278, - "{} only supports a string argument, but found {}"_format(kStageName, - typeName(elem.type())), - elem.type() == BSONType::String); - return create({expCtx->ns.db(), elem.str()}, expCtx); + auto targetNS = parseNsFromElem(elem, expCtx->ns.db()); + return create(targetNS, expCtx); } -boost::intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBsonToDifferentDB( - BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& expCtx) { - - auto nsObj = elem.Obj(); - return createAndAllowDifferentDB(NamespaceString(nsObj["db"].String(), nsObj["coll"].String()), - expCtx); -} Value DocumentSourceOut::serialize(boost::optional<ExplainOptions::Verbosity> explain) const { - return _toDifferentDB - ? Value(DOC(getSourceName() << DOC("db" << _outputNs.db() << "coll" << _outputNs.coll()))) - : Value(DOC(getSourceName() << _outputNs.coll())); + return Value(DOC(kStageName << DOC("db" << _outputNs.db() << "coll" << _outputNs.coll()))); } void DocumentSourceOut::waitWhileFailPointEnabled() { diff --git a/src/mongo/db/pipeline/document_source_out.h b/src/mongo/db/pipeline/document_source_out.h index a8466f51fc4..8ff910ac007 100644 --- a/src/mongo/db/pipeline/document_source_out.h +++ b/src/mongo/db/pipeline/document_source_out.h @@ -38,7 +38,6 @@ namespace mongo { class DocumentSourceOut final : public DocumentSourceWriter<BSONObj> { public: static constexpr StringData kStageName = "$out"_sd; - static constexpr StringData kInternalStageName = "$internalOutToDifferentDB"_sd; /** * A "lite parsed" $out stage is similar to other stages involving foreign collections except in @@ -51,9 +50,6 @@ public: static std::unique_ptr<LiteParsed> parse(const NamespaceString& nss, const BSONElement& spec); - static std::unique_ptr<LiteParsed> parseToDifferentDB(const NamespaceString& nss, - const BSONElement& spec); - bool allowShardedForeignCollection(NamespaceString nss) const final { return _foreignNss != nss; } @@ -82,13 +78,6 @@ public: ~DocumentSourceOut() override; - const char* getSourceName() const final override { - if (_toDifferentDB) { - return kInternalStageName.rawData(); - } - return kStageName.rawData(); - } - StageConstraints constraints(Pipeline::SplitState pipeState) const final override { return {StreamType::kStreaming, PositionRequirement::kLast, @@ -104,30 +93,23 @@ public: boost::optional<ExplainOptions::Verbosity> explain = boost::none) const final override; /** - * Creates a new $out or $internalOutToDifferentDB stage from the given arguments. + * Creates a new $out stage from the given arguments. */ static boost::intrusive_ptr<DocumentSource> create( NamespaceString outputNs, const boost::intrusive_ptr<ExpressionContext>& expCtx); - static boost::intrusive_ptr<DocumentSource> createAndAllowDifferentDB( - NamespaceString outputNs, const boost::intrusive_ptr<ExpressionContext>& expCtx); - /** - * Parses a $out or $internalOutToDifferentDB stage from the user-supplied BSON. + * Parses a $out stage from the user-supplied BSON. */ static boost::intrusive_ptr<DocumentSource> createFromBson( BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& pExpCtx); - static boost::intrusive_ptr<DocumentSource> createFromBsonToDifferentDB( - BSONElement elem, const boost::intrusive_ptr<ExpressionContext>& pExpCtx); private: DocumentSourceOut(NamespaceString outputNs, const boost::intrusive_ptr<ExpressionContext>& expCtx) - : DocumentSourceWriter(outputNs.db() == expCtx->ns.db() ? kStageName.rawData() - : kInternalStageName.rawData(), - std::move(outputNs), - expCtx), - _toDifferentDB(getOutputNs().db() != expCtx->ns.db()) {} + : DocumentSourceWriter(kStageName.rawData(), std::move(outputNs), expCtx) {} + + static NamespaceString parseNsFromElem(const BSONElement& spec, const StringData& defaultDB); void initialize() override; @@ -155,10 +137,6 @@ private: // The temporary namespace for the $out writes. NamespaceString _tempNs; - - // Keep track of whether this document source is writing to a different DB for serialization - // purposes. - bool _toDifferentDB; }; } // namespace mongo diff --git a/src/mongo/db/pipeline/document_source_out_test.cpp b/src/mongo/db/pipeline/document_source_out_test.cpp index a1cf3722676..aef9be321f0 100644 --- a/src/mongo/db/pipeline/document_source_out_test.cpp +++ b/src/mongo/db/pipeline/document_source_out_test.cpp @@ -85,13 +85,13 @@ public: TEST_F(DocumentSourceOutTest, FailsToParseIncorrectType) { BSONObj spec = BSON("$out" << 1); - ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 31278); + ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 16990); spec = BSON("$out" << BSONArray()); - ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 31278); + ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 16990); spec = BSON("$out" << BSONObj()); - ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 31278); + ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 16994); } TEST_F(DocumentSourceOutTest, AcceptsStringArgument) { @@ -106,12 +106,12 @@ TEST_F(DocumentSourceOutTest, SerializeToString) { << "some_collection"); auto outStage = createOutStage(spec); auto serialized = outStage->serialize().getDocument(); - ASSERT_EQ(serialized["$out"].getStringData(), "some_collection"); + ASSERT_EQ(serialized["$out"]["coll"].getStringData(), "some_collection"); // Make sure we can reparse the serialized BSON. auto reparsedOutStage = createOutStage(serialized.toBson()); auto reSerialized = reparsedOutStage->serialize().getDocument(); - ASSERT_EQ(reSerialized["$out"].getStringData(), "some_collection"); + ASSERT_EQ(reSerialized["$out"]["coll"].getStringData(), "some_collection"); } } // namespace diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index 912d96fe49f..870717b4624 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -2573,7 +2573,7 @@ class Out : public ShardMergerBase { return "[]"; } string mergePipeJson() { - return "[{$out: 'outColl'}]"; + return "[{$out: {db: 'a', coll: 'outColl'}}]"; } }; |