summaryrefslogtreecommitdiff
path: root/src/mongo/db/ops
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2015-12-15 14:29:23 -0500
committerDavid Storch <david.storch@10gen.com>2015-12-30 10:20:27 -0500
commit994060e622c22783c29ff3d1c243c298fcd3442c (patch)
tree334494866929b22cb0292d857e1078f1a9db9349 /src/mongo/db/ops
parenteb93849cdbdaa9ffb60bd424036d48e2aa3c4826 (diff)
downloadmongo-994060e622c22783c29ff3d1c243c298fcd3442c.tar.gz
SERVER-21647 fix $rename to not re-order fields when the destination field is already present
Diffstat (limited to 'src/mongo/db/ops')
-rw-r--r--src/mongo/db/ops/modifier_rename.cpp6
-rw-r--r--src/mongo/db/ops/modifier_rename_test.cpp42
2 files changed, 44 insertions, 4 deletions
diff --git a/src/mongo/db/ops/modifier_rename.cpp b/src/mongo/db/ops/modifier_rename.cpp
index 123b253f227..38555546a70 100644
--- a/src/mongo/db/ops/modifier_rename.cpp
+++ b/src/mongo/db/ops/modifier_rename.cpp
@@ -221,10 +221,8 @@ Status ModifierRename::apply() const {
(_preparedState->toIdxFound == (_toFieldRef.numParts() - 1));
if (destExists) {
- removeStatus = _preparedState->toElemFound.remove();
- if (!removeStatus.isOK()) {
- return removeStatus;
- }
+ // Set destination element to the value of the source element.
+ return _preparedState->toElemFound.setValueElement(_preparedState->fromElemFound);
}
// Creates the final element that's going to be the in 'doc'.
diff --git a/src/mongo/db/ops/modifier_rename_test.cpp b/src/mongo/db/ops/modifier_rename_test.cpp
index db03531d4b4..0958c1581cb 100644
--- a/src/mongo/db/ops/modifier_rename_test.cpp
+++ b/src/mongo/db/ops/modifier_rename_test.cpp
@@ -220,6 +220,48 @@ TEST(SimpleReplace, FromDottedElement) {
ASSERT_EQUALS(logDoc, logObj);
}
+TEST(SimpleReplace, RenameToExistingFieldDoesNotReorderFields) {
+ Document doc(fromjson("{a: 1, b: 2, c: 3}"));
+ Mod setMod(fromjson("{$rename: {a: 'b'}}"));
+
+ ModifierInterface::ExecInfo execInfo;
+ ASSERT_OK(setMod.prepare(doc.root(), "", &execInfo));
+ ASSERT_EQUALS(execInfo.fieldRef[0]->dottedField(), "a");
+ ASSERT_EQUALS(execInfo.fieldRef[1]->dottedField(), "b");
+ ASSERT_FALSE(execInfo.noOp);
+
+ ASSERT_OK(setMod.apply());
+ ASSERT_FALSE(doc.isInPlaceModeEnabled());
+ ASSERT_EQUALS(doc, fromjson("{b: 1, c: 3}"));
+
+ Document logDoc;
+ LogBuilder logBuilder(logDoc.root());
+ BSONObj logObj = fromjson("{$set: {b: 1}, $unset: {a: true}}");
+ ASSERT_OK(setMod.log(&logBuilder));
+ ASSERT_EQUALS(logDoc, logObj);
+}
+
+TEST(SimpleReplace, RenameToExistingNestedFieldDoesNotReorderFields) {
+ Document doc(fromjson("{a: {b: {c: 1, d: 2}}, b: 3, c: {d: 4}}"));
+ Mod setMod(fromjson("{$rename: {'c.d': 'a.b.c'}}"));
+
+ ModifierInterface::ExecInfo execInfo;
+ ASSERT_OK(setMod.prepare(doc.root(), "", &execInfo));
+ ASSERT_EQUALS(execInfo.fieldRef[0]->dottedField(), "c.d");
+ ASSERT_EQUALS(execInfo.fieldRef[1]->dottedField(), "a.b.c");
+ ASSERT_FALSE(execInfo.noOp);
+
+ ASSERT_OK(setMod.apply());
+ ASSERT_FALSE(doc.isInPlaceModeEnabled());
+ ASSERT_EQUALS(doc, fromjson("{a: {b: {c: 4, d: 2}}, b: 3, c: {}}"));
+
+ Document logDoc;
+ LogBuilder logBuilder(logDoc.root());
+ BSONObj logObj = fromjson("{$set: {'a.b.c': 4}, $unset: {'c.d': true}}");
+ ASSERT_OK(setMod.log(&logBuilder));
+ ASSERT_EQUALS(logDoc, logObj);
+}
+
TEST(DottedTo, MissingCompleteTo) {
Document doc(fromjson("{a: 2, b: 1, c: {}}"));
Mod setMod(fromjson("{$rename: {'a':'c.r.d'}}"));