Example #1
0
NValue NValue::opDivideDecimals(const NValue lhs, const NValue rhs) const {
    if ((lhs.getValueType() != VALUE_TYPE_DECIMAL) ||
        (rhs.getValueType() != VALUE_TYPE_DECIMAL))
    {
        throw SQLException(SQLException::dynamic_sql_error, "No decimal NValue in decimal subtract");
    }

    if (lhs.isNull() || rhs.isNull()) {
        TTInt retval;
        retval.SetMin();
        return getDecimalValue( retval );
    }

    TTLInt calc;
    calc.FromInt(lhs.getDecimal());
    calc *= NValue::kMaxScaleFactor;
    if (calc.Div(rhs.getDecimal())) {
        char message[4096];
        snprintf( message, 4096, "Attempted to divide %s by %s causing overflow/underflow (or divide by zero)",
                lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str());
        throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                           message);
    }
    TTInt retval;
    if (retval.FromInt(calc)  || retval > NValue::s_maxDecimal || retval < s_minDecimal) {
        char message[4096];
        snprintf( message, 4096, "Attempted to divide %s by %s causing overflow. Unscaled result was %s",
                lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                calc.ToString(10).c_str());
        throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                           message);
    }
    return getDecimalValue(retval);
}
Example #2
0
/*
 * Avoid scaling both sides if possible. E.g, don't turn dec * 2 into
 * (dec * 2*kMaxScale*E-12). Then the result of simple multiplication
 * is a*b*E-24 and have to further multiply to get back to the assumed
 * E-12, which can overflow unnecessarily at the middle step.
 */
NValue NValue::opMultiplyDecimals(const NValue &lhs, const NValue &rhs) const {
    if ((lhs.getValueType() != VALUE_TYPE_DECIMAL) &&
        (rhs.getValueType() != VALUE_TYPE_DECIMAL))
    {
        throw SQLException(SQLException::dynamic_sql_error, "Non-decimal NValue in decimal multiply");
    }

    if (lhs.isNull() || rhs.isNull()) {
        TTInt retval;
        retval.SetMin();
        return getDecimalValue( retval );
    }

    if ((lhs.getValueType() == VALUE_TYPE_DECIMAL) &&
        (rhs.getValueType() == VALUE_TYPE_DECIMAL))
    {
        TTLInt calc;
        calc.FromInt(lhs.getDecimal());
        calc *= rhs.getDecimal();
        calc /= NValue::kMaxScaleFactor;
        TTInt retval;
        if (retval.FromInt(calc)  || retval > NValue::s_maxDecimal || retval < s_minDecimal) {
            char message[4096];
            snprintf(message, 4096, "Attempted to multiply %s by %s causing overflow/underflow. Unscaled result was %s",
                    lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                    calc.ToString(10).c_str());
            throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                               message);
        }
        return getDecimalValue(retval);
    } else if  (lhs.getValueType() != VALUE_TYPE_DECIMAL)
    {
        TTLInt calc;
        calc.FromInt(rhs.getDecimal());
        calc *= lhs.castAsDecimalAndGetValue();
        calc /= NValue::kMaxScaleFactor;
        TTInt retval;
        retval.FromInt(calc);
        if (retval.FromInt(calc)  || retval > NValue::s_maxDecimal || retval < s_minDecimal) {
            char message[4096];
            snprintf(message, 4096, "Attempted to multiply %s by %s causing overflow/underflow. Unscaled result was %s",
                    lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                    calc.ToString(10).c_str());
            throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                               message);
        }
        return getDecimalValue(retval);
    }
    else
    {
        TTLInt calc;
        calc.FromInt(lhs.getDecimal());
        calc *= rhs.castAsDecimalAndGetValue();
        calc /= NValue::kMaxScaleFactor;
        TTInt retval;
        retval.FromInt(calc);
        if (retval.FromInt(calc)  || retval > NValue::s_maxDecimal || retval < s_minDecimal) {
            char message[4096];
            snprintf(message, 4096, "Attempted to multiply %s by %s causing overflow/underflow. Unscaled result was %s",
                    lhs.createStringFromDecimal().c_str(), rhs.createStringFromDecimal().c_str(),
                    calc.ToString(10).c_str());
            throw SQLException(SQLException::data_exception_numeric_value_out_of_range,
                               message);
        }
        return getDecimalValue(retval);
   }
}