/** * Converter from a numeric object to Long. Input is checked to be within range represented by * Long. */ static Long convertToLong(Object a) { if (a instanceof Integer) { return ValuePool.getLong(((Integer) a).intValue()); } else if (a instanceof Long) { return (Long) a; } else if (a instanceof BigDecimal) { BigDecimal bd = (BigDecimal) a; if (bd.compareTo(MAX_LONG) > 0 || bd.compareTo(MIN_LONG) < 0) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getLong(bd.longValue()); } else if (a instanceof Double || a instanceof Float) { double d = ((Number) a).doubleValue(); if (Double.isInfinite(d) || Double.isNaN(d) || d >= (double) Long.MAX_VALUE + 1 || d <= (double) Long.MIN_VALUE - 1) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getLong((long) d); } else { throw Error.error(ErrorCode.X_42561); } }
/** * Converter from a numeric object to Long. Input is checked to be within range represented by * Long. */ static Long convertToLong(SessionInterface session, Object a) { if (a instanceof Integer) { return ValuePool.getLong(((Integer) a).intValue()); } else if (a instanceof Long) { return (Long) a; } else if (a instanceof BigDecimal) { BigDecimal bd = (BigDecimal) a; if (bd.compareTo(MAX_LONG) > 0 || bd.compareTo(MIN_LONG) < 0) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getLong(bd.longValue()); } else if (a instanceof Double || a instanceof Float) { double d = ((Number) a).doubleValue(); if (session instanceof Session) { if (!((Session) session).database.sqlConvertTruncate) { d = java.lang.Math.rint(d); } } if (Double.isInfinite(d) || Double.isNaN(d) || d >= (double) Long.MAX_VALUE + 1 || d <= (double) Long.MIN_VALUE - 1) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getLong((long) d); } else { throw Error.error(ErrorCode.X_42561); } }
@Override public Object add(Object a, Object b, Type otherType) { if (a == null || b == null) { return null; } switch (typeCode) { case Types.SQL_REAL: case Types.SQL_FLOAT: case Types.SQL_DOUBLE: { double ad = ((Number) a).doubleValue(); double bd = ((Number) b).doubleValue(); return ValuePool.getDouble(Double.doubleToLongBits(ad + bd)); // return new Double(ad + bd); } case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: { a = convertToDefaultType(null, a); b = convertToDefaultType(null, b); BigDecimal abd = (BigDecimal) a; BigDecimal bbd = (BigDecimal) b; return abd.add(bbd); } case Types.TINYINT: case Types.SQL_SMALLINT: case Types.SQL_INTEGER: { int ai = ((Number) a).intValue(); int bi = ((Number) b).intValue(); return ValuePool.getInt(ai + bi); } case Types.SQL_BIGINT: { long longa = ((Number) a).longValue(); long longb = ((Number) b).longValue(); return ValuePool.getLong(longa + longb); } default: throw Error.runtimeError(ErrorCode.U_S0500, "NumberType"); } }
@Override public Object convertToType(SessionInterface session, Object a, Type otherType) { if (a == null) { return a; } if (otherType.typeCode == typeCode) { switch (typeCode) { case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: if (otherType.scale == scale && otherType.precision <= precision) { return a; } break; default: return a; } } if (otherType.isIntervalType()) { int endType = ((IntervalType) otherType).endIntervalType; switch (endType) { case Types.SQL_INTERVAL_YEAR: case Types.SQL_INTERVAL_MONTH: case Types.SQL_INTERVAL_DAY: case Types.SQL_INTERVAL_HOUR: case Types.SQL_INTERVAL_MINUTE: { Long value = ValuePool.getLong(((IntervalType) otherType).convertToLong(a)); return convertToType(session, value, Type.SQL_BIGINT); } case Types.SQL_INTERVAL_SECOND: { long seconds = ((IntervalSecondData) a).units; long nanos = ((IntervalSecondData) a).nanos; BigDecimal value = ((DTIType) otherType).getSecondPart(seconds, nanos); return value; } } } switch (otherType.typeCode) { case Types.SQL_CLOB: a = ((ClobData) a).getSubString(session, 0L, (int) ((ClobData) a).length(session)); // fall through case Types.SQL_CHAR: case Types.SQL_VARCHAR: case Types.VARCHAR_IGNORECASE: { a = session.getScanner().convertToNumber((String) a, this); return convertToDefaultType(session, a); } case Types.TINYINT: case Types.SQL_SMALLINT: case Types.SQL_INTEGER: case Types.SQL_BIGINT: case Types.SQL_REAL: case Types.SQL_FLOAT: case Types.SQL_DOUBLE: case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: break; default: throw Error.error(ErrorCode.X_42561); } switch (this.typeCode) { case Types.TINYINT: case Types.SQL_SMALLINT: case Types.SQL_INTEGER: return convertToInt(a, this.typeCode); case Types.SQL_BIGINT: return convertToLong(a); case Types.SQL_REAL: case Types.SQL_FLOAT: case Types.SQL_DOUBLE: return convertToDouble(a); case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: BigDecimal value = convertToDecimal(a); return convertToTypeLimits(session, value); default: throw Error.error(ErrorCode.X_42561); } }
@Override public Object negate(Object a) { if (a == null) { return null; } switch (typeCode) { case Types.SQL_REAL: case Types.SQL_FLOAT: case Types.SQL_DOUBLE: { double ad = -((Number) a).doubleValue(); return ValuePool.getDouble(Double.doubleToLongBits(ad)); } case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: return ((BigDecimal) a).negate(); case Types.TINYINT: { int value = ((Number) a).intValue(); if (value == Byte.MIN_VALUE) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getInt(-value); } case Types.SQL_SMALLINT: { int value = ((Number) a).intValue(); if (value == Short.MIN_VALUE) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getInt(-value); } case Types.SQL_INTEGER: { int value = ((Number) a).intValue(); if (value == Integer.MIN_VALUE) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getInt(-value); } case Types.SQL_BIGINT: { long value = ((Number) a).longValue(); if (value == Long.MIN_VALUE) { throw Error.error(ErrorCode.X_22003); } return ValuePool.getLong(-value); } default: throw Error.runtimeError(ErrorCode.U_S0500, "NumberType"); } }
@Override public Object divide(Object a, Object b) { if (a == null || b == null) { return null; } switch (typeCode) { case Types.SQL_REAL: case Types.SQL_FLOAT: case Types.SQL_DOUBLE: { double ad = ((Number) a).doubleValue(); double bd = ((Number) b).doubleValue(); if (bd == 0) { throw Error.error(ErrorCode.X_22012); } return ValuePool.getDouble(Double.doubleToLongBits(ad / bd)); } case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: { a = convertToDefaultType(null, a); b = convertToDefaultType(null, b); BigDecimal abd = (BigDecimal) a; BigDecimal bbd = (BigDecimal) b; int scale = abd.scale() > bbd.scale() ? abd.scale() : bbd.scale(); if (bbd.signum() == 0) { throw Error.error(ErrorCode.X_22012); } return abd.divide(bbd, scale, BigDecimal.ROUND_DOWN); } case Types.TINYINT: case Types.SQL_SMALLINT: case Types.SQL_INTEGER: { int ai = ((Number) a).intValue(); int bi = ((Number) b).intValue(); if (bi == 0) { throw Error.error(ErrorCode.X_22012); } return ValuePool.getInt(ai / bi); } case Types.SQL_BIGINT: { long al = ((Number) a).longValue(); long bl = ((Number) b).longValue(); if (bl == 0) { throw Error.error(ErrorCode.X_22012); } return ValuePool.getLong(al / bl); } default: throw Error.runtimeError(ErrorCode.U_S0500, "NumberType"); } }