diff options
-rw-r--r-- | jstests/aggregation/explain_writing_aggs.js | 3 | ||||
-rw-r--r-- | jstests/aggregation/sources/out/replace_collection.js | 11 | ||||
-rw-r--r-- | jstests/libs/override_methods/implicitly_wrap_pipelines_in_facets.js | 1 | ||||
-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 |
6 files changed, 32 insertions, 87 deletions
diff --git a/jstests/aggregation/explain_writing_aggs.js b/jstests/aggregation/explain_writing_aggs.js index 077119daa3f..a6d2a937670 100644 --- a/jstests/aggregation/explain_writing_aggs.js +++ b/jstests/aggregation/explain_writing_aggs.js @@ -38,7 +38,8 @@ let explain = sourceColl.explain("queryPlanner").aggregate([{$out: targetColl.ge let outExplain = getAggPlanStage(explain, "$out"); assert.neq(outExplain, null, explain); -assert.eq(outExplain.$out, targetColl.getName(), explain); +assert.eq(outExplain.$out.coll, targetColl.getName(), explain); +assert.eq(outExplain.$out.db, db.getName(), explain); assert.eq(targetColl.find().itcount(), 0, explain); // Verify that execution explains don't error for $out. diff --git a/jstests/aggregation/sources/out/replace_collection.js b/jstests/aggregation/sources/out/replace_collection.js index 1544c398822..81a83bbdb4f 100644 --- a/jstests/aggregation/sources/out/replace_collection.js +++ b/jstests/aggregation/sources/out/replace_collection.js @@ -26,7 +26,7 @@ assert.commandWorked(coll.insert({_id: 0})); coll.aggregate(pipeline); assert.eq(1, targetColl.find().itcount()); -// Test $internalOutToDifferentDB with a non-existent database. This is only expected to work in a +// Test $out with a non-existent database. This is only expected to work in a // non-sharded environment. const destDB = db.getSiblingDB("outDifferentDB"); destDB.dropDatabase(); @@ -34,16 +34,11 @@ if (FixtureHelpers.isMongos(db)) { assert.commandFailedWithCode(db.runCommand({ aggregate: coll.getName(), cursor: {}, - pipeline: [{ - $internalOutToDifferentDB: - {db: destDB.getName(), coll: destDB.outDifferentColl.getName()} - }] + pipeline: [{$out: {db: destDB.getName(), coll: destDB.outDifferentColl.getName()}}] }), ErrorCodes.NamespaceNotFound); } else { - coll.aggregate({ - $internalOutToDifferentDB: {db: destDB.getName(), coll: destDB.outDifferentColl.getName()} - }); + coll.aggregate({$out: {db: destDB.getName(), coll: destDB.outDifferentColl.getName()}}); assert.eq(1, destDB.outDifferentColl.find().itcount()); } diff --git a/jstests/libs/override_methods/implicitly_wrap_pipelines_in_facets.js b/jstests/libs/override_methods/implicitly_wrap_pipelines_in_facets.js index ab680de1521..92199015faf 100644 --- a/jstests/libs/override_methods/implicitly_wrap_pipelines_in_facets.js +++ b/jstests/libs/override_methods/implicitly_wrap_pipelines_in_facets.js @@ -32,7 +32,6 @@ Mongo.prototype.runCommand = function(dbName, cmdObj, options) { '$indexStats', '$merge', '$out', - '$internalOutToDifferentDB' ]; for (let stageSpec of originalPipeline) { // Skip wrapping the pipeline in a $facet stage if it has an invalid stage 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<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 |