diff options
author | Nick Zolnierz <nicholas.zolnierz@mongodb.com> | 2018-07-23 12:24:56 -0400 |
---|---|---|
committer | Nick Zolnierz <nicholas.zolnierz@mongodb.com> | 2018-07-26 12:14:00 -0400 |
commit | 2471e2bb651442d84aef69a7c1885f653a179b35 (patch) | |
tree | 81168512f82b11d49ea94d29b5e4679e8f9f2350 | |
parent | 2a2630d2d38f215ab23c18876387f3296d485d2e (diff) | |
download | mongo-2471e2bb651442d84aef69a7c1885f653a179b35.tar.gz |
SERVER-36286: Rename options for $out
-rw-r--r-- | jstests/aggregation/sources/out/drop_target.js | 70 | ||||
-rw-r--r-- | jstests/aggregation/sources/out/mode_insert_documents.js | 66 | ||||
-rw-r--r-- | jstests/aggregation/sources/out/mode_replace_collection.js | 69 | ||||
-rw-r--r-- | src/mongo/db/pipeline/SConscript | 2 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out.cpp | 25 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out.h | 2 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out.idl | 17 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out_replace_coll.cpp (renamed from src/mongo/db/pipeline/document_source_out_drop_target.cpp) | 6 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out_replace_coll.h (renamed from src/mongo/db/pipeline/document_source_out_drop_target.h) | 4 | ||||
-rw-r--r-- | src/mongo/db/pipeline/document_source_out_test.cpp | 95 | ||||
-rw-r--r-- | src/mongo/db/pipeline/pipeline_test.cpp | 3 |
11 files changed, 185 insertions, 174 deletions
diff --git a/jstests/aggregation/sources/out/drop_target.js b/jstests/aggregation/sources/out/drop_target.js deleted file mode 100644 index a998fa6cb56..00000000000 --- a/jstests/aggregation/sources/out/drop_target.js +++ /dev/null @@ -1,70 +0,0 @@ -// Tests the behavior of $out with the dropTarget option. -// @tags: [assumes_unsharded_collection] -(function() { - "use strict"; - - load("jstests/aggregation/extras/utils.js"); // For assertErrorCode. - - const coll = db.drop_target; - coll.drop(); - - const targetColl = db.drop_target_out; - targetColl.drop(); - - // - // Test $out with dropTarget set to true with a non-existent output collection. - // - assert.commandWorked(coll.insert({_id: 0})); - - coll.aggregate([{$out: {to: targetColl.getName(), mode: "insert", dropTarget: true}}]); - assert.eq(1, targetColl.find().itcount()); - - // - // Test $out with dropTarget set to true with an existing output collection. - // - coll.aggregate([{$out: {to: targetColl.getName(), mode: "insert", dropTarget: true}}]); - assert.eq(1, targetColl.find().itcount()); - - // - // Test $out with dropTarget set to false with an existing output collection. - // - coll.drop(); - assert.commandWorked(coll.insert({_id: 1})); - - coll.aggregate([{$out: {to: targetColl.getName(), mode: "insert", dropTarget: false}}]); - assert.eq(2, targetColl.find().itcount()); - - // - // Test $out with dropTarget set to false with a non-existent output collection. - // - targetColl.drop(); - coll.drop(); - assert.commandWorked(coll.insert({_id: 0})); - - coll.aggregate([{$out: {to: targetColl.getName(), mode: "insert", dropTarget: false}}]); - assert.eq(1, targetColl.find().itcount()); - - // Test that the aggregation fails if there's a duplicate key error. - assertErrorCode( - coll, [{$out: {to: targetColl.getName(), mode: "insert", dropTarget: false}}], 16996); - - // - // Test that a $out with dropTarget set to true will preserve the indexes and options of the - // output collection. - // - targetColl.drop(); - assert.commandWorked(db.createCollection(targetColl.getName(), {validator: {a: {$gt: 0}}})); - assert.commandWorked(targetColl.createIndex({a: 1})); - - coll.drop(); - assert.commandWorked(coll.insert({a: 1})); - - coll.aggregate([{$out: {to: targetColl.getName(), mode: "insert", dropTarget: true}}]); - assert.eq(1, targetColl.find().itcount()); - assert.eq(2, targetColl.getIndexes().length); - - const listColl = db.runCommand({listCollections: 1, filter: {name: targetColl.getName()}}); - assert.commandWorked(listColl); - assert.eq({a: {$gt: 0}}, listColl.cursor.firstBatch[0].options["validator"]); - -}()); diff --git a/jstests/aggregation/sources/out/mode_insert_documents.js b/jstests/aggregation/sources/out/mode_insert_documents.js new file mode 100644 index 00000000000..b6918424a9c --- /dev/null +++ b/jstests/aggregation/sources/out/mode_insert_documents.js @@ -0,0 +1,66 @@ +// Tests the behavior of $out with mode "insertDocuments". +// @tags: [assumes_unsharded_collection, assumes_no_implicit_collection_creation_after_drop] +(function() { + "use strict"; + + load("jstests/aggregation/extras/utils.js"); // For assertErrorCode. + + const coll = db.mode_insert_documents; + coll.drop(); + + const targetColl = db.mode_insert_documents_out; + targetColl.drop(); + + const pipeline = [{$out: {to: targetColl.getName(), mode: "insertDocuments"}}]; + + // + // Test $out with a non-existent output collection. + // + assert.commandWorked(coll.insert({_id: 0})); + + coll.aggregate(pipeline); + assert.eq(1, targetColl.find().itcount()); + + // + // Test $out with an existing output collection. + // + assert.commandWorked(coll.remove({_id: 0})); + assert.commandWorked(coll.insert({_id: 1})); + coll.aggregate(pipeline); + assert.eq(2, targetColl.find().itcount()); + + // + // Test that $out fails if there's a duplicate key error. + // + assertErrorCode(coll, pipeline, 16996); + + // + // Test that $out will preserve the indexes and options of the output collection. + // + const validator = {a: {$gt: 0}}; + targetColl.drop(); + assert.commandWorked(db.createCollection(targetColl.getName(), {validator: validator})); + assert.commandWorked(targetColl.createIndex({a: 1})); + + coll.drop(); + assert.commandWorked(coll.insert({a: 1})); + + coll.aggregate(pipeline); + assert.eq(1, targetColl.find().itcount()); + assert.eq(2, targetColl.getIndexes().length); + + const listColl = db.runCommand({listCollections: 1, filter: {name: targetColl.getName()}}); + assert.commandWorked(listColl); + assert.eq(validator, listColl.cursor.firstBatch[0].options["validator"]); + + // + // Test that $out fails if it violates a unique index constraint. + // + coll.drop(); + assert.commandWorked(coll.insert([{_id: 0, a: 0}, {_id: 1, a: 0}])); + targetColl.drop(); + assert.commandWorked(targetColl.createIndex({a: 1}, {unique: true})); + + assertErrorCode(coll, pipeline, 16996); + +}()); diff --git a/jstests/aggregation/sources/out/mode_replace_collection.js b/jstests/aggregation/sources/out/mode_replace_collection.js new file mode 100644 index 00000000000..e7e770c6d5b --- /dev/null +++ b/jstests/aggregation/sources/out/mode_replace_collection.js @@ -0,0 +1,69 @@ +// Tests the behavior of $out. +// @tags: [assumes_unsharded_collection] +(function() { + "use strict"; + + load("jstests/aggregation/extras/utils.js"); // For assertErrorCode. + + const coll = db.mode_replace_collection; + coll.drop(); + + const targetColl = db.mode_replace_collection_out; + targetColl.drop(); + + const pipeline = [{$out: {to: targetColl.getName(), mode: "replaceCollection"}}]; + + // + // Test $out with a non-existent output collection. + // + assert.commandWorked(coll.insert({_id: 0})); + coll.aggregate(pipeline); + assert.eq(1, targetColl.find().itcount()); + + // + // Test $out with an existing output collection. + // + coll.aggregate(pipeline); + assert.eq(1, targetColl.find().itcount()); + + // + // Test that $out will preserve the indexes and options of the output collection. + // + targetColl.drop(); + assert.commandWorked(db.createCollection(targetColl.getName(), {validator: {a: {$gt: 0}}})); + assert.commandWorked(targetColl.createIndex({a: 1})); + + coll.drop(); + assert.commandWorked(coll.insert({a: 1})); + + coll.aggregate(pipeline); + assert.eq(1, targetColl.find().itcount()); + assert.eq(2, targetColl.getIndexes().length); + + const listColl = db.runCommand({listCollections: 1, filter: {name: targetColl.getName()}}); + assert.commandWorked(listColl); + assert.eq({a: {$gt: 0}}, listColl.cursor.firstBatch[0].options["validator"]); + + // + // Test that $out fails if it violates a unique index constraint. + // + coll.drop(); + assert.commandWorked(coll.insert([{_id: 0, a: 0}, {_id: 1, a: 0}])); + targetColl.drop(); + assert.commandWorked(targetColl.createIndex({a: 1}, {unique: true})); + + assertErrorCode(coll, pipeline, 16996); + + // Rerun a similar test, except populate the target collection with a document that conflics + // with one out of the pipeline. In this case, there is no unique key violation since the target + // collection will be dropped before renaming the source collection. + coll.drop(); + assert.commandWorked(coll.insert({_id: 0, a: 0})); + targetColl.remove({}); + assert.commandWorked(targetColl.insert({_id: 1, a: 0})); + + coll.aggregate(pipeline); + assert.eq(1, targetColl.find().itcount()); + assert.eq(2, targetColl.getIndexes().length); + +}()); diff --git a/src/mongo/db/pipeline/SConscript b/src/mongo/db/pipeline/SConscript index bb8f4e3addd..a9bad067648 100644 --- a/src/mongo/db/pipeline/SConscript +++ b/src/mongo/db/pipeline/SConscript @@ -295,7 +295,7 @@ pipelineeEnv.Library( 'document_source_match.cpp', 'document_source_merge_cursors.cpp', 'document_source_out.cpp', - 'document_source_out_drop_target.cpp', + 'document_source_out_replace_coll.cpp', 'document_source_project.cpp', 'document_source_redact.cpp', 'document_source_replace_root.cpp', diff --git a/src/mongo/db/pipeline/document_source_out.cpp b/src/mongo/db/pipeline/document_source_out.cpp index eaec798cca6..aac7f5d31c8 100644 --- a/src/mongo/db/pipeline/document_source_out.cpp +++ b/src/mongo/db/pipeline/document_source_out.cpp @@ -30,9 +30,9 @@ #include "mongo/db/ops/write_ops.h" #include "mongo/db/pipeline/document_source_out.h" -#include "mongo/db/pipeline/document_source_out_drop_target.h" #include "mongo/db/pipeline/document_source_out_gen.h" #include "mongo/db/pipeline/document_source_out_in_place.h" +#include "mongo/db/pipeline/document_source_out_replace_coll.h" namespace mongo { @@ -144,13 +144,11 @@ DocumentSource::GetNextResult DocumentSourceOut::getNext() { DocumentSourceOut::DocumentSourceOut(const NamespaceString& outputNs, const boost::intrusive_ptr<ExpressionContext>& expCtx, WriteModeEnum mode, - bool dropTarget, boost::optional<Document> uniqueKey) : DocumentSource(expCtx), _done(false), _outputNs(outputNs), _mode(mode), - _dropTarget(dropTarget), _uniqueKey(uniqueKey) {} intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( @@ -165,8 +163,7 @@ intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( "$out cannot be used with a 'majority' read concern level", readConcernLevel != repl::ReadConcernLevel::kMajorityReadConcern); - bool dropTarget = true; - auto mode = WriteModeEnum::kModeInsert; + auto mode = WriteModeEnum::kModeReplaceCollection; boost::optional<Document> uniqueKey; NamespaceString outputNs; if (elem.type() == BSONType::String) { @@ -175,11 +172,11 @@ intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( auto spec = DocumentSourceOutSpec::parse(IDLParserErrorContext("$out"), elem.embeddedObject()); - dropTarget = spec.getDropTarget(); mode = spec.getMode(); uassert(ErrorCodes::InvalidOptions, - "$out is currently supported only with mode insert.", - mode == WriteModeEnum::kModeInsert); + str::stream() << "$out is not currently supported with mode " + << WriteMode_serializer(mode), + mode != WriteModeEnum::kModeReplaceDocuments); if (auto uniqueKeyDoc = spec.getUniqueKey()) { uniqueKey = Document{{uniqueKeyDoc.get()}}; @@ -201,17 +198,19 @@ intrusive_ptr<DocumentSource> DocumentSourceOut::createFromBson( uassert(17385, "Can't $out to special collection: " + outputNs.coll(), !outputNs.isSpecial()); - if (dropTarget) { - return new DocumentSourceOutDropTarget(outputNs, expCtx, mode, dropTarget, uniqueKey); - } else { - return new DocumentSourceOutInPlace(outputNs, expCtx, mode, dropTarget, uniqueKey); + switch (mode) { + case WriteModeEnum::kModeReplaceCollection: + return new DocumentSourceOutReplaceColl(outputNs, expCtx, mode, uniqueKey); + case WriteModeEnum::kModeInsertDocuments: + return new DocumentSourceOutInPlace(outputNs, expCtx, mode, uniqueKey); + default: + MONGO_UNREACHABLE; } } Value DocumentSourceOut::serialize(boost::optional<ExplainOptions::Verbosity> explain) const { MutableDocument serialized( Document{{DocumentSourceOutSpec::kTargetCollectionFieldName, _outputNs.coll()}, - {DocumentSourceOutSpec::kDropTargetFieldName, _dropTarget}, {DocumentSourceOutSpec::kTargetDbFieldName, _outputNs.db()}, {DocumentSourceOutSpec::kModeFieldName, WriteMode_serializer(_mode)}}); if (_uniqueKey) { diff --git a/src/mongo/db/pipeline/document_source_out.h b/src/mongo/db/pipeline/document_source_out.h index 7957fcc60a9..18a44cd8ac3 100644 --- a/src/mongo/db/pipeline/document_source_out.h +++ b/src/mongo/db/pipeline/document_source_out.h @@ -44,7 +44,6 @@ public: DocumentSourceOut(const NamespaceString& outputNs, const boost::intrusive_ptr<ExpressionContext>& expCtx, WriteModeEnum mode, - bool dropTarget, boost::optional<Document> uniqueKey); virtual ~DocumentSourceOut() = default; @@ -105,7 +104,6 @@ private: const NamespaceString _outputNs; WriteModeEnum _mode; - bool _dropTarget; boost::optional<Document> _uniqueKey; }; diff --git a/src/mongo/db/pipeline/document_source_out.idl b/src/mongo/db/pipeline/document_source_out.idl index 1cb5122b005..6da8218eae6 100644 --- a/src/mongo/db/pipeline/document_source_out.idl +++ b/src/mongo/db/pipeline/document_source_out.idl @@ -34,11 +34,12 @@ imports: enums: WriteMode: - description: "Possible merge mode values." + description: "Possible write mode values." type: string values: - kModeInsert: "insert" - kModeReplace: "replace" + kModeReplaceCollection: "replaceCollection" + kModeInsertDocuments: "insertDocuments" + kModeReplaceDocuments: "replaceDocuments" structs: DocumentSourceOutSpec: @@ -60,18 +61,10 @@ structs: mode: cpp_name: mode type: WriteMode - description: The merge mode for the output operation. + description: The write mode for the output operation. uniqueKey: cpp_name: uniqueKey type: object optional: true description: Document of fields representing the unique key. - - dropTarget: - cpp_name: dropTarget - type: bool - default: false - description: If true, the 'to' collection is atomically dropped and replaced with - the results of the aggregation. -
\ No newline at end of file diff --git a/src/mongo/db/pipeline/document_source_out_drop_target.cpp b/src/mongo/db/pipeline/document_source_out_replace_coll.cpp index 0623616da17..7b0be7fd252 100644 --- a/src/mongo/db/pipeline/document_source_out_drop_target.cpp +++ b/src/mongo/db/pipeline/document_source_out_replace_coll.cpp @@ -28,13 +28,13 @@ #include "mongo/platform/basic.h" -#include "mongo/db/pipeline/document_source_out_drop_target.h" +#include "mongo/db/pipeline/document_source_out_replace_coll.h" namespace mongo { static AtomicUInt32 aggOutCounter; -void DocumentSourceOutDropTarget::initializeWriteNs() { +void DocumentSourceOutReplaceColl::initializeWriteNs() { DBClientBase* conn = pExpCtx->mongoProcessInterface->directClient(); const auto& outputNs = getOutputNs(); @@ -98,7 +98,7 @@ void DocumentSourceOutDropTarget::initializeWriteNs() { } }; -void DocumentSourceOutDropTarget::finalize() { +void DocumentSourceOutReplaceColl::finalize() { const auto& outputNs = getOutputNs(); auto renameCommandObj = BSON("renameCollection" << _tempNs.ns() << "to" << outputNs.ns() << "dropTarget" << true); diff --git a/src/mongo/db/pipeline/document_source_out_drop_target.h b/src/mongo/db/pipeline/document_source_out_replace_coll.h index 569c86920da..0dd0bd773bf 100644 --- a/src/mongo/db/pipeline/document_source_out_drop_target.h +++ b/src/mongo/db/pipeline/document_source_out_replace_coll.h @@ -37,11 +37,11 @@ namespace mongo { * Version of $out which directs writes to a temporary collection, then renames the temp collection * to the target collection with the 'dropTarget' option set to true. */ -class DocumentSourceOutDropTarget final : public DocumentSourceOut { +class DocumentSourceOutReplaceColl final : public DocumentSourceOut { public: using DocumentSourceOut::DocumentSourceOut; - ~DocumentSourceOutDropTarget() { + ~DocumentSourceOutReplaceColl() { DESTRUCTOR_GUARD( // Make sure we drop the temp collection if anything goes wrong. Errors are ignored // here because nothing can be done about them. Additionally, if this fails and the diff --git a/src/mongo/db/pipeline/document_source_out_test.cpp b/src/mongo/db/pipeline/document_source_out_test.cpp index a0a5f564456..412f49e7ab8 100644 --- a/src/mongo/db/pipeline/document_source_out_test.cpp +++ b/src/mongo/db/pipeline/document_source_out_test.cpp @@ -40,6 +40,8 @@ namespace { using boost::intrusive_ptr; +StringData kDefaultMode = WriteMode_serializer(WriteModeEnum::kModeReplaceCollection); + class DocumentSourceOutTest : public AggregationContextFixture { public: intrusive_ptr<DocumentSource> createOutStage(BSONObj spec) { @@ -64,40 +66,35 @@ TEST_F(DocumentSourceOutTest, AcceptsStringArgument) { ASSERT_EQ(outStage->getOutputNs().coll(), "some_collection"); } -TEST_F(DocumentSourceOutTest, SerializeDefaultsModeInsertAndDropTargetTrue) { +TEST_F(DocumentSourceOutTest, SerializeDefaultsModeRecreateCollection) { BSONObj spec = BSON("$out" << "some_collection"); auto docSource = createOutStage(spec); auto outStage = dynamic_cast<DocumentSourceOut*>(docSource.get()); auto serialized = outStage->serialize().getDocument(); - ASSERT_EQ(serialized["$out"][DocumentSourceOutSpec::kDropTargetFieldName].getBool(), true); ASSERT_EQ(serialized["$out"][DocumentSourceOutSpec::kModeFieldName].getStringData(), - "insert"_sd); + kDefaultMode); // Make sure we can reparse the serialized BSON. auto reparsedDocSource = createOutStage(serialized.toBson()); auto reparsedOut = dynamic_cast<DocumentSourceOut*>(reparsedDocSource.get()); auto reSerialized = reparsedOut->serialize().getDocument(); - ASSERT_EQ(reSerialized["$out"][DocumentSourceOutSpec::kDropTargetFieldName].getBool(), true); ASSERT_EQ(reSerialized["$out"][DocumentSourceOutSpec::kModeFieldName].getStringData(), - "insert"_sd); + kDefaultMode); } TEST_F(DocumentSourceOutTest, SerializeUniqueKeyOnlyIfSpecified) { BSONObj spec = BSON("$out" << BSON("to" << "target" << "mode" - << "insert" - << "dropTarget" - << true + << kDefaultMode << "uniqueKey" << BSON("_id" << 1 << "shardKey" << 1))); auto docSource = createOutStage(spec); auto outStage = dynamic_cast<DocumentSourceOut*>(docSource.get()); auto serialized = outStage->serialize().getDocument(); - ASSERT_EQ(serialized["$out"][DocumentSourceOutSpec::kDropTargetFieldName].getBool(), true); ASSERT_EQ(serialized["$out"][DocumentSourceOutSpec::kModeFieldName].getStringData(), - "insert"_sd); + kDefaultMode); ASSERT_DOCUMENT_EQ(serialized["$out"][DocumentSourceOutSpec::kUniqueKeyFieldName].getDocument(), (Document{{"_id", 1}, {"shardKey", 1}})); } @@ -117,59 +114,27 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfToIsNotAValidUserCollection) { BSONObj spec = BSON("$out" << BSON("to" << "$test" << "mode" - << "insert" - << "dropTarget" - << true)); + << kDefaultMode)); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 17385); spec = BSON("$out" << BSON("to" << "system.views" << "mode" - << "insert" - << "dropTarget" - << true)); + << kDefaultMode)); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 17385); spec = BSON("$out" << BSON("to" << ".test." << "mode" - << "insert" - << "dropTarget" - << true)); + << kDefaultMode)); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::InvalidNamespace); } -TEST_F(DocumentSourceOutTest, FailsToParseIfDropTargetIsNotBoolean) { - BSONObj spec = BSON("$out" << BSON("to" - << "test" - << "mode" - << "insert" - << "dropTarget" - << "invalid")); - ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); - - spec = BSON("$out" << BSON("to" - << "test" - << "mode" - << "insert" - << "dropTarget" - << BSONArray())); - ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); - - spec = BSON("$out" << BSON("to" - << "test" - << "mode" - << "insert" - << "dropTarget" - << 1)); - ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); -} - TEST_F(DocumentSourceOutTest, FailsToParseIfDbIsNotString) { BSONObj spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" + << kDefaultMode << "db" << true)); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); @@ -177,7 +142,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfDbIsNotString) { spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" + << kDefaultMode << "db" << BSONArray())); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); @@ -185,7 +150,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfDbIsNotString) { spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" + << kDefaultMode << "db" << BSON("" << "test"))); @@ -196,9 +161,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfDbIsNotAValidDatabaseName) { BSONObj spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" - << "dropTarget" - << true + << kDefaultMode << "db" << "$invalid")); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, 17385); @@ -206,9 +169,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfDbIsNotAValidDatabaseName) { spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" - << "dropTarget" - << true + << kDefaultMode << "db" << ".test")); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::InvalidNamespace); @@ -230,8 +191,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfModeIsNotString) { spec = BSON("$out" << BSON("to" << "test" << "mode" - << BSON("" - << "insert"))); + << BSON("" << kDefaultMode))); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); } @@ -239,7 +199,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfModeIsUnsupportedString) { BSONObj spec = BSON("$out" << BSON("to" << "test" << "mode" - << "not_insert")); + << "unsupported")); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::BadValue); spec = BSON("$out" << BSON("to" @@ -253,7 +213,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfUniqueKeyIsNotAnObject) { BSONObj spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" + << kDefaultMode << "uniqueKey" << 1)); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); @@ -261,7 +221,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfUniqueKeyIsNotAnObject) { spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" + << kDefaultMode << "uniqueKey" << BSONArray())); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); @@ -269,7 +229,7 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfUniqueKeyIsNotAnObject) { spec = BSON("$out" << BSON("to" << "test" << "mode" - << "insert" + << kDefaultMode << "uniqueKey" << "_id")); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::TypeMismatch); @@ -278,12 +238,8 @@ TEST_F(DocumentSourceOutTest, FailsToParseIfUniqueKeyIsNotAnObject) { TEST_F(DocumentSourceOutTest, CorrectlyUsesTargetDbIfSpecified) { const auto targetDb = "someOtherDb"_sd; const auto targetColl = "test"_sd; - BSONObj spec = BSON("$out" << BSON("to" << targetColl << "mode" - << "insert" - << "dropTarget" - << true - << "db" - << targetDb)); + BSONObj spec = + BSON("$out" << BSON("to" << targetColl << "mode" << kDefaultMode << "db" << targetDb)); auto docSource = createOutStage(spec); auto outStage = dynamic_cast<DocumentSourceOut*>(docSource.get()); @@ -291,13 +247,12 @@ TEST_F(DocumentSourceOutTest, CorrectlyUsesTargetDbIfSpecified) { ASSERT_EQ(outStage->getOutputNs().coll(), targetColl); } -TEST_F(DocumentSourceOutTest, ModeMustBeInsert) { +TEST_F(DocumentSourceOutTest, ModeReplaceDocumentsNotSupported) { BSONObj spec = BSON("$out" << BSON("to" << "test" << "mode" - << "replace" - << "dropTarget" - << true)); + << WriteMode_serializer( + WriteModeEnum::kModeReplaceDocuments))); ASSERT_THROWS_CODE(createOutStage(spec), AssertionException, ErrorCodes::InvalidOptions); } diff --git a/src/mongo/db/pipeline/pipeline_test.cpp b/src/mongo/db/pipeline/pipeline_test.cpp index 6f49c17ca97..bdfae082c72 100644 --- a/src/mongo/db/pipeline/pipeline_test.cpp +++ b/src/mongo/db/pipeline/pipeline_test.cpp @@ -2119,7 +2119,8 @@ class Out : public needsPrimaryShardMergerBase { return "[]"; } string mergePipeJson() { - return "[{$out: {to: 'outColl', dropTarget: true, db: 'a', mode: 'insert'}}]"; + return "[{$out: {to: 'outColl', db: 'a', mode: '" + + WriteMode_serializer(WriteModeEnum::kModeReplaceCollection) + "'}}]"; } }; |