Example #1
0
void ArithmeticNode::updateExistingElement(mutablebson::Element* element, bool* noop) const {
    if (!element->isNumeric()) {
        mutablebson::Element 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()
                                << "} has the field '"
                                << element->getFieldName()
                                << "' of non-numeric type "
                                << typeName(element->getType()));
    }

    SafeNum originalValue = element->getValueSafeNum();
    SafeNum valueToSet = _val;
    switch (_op) {
        case ArithmeticOp::kAdd:
            valueToSet += originalValue;
            break;
        case ArithmeticOp::kMultiply:
            valueToSet *= originalValue;
            break;
    }

    // If the updated value is identical to the original value, treat this as a no-op. Caveat:
    // if the found element is in a deserialized state, we can't do that.
    if (element->getValue().ok() && valueToSet.isIdentical(originalValue)) {
        *noop = true;
    } else {

        // This can fail if 'valueToSet' is not representable as a 64-bit integer.
        uassertStatusOK(element->setValueSafeNum(valueToSet));
    }
}
Example #2
0
ModifierNode::ModifyResult BitNode::updateExistingElement(
    mutablebson::Element* element, std::shared_ptr<FieldRef> elementPath) const {
    if (!element->isIntegral()) {
        mutablebson::Element idElem =
            mutablebson::findFirstChildNamed(element->getDocument().root(), "_id");
        uasserted(ErrorCodes::BadValue,
                  str::stream() << "Cannot apply $bit to a value of non-integral type."
                                << idElem.toString()
                                << " has the field "
                                << element->getFieldName()
                                << " of non-integer type "
                                << typeName(element->getType()));
    }

    SafeNum value = applyOpList(element->getValueSafeNum());

    if (!value.isIdentical(element->getValueSafeNum())) {
        invariantOK(element->setValueSafeNum(value));
        return ModifyResult::kNormalUpdate;
    } else {
        return ModifyResult::kNoOp;
    }
}
Example #3
0
        const SafeNum val1(static_cast<int>(0xE0F1U));
        const SafeNum val2(static_cast<int>(0xDF01U));
        const SafeNum expected(static_cast<int>(0xC001U));
        const SafeNum result = val1 & val2;
        ASSERT_EQUALS(mongo::NumberInt, result.type());

        ASSERT_TRUE(expected.isIdentical(result));
    }

    TEST(BitAnd, 64and64) {
        const SafeNum val1(static_cast<long long>(0xE0F1E0F1E0F1ULL));
        const SafeNum val2(static_cast<long long>(0xDF01DF01DF01ULL));
        const SafeNum expected(static_cast<long long>(0xC001C001C001ULL));
        const SafeNum result = val1 & val2;
        ASSERT_EQUALS(mongo::NumberLong, result.type());
        ASSERT_TRUE(expected.isIdentical(result));
    }

    TEST(BitAnd, MixedSize) {
        const SafeNum val_small(static_cast<int>(0xE0F1U));
        const SafeNum val_big(static_cast<long long>(0xDF01U));
        const SafeNum expected(static_cast<long long>(0xC001U));
        const SafeNum result_s_b = val_small & val_big;
        const SafeNum result_b_s = val_big & val_small;

        ASSERT_EQUALS(mongo::NumberLong, result_s_b.type());
        ASSERT_TRUE(expected.isIdentical(result_s_b));

        ASSERT_EQUALS(mongo::NumberLong, result_b_s.type());
        ASSERT_TRUE(expected.isIdentical(result_b_s));
    }