From 994060e622c22783c29ff3d1c243c298fcd3442c Mon Sep 17 00:00:00 2001 From: David Storch Date: Tue, 15 Dec 2015 14:29:23 -0500 Subject: SERVER-21647 fix $rename to not re-order fields when the destination field is already present --- src/mongo/db/ops/modifier_rename.cpp | 6 ++--- src/mongo/db/ops/modifier_rename_test.cpp | 42 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) (limited to 'src/mongo/db/ops') 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'}}")); -- cgit v1.2.1