/** @todo - review usage to see if range enforcement / java type conversion is necessary */ @Override public Object convertToTypeLimits(SessionInterface session, Object a) { if (a == null) { return null; } switch (typeCode) { case Types.TINYINT: case Types.SQL_SMALLINT: case Types.SQL_INTEGER: case Types.SQL_BIGINT: return a; case Types.SQL_REAL: case Types.SQL_FLOAT: case Types.SQL_DOUBLE: return a; case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: BigDecimal dec = (BigDecimal) a; if (scale != dec.scale()) { dec = dec.setScale(scale, BigDecimal.ROUND_HALF_DOWN); } int valuePrecision = JavaSystem.precision(dec); if (valuePrecision > precision) { throw Error.error(ErrorCode.X_22003); } return dec; default: throw Error.runtimeError(ErrorCode.U_S0500, "NumberType"); } }
@Override public String convertToString(Object a) { if (a == null) { return null; } switch (this.typeCode) { case Types.TINYINT: case Types.SQL_SMALLINT: case Types.SQL_INTEGER: case Types.SQL_BIGINT: return a.toString(); case Types.SQL_REAL: case Types.SQL_DOUBLE: double value = ((Double) a).doubleValue(); /** @todo - java 5 format change */ if (value == Double.NEGATIVE_INFINITY) { return "-1E0/0"; } if (value == Double.POSITIVE_INFINITY) { return "1E0/0"; } if (Double.isNaN(value)) { return "0E0/0E0"; } // START of VoltDB patch to comply literally with the SQL standard requirement // that 0.0 be represented as a special cased "0E0" // and NOT "0.0E0" as HSQL had been giving. if (value == 0.0) { return "0E0"; } // END of VoltDB patch. String s = Double.toString(value); // ensure the engine treats the value as a DOUBLE, not DECIMAL if (s.indexOf('E') < 0) { // START of VoltDB patch to ALWAYS use proper E notation, // with a proper single-non-zero-digit integer part. // HSQL originally just had: s = s.concat("E0"); int decimalOffset = s.indexOf('.'); String optionalSign = (value < 0.0 ? "-" : ""); int leadingNonZeroOffset; String decimalPart; int exponent; if (value > -10.0 && value < 10.0) { if (value <= -1.0 || value >= 1.0) { // OK -- exactly 1 leading digit. Done. s = s.concat("E0"); return s; } // A zero leading digit, and maybe more zeros after the decimal. // Search for a significant digit past the decimal point. for (leadingNonZeroOffset = decimalOffset + 1; leadingNonZeroOffset < s.length(); ++leadingNonZeroOffset) { if (s.charAt(leadingNonZeroOffset) != '0') { break; } } // Count 1 for the leading 0 but not for the decimal point. exponent = decimalOffset - leadingNonZeroOffset; // Since exact 0.0 was eliminated earlier, // s.charAt(leadingNonZeroOffset) must be our leading non-zero digit. // Rewrite 0.[0]*nn* as n.n*E-x where x is the number of leading zeros found // BUT rewrite 0.[0]*n as n.0E-x where x is the number of leading zeros found. if (leadingNonZeroOffset + 1 == s.length()) { decimalPart = "0"; } else { decimalPart = s.substring(leadingNonZeroOffset + 1); } } else { // Too many leading digits. leadingNonZeroOffset = optionalSign.length(); // Set the exponent to how far the original decimal point was from its target // position, just after the leading digit. This is also the length of the // string of extra integer part digits that need to be moved into the decimal part. exponent = decimalOffset - (leadingNonZeroOffset + 1); decimalPart = s.substring(leadingNonZeroOffset + 1, exponent) + s.substring(decimalOffset + 1); // Trim any trailing zeros from the result. int lastIndex; for (lastIndex = decimalPart.length() - 1; lastIndex > 0; --lastIndex) { if (decimalPart.charAt(lastIndex) != '0') { break; } } if (lastIndex > 0 && decimalPart.charAt(lastIndex) == '0') { decimalPart = decimalPart.substring(lastIndex); } } s = optionalSign + s.charAt(leadingNonZeroOffset) + "." + decimalPart + "E" + exponent; // END of VoltDB patch to use proper E notation, } return s; case Types.SQL_NUMERIC: case Types.SQL_DECIMAL: return JavaSystem.toString((BigDecimal) a); default: throw Error.runtimeError(ErrorCode.U_S0500, "NumberType"); } }