summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Zolnierz <nicholas.zolnierz@mongodb.com>2018-07-23 12:24:56 -0400
committerNick Zolnierz <nicholas.zolnierz@mongodb.com>2018-07-26 12:14:00 -0400
commit2471e2bb651442d84aef69a7c1885f653a179b35 (patch)
tree81168512f82b11d49ea94d29b5e4679e8f9f2350
parent2a2630d2d38f215ab23c18876387f3296d485d2e (diff)
downloadmongo-2471e2bb651442d84aef69a7c1885f653a179b35.tar.gz
SERVER-36286: Rename options for $out
-rw-r--r--jstests/aggregation/sources/out/drop_target.js70
-rw-r--r--jstests/aggregation/sources/out/mode_insert_documents.js66
-rw-r--r--jstests/aggregation/sources/out/mode_replace_collection.js69
-rw-r--r--src/mongo/db/pipeline/SConscript2
-rw-r--r--src/mongo/db/pipeline/document_source_out.cpp25
-rw-r--r--src/mongo/db/pipeline/document_source_out.h2
-rw-r--r--src/mongo/db/pipeline/document_source_out.idl17
-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.cpp95
-rw-r--r--src/mongo/db/pipeline/pipeline_test.cpp3
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) + "'}}]";
}
};