use of io.trino.spi.type.Int128 in project trino by trinodb.
the class DecimalEncoding method writeSlice.
private void writeSlice(SliceOutput output, Block block, int position) {
// first vint is scale
writeVInt(output, type.getScale());
// second vint is length
// todo get rid of BigInteger
BigInteger decimal = ((Int128) type.getObject(block, position)).toBigInteger();
byte[] decimalBytes = decimal.toByteArray();
writeVInt(output, decimalBytes.length);
// NOTE: long decimals are stored in a slice in big endian encoding
for (byte decimalByte : decimalBytes) {
output.write(decimalByte);
}
}
use of io.trino.spi.type.Int128 in project trino by trinodb.
the class DecimalCasts method jsonToLongDecimal.
@UsedByGeneratedCode
public static Int128 jsonToLongDecimal(Slice json, long precision, long scale, Int128 tenToScale) {
try (JsonParser parser = createJsonParser(JSON_FACTORY, json)) {
parser.nextToken();
Int128 result = currentTokenAsLongDecimal(parser, intPrecision(precision), DecimalConversions.intScale(scale));
// check no trailing token
checkCondition(parser.nextToken() == null, INVALID_CAST_ARGUMENT, "Cannot cast input json to DECIMAL(%s,%s)", precision, scale);
return result;
} catch (IOException | NumberFormatException | JsonCastException e) {
throw new TrinoException(INVALID_CAST_ARGUMENT, format("Cannot cast '%s' to DECIMAL(%s,%s)", json.toStringUtf8(), precision, scale), e);
}
}
use of io.trino.spi.type.Int128 in project trino by trinodb.
the class DecimalSaturatedFloorCasts method saturatedCast.
private static Int128 saturatedCast(Int128 value, int sourceScale, int resultPrecision, int resultScale) {
int scale = resultScale - sourceScale;
if (scale > 0) {
value = multiply(value, powerOfTen(scale));
} else if (scale < 0) {
value = floorDiv(value, powerOfTen(-scale));
}
Int128 maxUnscaledValue = subtract(powerOfTen(resultPrecision), Int128.ONE);
if (value.compareTo(maxUnscaledValue) > 0) {
return maxUnscaledValue;
}
Int128 minUnscaledValue = negate(maxUnscaledValue);
if (value.compareTo(minUnscaledValue) < 0) {
return minUnscaledValue;
}
return value;
}
use of io.trino.spi.type.Int128 in project trino by trinodb.
the class LongDecimalColumnReader method readValue.
@Override
protected void readValue(BlockBuilder blockBuilder, Type trinoType) {
if (!(trinoType instanceof DecimalType)) {
throw new ParquetDecodingException(format("Unsupported Trino column type (%s) for Parquet column (%s)", trinoType, columnDescriptor));
}
DecimalType trinoDecimalType = (DecimalType) trinoType;
Binary binary = valuesReader.readBytes();
Int128 value = Int128.fromBigEndian(binary.getBytes());
if (trinoDecimalType.isShort()) {
trinoType.writeLong(blockBuilder, longToShortCast(value, parquetDecimalType.getPrecision(), parquetDecimalType.getScale(), trinoDecimalType.getPrecision(), trinoDecimalType.getScale()));
} else {
trinoType.writeObject(blockBuilder, longToLongCast(value, parquetDecimalType.getPrecision(), parquetDecimalType.getScale(), trinoDecimalType.getPrecision(), trinoDecimalType.getScale()));
}
}
use of io.trino.spi.type.Int128 in project trino by trinodb.
the class TupleDomainParquetPredicate method getDomain.
/**
* Get a domain for the ranges defined by each pair of elements from {@code minimums} and {@code maximums}.
* Both arrays must have the same length.
*/
private static Domain getDomain(ColumnDescriptor column, Type type, List<Object> minimums, List<Object> maximums, boolean hasNullValue, DateTimeZone timeZone) {
checkArgument(minimums.size() == maximums.size(), "Expected minimums and maximums to have the same size");
if (type.equals(BOOLEAN)) {
boolean hasTrueValues = minimums.stream().anyMatch(value -> (boolean) value) || maximums.stream().anyMatch(value -> (boolean) value);
boolean hasFalseValues = minimums.stream().anyMatch(value -> !(boolean) value) || maximums.stream().anyMatch(value -> !(boolean) value);
if (hasTrueValues && hasFalseValues) {
return Domain.all(type);
}
if (hasTrueValues) {
return Domain.create(ValueSet.of(type, true), hasNullValue);
}
if (hasFalseValues) {
return Domain.create(ValueSet.of(type, false), hasNullValue);
}
// All nulls case is handled earlier
throw new VerifyException("Impossible boolean statistics");
}
if (type.equals(BIGINT) || type.equals(INTEGER) || type.equals(DATE) || type.equals(SMALLINT) || type.equals(TINYINT)) {
List<Range> ranges = new ArrayList<>();
for (int i = 0; i < minimums.size(); i++) {
long min = asLong(minimums.get(i));
long max = asLong(maximums.get(i));
if (isStatisticsOverflow(type, min, max)) {
return Domain.create(ValueSet.all(type), hasNullValue);
}
ranges.add(Range.range(type, min, true, max, true));
}
return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
}
if (type instanceof DecimalType) {
DecimalType decimalType = (DecimalType) type;
List<Range> ranges = new ArrayList<>();
if (decimalType.isShort()) {
for (int i = 0; i < minimums.size(); i++) {
Object min = minimums.get(i);
Object max = maximums.get(i);
long minValue = min instanceof Binary ? getShortDecimalValue(((Binary) min).getBytes()) : asLong(min);
long maxValue = min instanceof Binary ? getShortDecimalValue(((Binary) max).getBytes()) : asLong(max);
if (isStatisticsOverflow(type, minValue, maxValue)) {
return Domain.create(ValueSet.all(type), hasNullValue);
}
ranges.add(Range.range(type, minValue, true, maxValue, true));
}
} else {
for (int i = 0; i < minimums.size(); i++) {
Int128 min = Int128.fromBigEndian(((Binary) minimums.get(i)).getBytes());
Int128 max = Int128.fromBigEndian(((Binary) maximums.get(i)).getBytes());
ranges.add(Range.range(type, min, true, max, true));
}
}
return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
}
if (type.equals(REAL)) {
List<Range> ranges = new ArrayList<>();
for (int i = 0; i < minimums.size(); i++) {
Float min = (Float) minimums.get(i);
Float max = (Float) maximums.get(i);
if (min.isNaN() || max.isNaN()) {
return Domain.create(ValueSet.all(type), hasNullValue);
}
ranges.add(Range.range(type, (long) floatToRawIntBits(min), true, (long) floatToRawIntBits(max), true));
}
return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
}
if (type.equals(DOUBLE)) {
List<Range> ranges = new ArrayList<>();
for (int i = 0; i < minimums.size(); i++) {
Double min = (Double) minimums.get(i);
Double max = (Double) maximums.get(i);
if (min.isNaN() || max.isNaN()) {
return Domain.create(ValueSet.all(type), hasNullValue);
}
ranges.add(Range.range(type, min, true, max, true));
}
return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
}
if (type instanceof VarcharType) {
List<Range> ranges = new ArrayList<>();
for (int i = 0; i < minimums.size(); i++) {
Slice min = Slices.wrappedBuffer(((Binary) minimums.get(i)).toByteBuffer());
Slice max = Slices.wrappedBuffer(((Binary) maximums.get(i)).toByteBuffer());
ranges.add(Range.range(type, min, true, max, true));
}
return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
}
if (type instanceof TimestampType) {
if (column.getPrimitiveType().getPrimitiveTypeName().equals(INT96)) {
TrinoTimestampEncoder<?> timestampEncoder = createTimestampEncoder((TimestampType) type, timeZone);
List<Object> values = new ArrayList<>();
for (int i = 0; i < minimums.size(); i++) {
Object min = minimums.get(i);
Object max = maximums.get(i);
// available and valid in that special case
if (!(min instanceof Binary) || !(max instanceof Binary) || !min.equals(max)) {
return Domain.create(ValueSet.all(type), hasNullValue);
}
values.add(timestampEncoder.getTimestamp(decodeInt96Timestamp((Binary) min)));
}
return Domain.multipleValues(type, values, hasNullValue);
}
if (column.getPrimitiveType().getPrimitiveTypeName().equals(INT64)) {
LogicalTypeAnnotation logicalTypeAnnotation = column.getPrimitiveType().getLogicalTypeAnnotation();
if (!(logicalTypeAnnotation instanceof TimestampLogicalTypeAnnotation)) {
// Invalid statistics. Unit and UTC adjustment are not known
return Domain.create(ValueSet.all(type), hasNullValue);
}
TimestampLogicalTypeAnnotation timestampTypeAnnotation = (TimestampLogicalTypeAnnotation) logicalTypeAnnotation;
// Bail out if the precision is not known
if (timestampTypeAnnotation.getUnit() == null) {
return Domain.create(ValueSet.all(type), hasNullValue);
}
TrinoTimestampEncoder<?> timestampEncoder = createTimestampEncoder((TimestampType) type, DateTimeZone.UTC);
List<Range> ranges = new ArrayList<>();
for (int i = 0; i < minimums.size(); i++) {
long min = (long) minimums.get(i);
long max = (long) maximums.get(i);
ranges.add(Range.range(type, timestampEncoder.getTimestamp(decodeInt64Timestamp(min, timestampTypeAnnotation.getUnit())), true, timestampEncoder.getTimestamp(decodeInt64Timestamp(max, timestampTypeAnnotation.getUnit())), true));
}
return Domain.create(ValueSet.ofRanges(ranges), hasNullValue);
}
}
return Domain.create(ValueSet.all(type), hasNullValue);
}
Aggregations