📄 sqldecimal.java
字号:
result.setToNull(); return result; } result.setBigDecimal(SQLDecimal.getBigDecimal(addend1).add(SQLDecimal.getBigDecimal(addend2))); return result; } /** * This method implements the - operator for "decimal - decimal". * * @param left The value to be subtracted from * @param right The value to be subtracted * @param result The result of a previous call to this method, null * if not called yet * * @return A SQLDecimal containing the result of the subtraction * * @exception StandardException Thrown on error */ public NumberDataValue minus(NumberDataValue left, NumberDataValue right, NumberDataValue result) throws StandardException { if (result == null) { result = new SQLDecimal(); } if (left.isNull() || right.isNull()) { result.setToNull(); return result; } result.setBigDecimal(SQLDecimal.getBigDecimal(left).subtract(SQLDecimal.getBigDecimal(right))); return result; } /** * This method implements the * operator for "double * double". * * @param left The first value to be multiplied * @param right The second value to be multiplied * @param result The result of a previous call to this method, null * if not called yet * * @return A SQLDecimal containing the result of the multiplication * * @exception StandardException Thrown on error */ public NumberDataValue times(NumberDataValue left, NumberDataValue right, NumberDataValue result) throws StandardException { if (result == null) { result = new SQLDecimal(); } if (left.isNull() || right.isNull()) { result.setToNull(); return result; } result.setBigDecimal(SQLDecimal.getBigDecimal(left).multiply(SQLDecimal.getBigDecimal(right))); return result; } /** * This method implements the / operator for BigDecimal/BigDecimal * * @param dividend The numerator * @param divisor The denominator * @param result The result of a previous call to this method, null * if not called yet * * @return A SQLDecimal containing the result of the division * * @exception StandardException Thrown on error */ public NumberDataValue divide(NumberDataValue dividend, NumberDataValue divisor, NumberDataValue result) throws StandardException { return divide(dividend, divisor, result, -1); } /** * This method implements the / operator for BigDecimal/BigDecimal * * @param dividend The numerator * @param divisor The denominator * @param result The result of a previous call to this method, null * if not called yet * @param scale The result scale, if < 0, calculate the scale according * to the actual values' sizes * * @return A SQLDecimal containing the result of the division * * @exception StandardException Thrown on error */ public NumberDataValue divide(NumberDataValue dividend, NumberDataValue divisor, NumberDataValue result, int scale) throws StandardException { if (result == null) { result = new SQLDecimal(); } if (dividend.isNull() || divisor.isNull()) { result.setToNull(); return result; } BigDecimal divisorBigDecimal = SQLDecimal.getBigDecimal(divisor); if (divisorBigDecimal.compareTo(ZERO) == 0) { throw StandardException.newException(SQLState.LANG_DIVIDE_BY_ZERO); } BigDecimal dividendBigDecimal = SQLDecimal.getBigDecimal(dividend); /* ** Set the result scale to be either the passed in scale, whcih was ** calculated at bind time to be max(ls+rp-rs+1, 4), where ls,rp,rs ** are static data types' sizes, which are predictable and stable ** (for the whole result set column, eg.); otherwise dynamically ** calculates the scale according to actual values. Beetle 3901 */ result.setBigDecimal(dividendBigDecimal.divide( divisorBigDecimal, scale > -1 ? scale : Math.max((dividendBigDecimal.scale() + SQLDecimal.getWholeDigits(divisorBigDecimal) + 1), NumberDataValue.MIN_DECIMAL_DIVIDE_SCALE), BigDecimal.ROUND_DOWN)); return result; } /** * This method implements the unary minus operator for double. * * @param result The result of a previous call to this method, null * if not called yet * * @return A SQLDecimal containing the result of the division * * @exception StandardException Thrown on error */ public NumberDataValue minus(NumberDataValue result) throws StandardException { if (result == null) { result = new SQLDecimal(); } if (this.isNull()) { result.setToNull(); return result; } result.setBigDecimal(getBigDecimal().negate()); return result; } /** * This method implements the isNegative method. * * @return A boolean. If this.value is negative, return true. * For positive values or null, return false. */ protected boolean isNegative() { return !isNull() && (getBigDecimal().compareTo(ZERO) == -1); } /* * String display of value */ public String toString() { if (isNull()) return "NULL"; else return getString(); } /* * Hash code */ public int hashCode() { long longVal; BigDecimal localValue = getBigDecimal(); double doubleVal = (localValue != null) ? localValue.doubleValue() : 0; if (Double.isInfinite(doubleVal)) { /* ** This loses the fractional part, but it probably doesn't ** matter for numbers that are big enough to overflow a double - ** it's probably rare for numbers this big to be different only in ** their fractional parts. */ longVal = localValue.longValue(); } else { longVal = (long) doubleVal; if (longVal != doubleVal) { longVal = Double.doubleToLongBits(doubleVal); } } return (int) (longVal ^ (longVal >> 32)); } /////////////////////////////////////////////////////////////////////////////// // // VariableSizeDataValue interface // /////////////////////////////////////////////////////////////////////////////// /** * Set the precision/scale of the to the desired values. * Used when CASTing. Ideally we'd recycle normalize(), but * the use is different. * * @param desiredPrecision the desired precision -- IGNORE_PREICISION * if it is to be ignored. * @param desiredScale the desired scale * @param errorOnTrunc throw error on truncation (ignored -- * always thrown if we truncate the non-decimal part of * the value) * @return this with the target width * * @exception StandardException Thrown on non-zero truncation * if errorOnTrunc is true */ public DataValueDescriptor setWidth(int desiredPrecision, int desiredScale, boolean errorOnTrunc) throws StandardException { if (isNull()) return this; if (desiredPrecision != IGNORE_PRECISION && ((desiredPrecision - desiredScale) < SQLDecimal.getWholeDigits(getBigDecimal()))) { throw StandardException.newException(SQLState.LANG_OUTSIDE_RANGE_FOR_DATATYPE, ("DECIMAL/NUMERIC("+desiredPrecision+","+desiredScale+")")); } value = value.setScale(desiredScale, BigDecimal.ROUND_DOWN); rawData = null; return this; } /** * Return the SQL scale of this value, number of digits after the * decimal point, or zero for a whole number. This does not match the * return from BigDecimal.scale() since in J2SE 5.0 onwards that can return * negative scales. */ public int getDecimalValuePrecision() { if (isNull()) return 0; BigDecimal localValue = getBigDecimal(); return SQLDecimal.getWholeDigits(localValue) + getDecimalValueScale(); } /** * Return the SQL scale of this value, number of digits after the * decimal point, or zero for a whole number. This does not match the * return from BigDecimal.scale() since in J2SE 5.0 onwards that can return * negative scales. */ public int getDecimalValueScale() { if (isNull()) return 0; if (value == null) return rawScale; int scale = value.scale(); if (scale >= 0) return scale; // BigDecimal scale is negative, so number must have no fractional // part as its value is the unscaled value * 10^-scale return 0; } /** * Get a BigDecimal representing the value of a DataValueDescriptor * @param value Non-null value to be converted * @return BigDecimal value * @throws StandardException Invalid conversion or out of range. */ public static BigDecimal getBigDecimal(DataValueDescriptor value) throws StandardException { if (SanityManager.DEBUG) { if (value.isNull()) SanityManager.THROWASSERT("NULL value passed to SQLDecimal.getBigDecimal"); } switch (value.typeToBigDecimal()) { case Types.DECIMAL: return (BigDecimal) value.getObject(); case Types.CHAR: try { return new BigDecimal(value.getString().trim()); } catch (NumberFormatException nfe) { throw StandardException.newException(SQLState.LANG_FORMAT_EXCEPTION, "java.math.BigDecimal"); } case Types.BIGINT: return BigDecimal.valueOf(value.getLong()); default: if (SanityManager.DEBUG) SanityManager.THROWASSERT("invalid return from " + value.getClass() + ".typeToBigDecimal() " + value.typeToBigDecimal()); return null; } } /** * Calculate the number of digits to the left of the decimal point * of the passed in value. * @param decimalValue Value to get whole digits from, never null. * @return number of whole digits. */ private static int getWholeDigits(BigDecimal decimalValue) { /** * if ONE > abs(value) then the number of whole digits is 0 */ decimalValue = decimalValue.abs(); if (ONE.compareTo(decimalValue) == 1) { return 0; } if (JVMInfo.JDK_ID >= JVMInfo.J2SE_15) { // use reflection so we can still compile using JDK1.4 // if we are prepared to require 1.5 to compile then this can be a // direct call try { // precision is the number of digits in the unscaled value, // subtracting the scale (positive or negative) will give the // number of whole digits. int precision = ((Integer) bdPrecision.invoke(decimalValue, null)).intValue(); return precision - decimalValue.scale(); } catch (IllegalAccessException e) { // can't happen based on the JDK spec throw new IllegalAccessError("precision"); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof RuntimeException) { throw (RuntimeException) t; } else if (t instanceof Error) { throw (Error) t; } else { // can't happen throw new IncompatibleClassChangeError("precision"); } } } String s = decimalValue.toString(); return (decimalValue.scale() == 0) ? s.length() : s.indexOf('.'); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -