diff options
author | Justin Seyster <justin.seyster@mongodb.com> | 2017-09-12 11:22:16 -0400 |
---|---|---|
committer | Justin Seyster <justin.seyster@mongodb.com> | 2017-09-12 17:34:56 -0400 |
commit | 30d4f31fee2754a7c39be1c3653956e8953ee21e (patch) | |
tree | 9cf3878125c57e07dfec30b402c1f4339bdb86d2 /src/mongo/db/update | |
parent | 6264d36ac6002b296aa41b8dc79400fcc2cbdd74 (diff) | |
download | mongo-30d4f31fee2754a7c39be1c3653956e8953ee21e.tar.gz |
SERVER-30803 Better error message for invalid result with $inc/$mul.
This adds back a check that got lost in the translation from
modifier_inc to ArithmeticNode.
Diffstat (limited to 'src/mongo/db/update')
-rw-r--r-- | src/mongo/db/update/arithmetic_node.cpp | 18 | ||||
-rw-r--r-- | src/mongo/db/update/arithmetic_node_test.cpp | 17 |
2 files changed, 29 insertions, 6 deletions
diff --git a/src/mongo/db/update/arithmetic_node.cpp b/src/mongo/db/update/arithmetic_node.cpp index 49dfc9165e6..c5b7a3373f7 100644 --- a/src/mongo/db/update/arithmetic_node.cpp +++ b/src/mongo/db/update/arithmetic_node.cpp @@ -76,12 +76,11 @@ Status ArithmeticNode::init(BSONElement modExpr, const CollatorInterface* collat ModifierNode::ModifyResult ArithmeticNode::updateExistingElement( mutablebson::Element* element, std::shared_ptr<FieldRef> elementPath) const { if (!element->isNumeric()) { - mutablebson::Element idElem = - mutablebson::findFirstChildNamed(element->getDocument().root(), "_id"); + auto idElem = mutablebson::findFirstChildNamed(element->getDocument().root(), "_id"); uasserted(ErrorCodes::TypeMismatch, str::stream() << "Cannot apply " << getModifierNameForOp(_op) << " to a value of non-numeric type. {" - << idElem.toString() + << (idElem.ok() ? idElem.toString() : "no id") << "} has the field '" << element->getFieldName() << "' of non-numeric type " @@ -103,10 +102,17 @@ ModifierNode::ModifyResult ArithmeticNode::updateExistingElement( // if the found element is in a deserialized state, we can't do that. if (element->getValue().ok() && valueToSet.isIdentical(originalValue)) { return ModifyResult::kNoOp; + } else if (!valueToSet.isValid()) { + auto idElem = mutablebson::findFirstChildNamed(element->getDocument().root(), "_id"); + uasserted(ErrorCodes::BadValue, + str::stream() << "Failed to apply " << getModifierNameForOp(_op) + << " operations to current value (" + << originalValue.debugString() + << ") for document {" + << (idElem.ok() ? idElem.toString() : "no id") + << "}"); } else { - - // This can fail if 'valueToSet' is not representable as a 64-bit integer. - uassertStatusOK(element->setValueSafeNum(valueToSet)); + invariantOK(element->setValueSafeNum(valueToSet)); return ModifyResult::kNormalUpdate; } } diff --git a/src/mongo/db/update/arithmetic_node_test.cpp b/src/mongo/db/update/arithmetic_node_test.cpp index a0a74654ac0..105f2019057 100644 --- a/src/mongo/db/update/arithmetic_node_test.cpp +++ b/src/mongo/db/update/arithmetic_node_test.cpp @@ -590,6 +590,23 @@ TEST_F(ArithmeticNodeTest, ApplyIncToStringFails) { "\"test_object\"} has the field 'a' of non-numeric type string"); } +TEST_F(ArithmeticNodeTest, OverflowingOperationFails) { + auto update = fromjson("{$mul: {a: 2}}"); + const CollatorInterface* collator = nullptr; + ArithmeticNode node(ArithmeticNode::ArithmeticOp::kMultiply); + ASSERT_OK(node.init(update["$mul"]["a"], collator)); + + mutablebson::Document doc(fromjson("{_id: 'test_object', a: NumberLong(9223372036854775807)}")); + setPathTaken("a"); + addIndexedPath("a"); + ASSERT_THROWS_CODE_AND_WHAT(node.apply(getApplyParams(doc.root()["a"])), + AssertionException, + ErrorCodes::BadValue, + "Failed to apply $mul operations to current value " + "((NumberLong)9223372036854775807) for document {_id: " + "\"test_object\"}"); +} + TEST_F(ArithmeticNodeTest, ApplyNewPath) { auto update = fromjson("{$inc: {a: 2}}"); const CollatorInterface* collator = nullptr; |