public static Block createShortDecimalsBlock(Iterable<String> values) { DecimalType shortDecimalType = DecimalType.createDecimalType(1); BlockBuilder builder = shortDecimalType.createBlockBuilder(null, 100); for (String value : values) { if (value == null) { builder.appendNull(); } else { shortDecimalType.writeLong(builder, new BigDecimal(value).unscaledValue().longValue()); } } return builder.build(); }
@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); }
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())); }
private static Type getCommonSuperTypeForDecimal(DecimalType firstType, DecimalType secondType) { int targetScale = Math.max(firstType.getScale(), secondType.getScale()); int targetPrecision = Math.max(firstType.getPrecision() - firstType.getScale(), secondType.getPrecision() - secondType.getScale()) + targetScale; //we allow potential loss of precision here. Overflow checking is done in operators. targetPrecision = Math.min(38, targetPrecision); return createDecimalType(targetPrecision, targetScale); }
private static HiveDecimal getHiveDecimal(DecimalType decimalType, Block block, int position) { BigInteger unscaledValue; if (decimalType.isShort()) { unscaledValue = BigInteger.valueOf(decimalType.getLong(block, position)); } else { unscaledValue = Decimals.decodeUnscaledValue(decimalType.getSlice(block, position)); } return HiveDecimal.create(unscaledValue, decimalType.getScale()); }
@Test public void testSlice() { assertFunction("SLICE(ARRAY [1, 2, 3, 4, 5], 1, 4)", new ArrayType(INTEGER), ImmutableList.of(1, 2, 3, 4)); assertFunction("SLICE(ARRAY [1, 2], 1, 4)", new ArrayType(INTEGER), ImmutableList.of(1, 2)); assertFunction("SLICE(ARRAY [1, 2, 3, 4, 5], 3, 2)", new ArrayType(INTEGER), ImmutableList.of(3, 4)); assertFunction("SLICE(ARRAY ['1', '2', '3', '4'], 2, 1)", new ArrayType(createVarcharType(1)), ImmutableList.of("2")); assertFunction("SLICE(ARRAY [1, 2, 3, 4], 3, 3)", new ArrayType(INTEGER), ImmutableList.of(3, 4)); assertFunction("SLICE(ARRAY [1, 2, 3, 4], -3, 3)", new ArrayType(INTEGER), ImmutableList.of(2, 3, 4)); assertFunction("SLICE(ARRAY [1, 2, 3, 4], -3, 5)", new ArrayType(INTEGER), ImmutableList.of(2, 3, 4)); assertFunction("SLICE(ARRAY [1, 2, 3, 4], 1, 0)", new ArrayType(INTEGER), ImmutableList.of()); assertFunction("SLICE(ARRAY [1, 2, 3, 4], -2, 0)", new ArrayType(INTEGER), ImmutableList.of()); assertFunction("SLICE(ARRAY [1, 2, 3, 4], -5, 5)", new ArrayType(INTEGER), ImmutableList.of()); assertFunction("SLICE(ARRAY [1, 2, 3, 4], -6, 5)", new ArrayType(INTEGER), ImmutableList.of()); assertFunction("SLICE(ARRAY [ARRAY [1], ARRAY [2, 3], ARRAY [4, 5, 6]], 1, 2)", new ArrayType(new ArrayType(INTEGER)), ImmutableList.of(ImmutableList.of(1), ImmutableList.of(2, 3))); assertFunction("SLICE(ARRAY [2.3, 2.3, 2.2], 2, 3)", new ArrayType(createDecimalType(2, 1)), ImmutableList.of(decimal("2.3"), decimal("2.2"))); assertFunction("SLICE(ARRAY [2.330, 1.900, 2.330], 1, 2)", new ArrayType(createDecimalType(4, 3)), ImmutableList.of(decimal("2.330"), decimal("1.900"))); assertInvalidFunction("SLICE(ARRAY [1, 2, 3, 4], 1, -1)", INVALID_FUNCTION_ARGUMENT); assertInvalidFunction("SLICE(ARRAY [1, 2, 3, 4], 0, 1)", INVALID_FUNCTION_ARGUMENT); }
if (decimalType.isShort()) { unscaledValue = BigInteger.valueOf(decimalType.getLong(block, position)); unscaledValue = Decimals.decodeUnscaledValue(decimalType.getSlice(block, position)); return new BigDecimal(unscaledValue);
private BigDecimal parseBigDecimal(Slice slice, int offset, int length) { checkArgument(length < buffer.length); for (int i = 0; i < length; i++) { buffer[i] = (char) slice.getByte(offset + i); } BigDecimal decimal = new BigDecimal(buffer, 0, length); checkState(decimal.scale() <= type.getScale(), "Read decimal value scale larger than column scale"); decimal = decimal.setScale(type.getScale(), HALF_UP); checkState(decimal.precision() <= type.getPrecision(), "Read decimal precision larger than column precision"); return decimal; } }
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 BigDecimal decimalPartitionKey(String value, DecimalType type, String name) { try { if (value.endsWith(BIG_DECIMAL_POSTFIX)) { value = value.substring(0, value.length() - BIG_DECIMAL_POSTFIX.length()); } BigDecimal decimal = new BigDecimal(value); decimal = decimal.setScale(type.getScale(), ROUND_UNNECESSARY); if (decimal.precision() > type.getPrecision()) { throw new PrestoException(HIVE_INVALID_PARTITION_VALUE, format("Invalid partition value '%s' for %s partition key: %s", value, type.toString(), name)); } return decimal; } catch (NumberFormatException e) { throw new PrestoException(HIVE_INVALID_PARTITION_VALUE, format("Invalid partition value '%s' for %s partition key: %s", value, type.toString(), name)); } }
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())); scaleStream.writeLong(type.getScale());
private SqlDecimal randomDecimal(DecimalType type) { int maxBits = (int) (Math.log(Math.pow(10, type.getPrecision())) / Math.log(2)); BigInteger bigInteger = new BigInteger(maxBits, random); if (bigInteger.equals(ZERO)) { bigInteger = ONE; } if (random.nextBoolean()) { bigInteger = bigInteger.negate(); } return new SqlDecimal(bigInteger, type.getPrecision(), type.getScale()); } }
@Test public void testDefaultDecimalLiteralSwitch() { Session decimalLiteral = Session.builder(getSession()) .setSystemProperty(SystemSessionProperties.PARSE_DECIMAL_LITERALS_AS_DOUBLE, "false") .build(); MaterializedResult decimalColumnResult = computeActual(decimalLiteral, "SELECT 1.0"); assertEquals(decimalColumnResult.getRowCount(), 1); assertEquals(decimalColumnResult.getTypes().get(0), createDecimalType(2, 1)); assertEquals(decimalColumnResult.getMaterializedRows().get(0).getField(0), new BigDecimal("1.0")); Session doubleLiteral = Session.builder(getSession()) .setSystemProperty(SystemSessionProperties.PARSE_DECIMAL_LITERALS_AS_DOUBLE, "true") .build(); MaterializedResult doubleColumnResult = computeActual(doubleLiteral, "SELECT 1.0"); assertEquals(doubleColumnResult.getRowCount(), 1); assertEquals(doubleColumnResult.getTypes().get(0), DOUBLE); assertEquals(doubleColumnResult.getMaterializedRows().get(0).getField(0), 1.0); }
@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))); }
@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); } } }
public static Block createLongDecimalsBlock(Iterable<String> values) { DecimalType longDecimalType = DecimalType.createDecimalType(MAX_SHORT_PRECISION + 1); BlockBuilder builder = longDecimalType.createBlockBuilder(null, 100); for (String value : values) { if (value == null) { builder.appendNull(); } else { writeBigDecimal(longDecimalType, builder, new BigDecimal(value)); } } return builder.build(); }
@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)); } } }
@Test public void testDecimalColumns() { TypeManager typeManager = new TypeRegistry(); IonSqlQueryBuilder queryBuilder = new IonSqlQueryBuilder(typeManager); List<HiveColumnHandle> columns = ImmutableList.of( new HiveColumnHandle("quantity", HiveType.valueOf("decimal(20,0)"), parseTypeSignature(DECIMAL), 0, REGULAR, Optional.empty()), new HiveColumnHandle("extendedprice", HiveType.valueOf("decimal(20,2)"), parseTypeSignature(DECIMAL), 1, REGULAR, Optional.empty()), new HiveColumnHandle("discount", HiveType.valueOf("decimal(10,2)"), parseTypeSignature(DECIMAL), 2, REGULAR, Optional.empty())); DecimalType decimalType = DecimalType.createDecimalType(10, 2); TupleDomain<HiveColumnHandle> tupleDomain = withColumnDomains( ImmutableMap.of( columns.get(0), Domain.create(ofRanges(Range.lessThan(DecimalType.createDecimalType(20, 0), longDecimal("50"))), false), columns.get(1), Domain.create(ofRanges(Range.equal(HiveType.valueOf("decimal(20,2)").getType(typeManager), longDecimal("0.05"))), false), columns.get(2), Domain.create(ofRanges(Range.range(decimalType, shortDecimal("0.0"), true, shortDecimal("0.02"), true)), false))); assertEquals("SELECT s._1, s._2, s._3 FROM S3Object s WHERE ((case s._1 when '' then null else CAST(s._1 AS DECIMAL(20,0)) end < 50)) AND " + "(case s._2 when '' then null else CAST(s._2 AS DECIMAL(20,2)) end = 0.05) AND ((case s._3 when '' then null else CAST(s._3 AS DECIMAL(10,2)) " + "end >= 0.00 AND case s._3 when '' then null else CAST(s._3 AS DECIMAL(10,2)) end <= 0.02))", queryBuilder.buildSql(columns, tupleDomain)); }
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 List<String> getFunctionParameterTypes() { return ImmutableList.of(DecimalType.createDecimalType(MAX_SHORT_PRECISION + 1, 2).getTypeSignature().toString()); } }