From 952fa6f3f323e5e6cfb4cf996ed1eef4ae52a9d6 Mon Sep 17 00:00:00 2001 From: Ted Tuckman Date: Fri, 21 Feb 2020 13:34:55 -0500 Subject: SERVER-46110 Expose $internalOutToDifferentDB in $out --- src/mongo/db/commands/mr_common.cpp | 2 +- src/mongo/db/pipeline/document_source_out.cpp | 70 ++++++++------------------- src/mongo/db/pipeline/document_source_out.h | 32 ++---------- 3 files changed, 27 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/mongo/db/commands/mr_common.cpp b/src/mongo/db/commands/mr_common.cpp index 9f9a2e0c7fa..52cd8bf0434 100644 --- a/src/mongo/db/commands/mr_common.cpp +++ b/src/mongo/db/commands/mr_common.cpp @@ -169,7 +169,7 @@ auto translateFinalize(boost::intrusive_ptr expCtx, auto translateOutReplace(boost::intrusive_ptr expCtx, NamespaceString targetNss) { - return DocumentSourceOut::createAndAllowDifferentDB(std::move(targetNss), expCtx); + return DocumentSourceOut::create(std::move(targetNss), expCtx); } auto translateOutMerge(boost::intrusive_ptr 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::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(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::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(spec.fieldName(), std::move(targetNss)); } @@ -188,16 +182,6 @@ void DocumentSourceOut::finalize() { boost::intrusive_ptr DocumentSourceOut::create( NamespaceString outputNs, const boost::intrusive_ptr& 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 DocumentSourceOut::createAndAllowDifferentDB( - NamespaceString outputNs, const boost::intrusive_ptr& expCtx) { uassert(ErrorCodes::OperationNotSupportedInTransaction, "{} cannot be used in a transaction"_format(kStageName), !expCtx->inMultiDocumentTransaction); @@ -219,24 +203,12 @@ boost::intrusive_ptr DocumentSourceOut::createAndAllowDifferentD boost::intrusive_ptr DocumentSourceOut::createFromBson( BSONElement elem, const boost::intrusive_ptr& 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 DocumentSourceOut::createFromBsonToDifferentDB( - BSONElement elem, const boost::intrusive_ptr& expCtx) { - - auto nsObj = elem.Obj(); - return createAndAllowDifferentDB(NamespaceString(nsObj["db"].String(), nsObj["coll"].String()), - expCtx); -} Value DocumentSourceOut::serialize(boost::optional 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 { 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 parse(const NamespaceString& nss, const BSONElement& spec); - static std::unique_ptr 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 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 create( NamespaceString outputNs, const boost::intrusive_ptr& expCtx); - static boost::intrusive_ptr createAndAllowDifferentDB( - NamespaceString outputNs, const boost::intrusive_ptr& 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 createFromBson( BSONElement elem, const boost::intrusive_ptr& pExpCtx); - static boost::intrusive_ptr createFromBsonToDifferentDB( - BSONElement elem, const boost::intrusive_ptr& pExpCtx); private: DocumentSourceOut(NamespaceString outputNs, const boost::intrusive_ptr& 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 -- cgit v1.2.1