@UsedByGeneratedCode public static Slice varcharToLongDecimal(Slice value, long precision, long scale, BigInteger tenToScale) { BigDecimal result; String stringValue = value.toString(UTF_8); try { result = new BigDecimal(stringValue).setScale(intScale(scale), HALF_UP); } catch (NumberFormatException e) { throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast VARCHAR '%s' to DECIMAL(%s, %s). Value is not a number.", stringValue, precision, scale)); } if (overflows(result, precision)) { throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast VARCHAR '%s' to DECIMAL(%s, %s). Value too large.", stringValue, precision, scale)); } return encodeUnscaledValue(result.unscaledValue()); }
@VisibleForTesting public static BigDecimal average(LongDecimalWithOverflowAndLongState state, DecimalType type) { BigDecimal sum = new BigDecimal(Decimals.decodeUnscaledValue(state.getLongDecimal()), type.getScale()); BigDecimal count = BigDecimal.valueOf(state.getLong()); if (state.getOverflow() != 0) { BigInteger overflowMultiplier = TWO.shiftLeft(UNSCALED_DECIMAL_128_SLICE_LENGTH * 8 - 2); BigInteger overflow = overflowMultiplier.multiply(BigInteger.valueOf(state.getOverflow())); sum = sum.add(new BigDecimal(overflow)); } return sum.divide(count, type.getScale(), ROUND_HALF_UP); }
private static Slice longDecimal(String value) { return encodeScaledValue(new BigDecimal(value)); } }
public static Slice encodeScaledValue(BigDecimal value, int scale) { checkArgument(scale >= 0); return encodeScaledValue(value.setScale(scale, UNNECESSARY)); }
public static Slice getLongDecimalValue(HiveDecimalWritable writable, int columnScale) { BigInteger value = new BigInteger(writable.getInternalStorage()); value = rescale(value, writable.getScale(), columnScale); return encodeUnscaledValue(value); } }
public static ReadMapping decimalReadMapping(DecimalType decimalType) { // JDBC driver can return BigDecimal with lower scale than column's scale when there are trailing zeroes int scale = decimalType.getScale(); if (decimalType.isShort()) { return longReadMapping(decimalType, (resultSet, columnIndex) -> encodeShortScaledValue(resultSet.getBigDecimal(columnIndex), scale)); } return sliceReadMapping(decimalType, (resultSet, columnIndex) -> encodeScaledValue(resultSet.getBigDecimal(columnIndex), scale)); }
return type.getBoolean(block, position); return type.getLong(block, position); return (int) type.getLong(block, position); if (decimalType.isShort()) { unscaledValue = BigInteger.valueOf(decimalType.getLong(block, position)); unscaledValue = Decimals.decodeUnscaledValue(decimalType.getSlice(block, position)); return new BigDecimal(unscaledValue); List<Type> fieldTypes = type.getTypeParameters(); if (fieldTypes.size() != rowBlock.getPositionCount()) { throw new PrestoException(StandardErrorCode.GENERIC_INTERNAL_ERROR, "Expected row value field count does not match type field count"); throw new PrestoException(NOT_SUPPORTED, "unsupported type: " + type);
public static BigDecimal readBigDecimal(DecimalType type, Block block, int position) { BigInteger unscaledValue = type.isShort() ? BigInteger.valueOf(type.getLong(block, position)) : decodeUnscaledValue(type.getSlice(block, position)); return new BigDecimal(unscaledValue, type.getScale(), new MathContext(type.getPrecision())); }
public static BigDecimal parseHiveDecimal(byte[] bytes, int start, int length, DecimalType columnType) { BigDecimal parsed = new BigDecimal(new String(bytes, start, length, UTF_8)); if (parsed.scale() > columnType.getScale()) { // Hive rounds HALF_UP too parsed = parsed.setScale(columnType.getScale(), HALF_UP); } return rescale(parsed, columnType); } }
private static Slice realToLongDecimal(long value, long precision, long scale) { float floatValue = intBitsToFloat(intScale(value)); if (Float.isInfinite(floatValue) || Float.isNaN(floatValue)) { throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast REAL '%s' to DECIMAL(%s, %s)", floatValue, precision, scale)); } try { // todo consider changing this implementation to more performant one which does not use intermediate String objects BigDecimal bigDecimal = new BigDecimal(String.valueOf(floatValue)).setScale(intScale(scale), HALF_UP); Slice decimal = Decimals.encodeScaledValue(bigDecimal); if (overflows(decimal, intScale(precision))) { throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast REAL '%s' to DECIMAL(%s, %s)", floatValue, precision, scale)); } return decimal; } catch (ArithmeticException e) { throw new PrestoException(INVALID_CAST_ARGUMENT, format("Cannot cast REAL '%s' to DECIMAL(%s, %s)", floatValue, precision, scale)); } }
@Override public void writeJsonValue(JsonGenerator jsonGenerator, Block block, int position, ConnectorSession session) throws IOException { if (block.isNull(position)) { jsonGenerator.writeNull(); } else { BigDecimal value = new BigDecimal( decodeUnscaledValue(type.getSlice(block, position)), type.getScale()); jsonGenerator.writeNumber(value); } } }
@Override public void addBlock(Type type, Block block) { int scale = ((DecimalType) type).getScale(); for (int position = 0; position < block.getPositionCount(); position++) { if (!block.isNull(position)) { Slice value = type.getSlice(block, position); addValue(new BigDecimal(Decimals.decodeUnscaledValue(value), scale)); } } }
@UsedByGeneratedCode public static Slice longDecimalToJson(Slice decimal, long precision, long scale, BigInteger tenToScale) { return decimalToJson(new BigDecimal(decodeUnscaledValue(decimal), intScale(scale))); }
private Block decimalAsBlock(String value) { Slice slice = encodeScaledValue(new BigDecimal(value)); BlockBuilder blockBuilder = new VariableWidthBlockBuilder(null, 1, slice.length()); TYPE.writeSlice(blockBuilder, slice); return blockBuilder.build(); } }
if (type.isShort()) { for (int position = 0; position < block.getPositionCount(); position++) { if (!block.isNull(position)) { long value = type.getLong(block, position); dataStream.writeUnscaledValue(value); shortDecimalStatisticsBuilder.addValue(value); for (int position = 0; position < block.getPositionCount(); position++) { if (!block.isNull(position)) { Slice value = type.getSlice(block, position); dataStream.writeUnscaledValue(value); longDecimalStatisticsBuilder.addValue(new BigDecimal(Decimals.decodeUnscaledValue(value), type.getScale()));
String sign = getMatcherGroup(matcher, 1); if (sign.isEmpty()) { sign = "+"; String leadingZeros = getMatcherGroup(matcher, 3); String integralPart = getMatcherGroup(matcher, 4); String fractionalPart = getMatcherGroup(matcher, 6); value = encodeUnscaledValue(new BigInteger(unscaledValue)); return new DecimalParseResult(value, createDecimalType(precision, scale));
@Override protected void readValue(BlockBuilder blockBuilder, Type type) { if (definitionLevel == columnDescriptor.getMaxDefinitionLevel()) { Binary value = valuesReader.readBytes(); type.writeSlice(blockBuilder, Decimals.encodeUnscaledValue(new BigInteger(value.getBytes()))); } else if (isValueNull()) { blockBuilder.appendNull(); } }
@Test public void testOptimizeDecimalLiteral() { // Short decimal assertEquals(translateAndOptimize(expression("CAST(NULL AS DECIMAL(7,2))")), constant(null, createDecimalType(7, 2))); assertEquals(translateAndOptimize(expression("DECIMAL '42'")), constant(42L, createDecimalType(2, 0))); assertEquals(translateAndOptimize(expression("CAST(42 AS DECIMAL(7,2))")), constant(4200L, createDecimalType(7, 2))); assertEquals(translateAndOptimize(simplifyExpression(expression("CAST(42 AS DECIMAL(7,2))"))), constant(4200L, createDecimalType(7, 2))); // Long decimal assertEquals(translateAndOptimize(expression("CAST(NULL AS DECIMAL(35,2))")), constant(null, createDecimalType(35, 2))); assertEquals( translateAndOptimize(expression("DECIMAL '123456789012345678901234567890'")), constant(encodeScaledValue(new BigDecimal("123456789012345678901234567890")), createDecimalType(30, 0))); assertEquals( translateAndOptimize(expression("CAST(DECIMAL '123456789012345678901234567890' AS DECIMAL(35,2))")), constant(encodeScaledValue(new BigDecimal("123456789012345678901234567890.00")), createDecimalType(35, 2))); assertEquals( translateAndOptimize(simplifyExpression(expression("CAST(DECIMAL '123456789012345678901234567890' AS DECIMAL(35,2))"))), constant(encodeScaledValue(new BigDecimal("123456789012345678901234567890.00")), createDecimalType(35, 2))); }
public static Block createLongDecimalSequenceBlock(int start, int end, DecimalType type) { BlockBuilder builder = type.createFixedSizeBlockBuilder(end - start); BigInteger base = BigInteger.TEN.pow(type.getScale()); for (int i = start; i < end; ++i) { type.writeSlice(builder, encodeUnscaledValue(BigInteger.valueOf(i).multiply(base))); } return builder.build(); }
private static void writeValue(Type type, BlockBuilder blockBuilder, Object value) blockBuilder.appendNull(); type.writeBoolean(blockBuilder, (Boolean) value); type.writeLong(blockBuilder, ((Number) value).longValue()); type.writeLong(blockBuilder, ((Number) value).longValue()); type.writeLong(blockBuilder, ((Number) value).longValue()); else if (Decimals.isShortDecimal(type)) { type.writeLong(blockBuilder, ((SqlDecimal) value).toBigDecimal().unscaledValue().longValue()); else if (Decimals.isLongDecimal(type)) { type.writeSlice(blockBuilder, Decimals.encodeUnscaledValue(((SqlDecimal) value).toBigDecimal().unscaledValue())); List<?> array = (List<?>) value; Type elementType = type.getTypeParameters().get(0); BlockBuilder arrayBlockBuilder = blockBuilder.beginBlockEntry(); for (Object elementValue : array) { writeValue(elementType, arrayBlockBuilder, elementValue); blockBuilder.closeEntry();