summaryrefslogtreecommitdiff
path: root/src/mongo/db/update
diff options
context:
space:
mode:
authorJustin Seyster <justin.seyster@mongodb.com>2017-09-12 11:22:16 -0400
committerJustin Seyster <justin.seyster@mongodb.com>2017-09-12 17:34:56 -0400
commit30d4f31fee2754a7c39be1c3653956e8953ee21e (patch)
tree9cf3878125c57e07dfec30b402c1f4339bdb86d2 /src/mongo/db/update
parent6264d36ac6002b296aa41b8dc79400fcc2cbdd74 (diff)
downloadmongo-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.cpp18
-rw-r--r--src/mongo/db/update/arithmetic_node_test.cpp17
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;