use of io.trino.spi.type.TimestampWithTimeZoneType in project trino by trinodb.
the class LiteralEncoder method toExpression.
public Expression toExpression(Session session, Object object, Type type) {
requireNonNull(type, "type is null");
if (object instanceof Expression) {
return (Expression) object;
}
if (object == null) {
if (type.equals(UNKNOWN)) {
return new NullLiteral();
}
return new Cast(new NullLiteral(), toSqlType(type), false, true);
}
checkArgument(Primitives.wrap(type.getJavaType()).isInstance(object), "object.getClass (%s) and type.getJavaType (%s) do not agree", object.getClass(), type.getJavaType());
if (type.equals(TINYINT)) {
return new GenericLiteral("TINYINT", object.toString());
}
if (type.equals(SMALLINT)) {
return new GenericLiteral("SMALLINT", object.toString());
}
if (type.equals(INTEGER)) {
return new LongLiteral(object.toString());
}
if (type.equals(BIGINT)) {
LongLiteral expression = new LongLiteral(object.toString());
if (expression.getValue() >= Integer.MIN_VALUE && expression.getValue() <= Integer.MAX_VALUE) {
return new GenericLiteral("BIGINT", object.toString());
}
return new LongLiteral(object.toString());
}
if (type.equals(DOUBLE)) {
Double value = (Double) object;
if (value.isNaN()) {
return FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(QualifiedName.of("nan")).build();
}
if (value.equals(Double.NEGATIVE_INFINITY)) {
return ArithmeticUnaryExpression.negative(FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(QualifiedName.of("infinity")).build());
}
if (value.equals(Double.POSITIVE_INFINITY)) {
return FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(QualifiedName.of("infinity")).build();
}
return new DoubleLiteral(object.toString());
}
if (type.equals(REAL)) {
Float value = intBitsToFloat(((Long) object).intValue());
if (value.isNaN()) {
return new Cast(FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(QualifiedName.of("nan")).build(), toSqlType(REAL));
}
if (value.equals(Float.NEGATIVE_INFINITY)) {
return ArithmeticUnaryExpression.negative(new Cast(FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(QualifiedName.of("infinity")).build(), toSqlType(REAL)));
}
if (value.equals(Float.POSITIVE_INFINITY)) {
return new Cast(FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(QualifiedName.of("infinity")).build(), toSqlType(REAL));
}
return new GenericLiteral("REAL", value.toString());
}
if (type instanceof DecimalType) {
String string;
if (isShortDecimal(type)) {
string = Decimals.toString((long) object, ((DecimalType) type).getScale());
} else {
string = Decimals.toString((Int128) object, ((DecimalType) type).getScale());
}
return new Cast(new DecimalLiteral(string), toSqlType(type));
}
if (type instanceof VarcharType) {
VarcharType varcharType = (VarcharType) type;
Slice value = (Slice) object;
if (varcharType.isUnbounded()) {
return new GenericLiteral("VARCHAR", value.toStringUtf8());
}
StringLiteral stringLiteral = new StringLiteral(value.toStringUtf8());
int boundedLength = varcharType.getBoundedLength();
int valueLength = SliceUtf8.countCodePoints(value);
if (boundedLength == valueLength) {
return stringLiteral;
}
if (boundedLength > valueLength) {
return new Cast(stringLiteral, toSqlType(type), false, true);
}
throw new IllegalArgumentException(format("Value [%s] does not fit in type %s", value.toStringUtf8(), varcharType));
}
if (type instanceof CharType) {
StringLiteral stringLiteral = new StringLiteral(((Slice) object).toStringUtf8());
return new Cast(stringLiteral, toSqlType(type), false, true);
}
if (type.equals(BOOLEAN)) {
return new BooleanLiteral(object.toString());
}
if (type.equals(DATE)) {
return new GenericLiteral("DATE", new SqlDate(toIntExact((Long) object)).toString());
}
if (type instanceof TimestampType) {
TimestampType timestampType = (TimestampType) type;
String representation;
if (timestampType.isShort()) {
representation = TimestampToVarcharCast.cast(timestampType.getPrecision(), (Long) object).toStringUtf8();
} else {
representation = TimestampToVarcharCast.cast(timestampType.getPrecision(), (LongTimestamp) object).toStringUtf8();
}
return new TimestampLiteral(representation);
}
if (type instanceof TimestampWithTimeZoneType) {
TimestampWithTimeZoneType timestampWithTimeZoneType = (TimestampWithTimeZoneType) type;
String representation;
if (timestampWithTimeZoneType.isShort()) {
representation = TimestampWithTimeZoneToVarcharCast.cast(timestampWithTimeZoneType.getPrecision(), (long) object).toStringUtf8();
} else {
representation = TimestampWithTimeZoneToVarcharCast.cast(timestampWithTimeZoneType.getPrecision(), (LongTimestampWithTimeZone) object).toStringUtf8();
}
if (!object.equals(parseTimestampWithTimeZone(timestampWithTimeZoneType.getPrecision(), representation))) {
// Certain (point in time, time zone) pairs cannot be represented as a TIMESTAMP literal, as the literal uses local date/time in given time zone.
// Thus, during DST backwards change by e.g. 1 hour, the local time is "repeated" twice and thus one local date/time logically corresponds to two
// points in time, leaving one of them non-referencable.
// TODO (https://github.com/trinodb/trino/issues/5781) consider treating such values as illegal
} else {
return new TimestampLiteral(representation);
}
}
// If the stack value is not a simple type, encode the stack value in a block
if (!type.getJavaType().isPrimitive() && type.getJavaType() != Slice.class && type.getJavaType() != Block.class) {
object = nativeValueToBlock(type, object);
}
if (object instanceof Block) {
SliceOutput output = new DynamicSliceOutput(toIntExact(((Block) object).getSizeInBytes()));
BlockSerdeUtil.writeBlock(plannerContext.getBlockEncodingSerde(), output, (Block) object);
object = output.slice();
// This if condition will evaluate to true: object instanceof Slice && !type.equals(VARCHAR)
}
Type argumentType = typeForMagicLiteral(type);
Expression argument;
if (object instanceof Slice) {
// HACK: we need to serialize VARBINARY in a format that can be embedded in an expression to be
// able to encode it in the plan that gets sent to workers.
// We do this by transforming the in-memory varbinary into a call to from_base64(<base64-encoded value>)
Slice encoded = VarbinaryFunctions.toBase64((Slice) object);
argument = FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(QualifiedName.of("from_base64")).addArgument(VARCHAR, new StringLiteral(encoded.toStringUtf8())).build();
} else {
argument = toExpression(session, object, argumentType);
}
ResolvedFunction resolvedFunction = plannerContext.getMetadata().getCoercion(session, QualifiedName.of(LITERAL_FUNCTION_NAME), argumentType, type);
return FunctionCallBuilder.resolve(session, plannerContext.getMetadata()).setName(resolvedFunction.toQualifiedName()).addArgument(argumentType, argument).build();
}
use of io.trino.spi.type.TimestampWithTimeZoneType in project trino by trinodb.
the class FormatFunction method valueConverter.
private static BiFunction<ConnectorSession, Block, Object> valueConverter(FunctionDependencies functionDependencies, Type type, int position) {
if (type.equals(UNKNOWN)) {
return (session, block) -> null;
}
if (type.equals(BOOLEAN)) {
return (session, block) -> type.getBoolean(block, position);
}
if (type.equals(TINYINT) || type.equals(SMALLINT) || type.equals(INTEGER) || type.equals(BIGINT)) {
return (session, block) -> type.getLong(block, position);
}
if (type.equals(REAL)) {
return (session, block) -> intBitsToFloat(toIntExact(type.getLong(block, position)));
}
if (type.equals(DOUBLE)) {
return (session, block) -> type.getDouble(block, position);
}
if (type.equals(DATE)) {
return (session, block) -> LocalDate.ofEpochDay(type.getLong(block, position));
}
if (type instanceof TimestampWithTimeZoneType) {
return (session, block) -> toZonedDateTime(((TimestampWithTimeZoneType) type), block, position);
}
if (type instanceof TimestampType) {
return (session, block) -> toLocalDateTime(((TimestampType) type), block, position);
}
if (type instanceof TimeType) {
return (session, block) -> toLocalTime(type.getLong(block, position));
}
// TODO: support TIME WITH TIME ZONE by https://github.com/trinodb/trino/issues/191 + mapping to java.time.OffsetTime
if (type.equals(JSON)) {
MethodHandle handle = functionDependencies.getFunctionInvoker(QualifiedName.of("json_format"), ImmutableList.of(JSON), simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
return (session, block) -> convertToString(handle, type.getSlice(block, position));
}
if (isShortDecimal(type)) {
int scale = ((DecimalType) type).getScale();
return (session, block) -> BigDecimal.valueOf(type.getLong(block, position), scale);
}
if (isLongDecimal(type)) {
int scale = ((DecimalType) type).getScale();
return (session, block) -> new BigDecimal(((Int128) type.getObject(block, position)).toBigInteger(), scale);
}
if (type instanceof VarcharType) {
return (session, block) -> type.getSlice(block, position).toStringUtf8();
}
if (type instanceof CharType) {
CharType charType = (CharType) type;
return (session, block) -> padSpaces(type.getSlice(block, position), charType).toStringUtf8();
}
BiFunction<ConnectorSession, Block, Object> function;
if (type.getJavaType() == long.class) {
function = (session, block) -> type.getLong(block, position);
} else if (type.getJavaType() == double.class) {
function = (session, block) -> type.getDouble(block, position);
} else if (type.getJavaType() == boolean.class) {
function = (session, block) -> type.getBoolean(block, position);
} else if (type.getJavaType() == Slice.class) {
function = (session, block) -> type.getSlice(block, position);
} else {
function = (session, block) -> type.getObject(block, position);
}
MethodHandle handle = functionDependencies.getCastInvoker(type, VARCHAR, simpleConvention(FAIL_ON_NULL, NEVER_NULL)).getMethodHandle();
return (session, block) -> convertToString(handle, function.apply(session, block));
}
use of io.trino.spi.type.TimestampWithTimeZoneType in project trino by trinodb.
the class CheckpointSchemaManager method getAddEntryType.
public RowType getAddEntryType(MetadataEntry metadataEntry) {
List<ColumnMetadata> allColumns = extractSchema(metadataEntry, typeManager);
List<ColumnMetadata> minMaxColumns = columnsWithStats(metadataEntry, typeManager);
ImmutableList.Builder<RowType.Field> minMaxFields = ImmutableList.builder();
for (ColumnMetadata dataColumn : minMaxColumns) {
Type type = dataColumn.getType();
if (type instanceof TimestampWithTimeZoneType) {
minMaxFields.add(RowType.field(dataColumn.getName(), TimestampType.TIMESTAMP_MILLIS));
} else {
minMaxFields.add(RowType.field(dataColumn.getName(), type));
}
}
ImmutableList.Builder<RowType.Field> statsColumns = ImmutableList.builder();
statsColumns.add(RowType.field("numRecords", BigintType.BIGINT));
List<RowType.Field> minMax = minMaxFields.build();
if (!minMax.isEmpty()) {
RowType minMaxType = RowType.from(minMax);
statsColumns.add(RowType.field("minValues", minMaxType));
statsColumns.add(RowType.field("maxValues", minMaxType));
}
statsColumns.add(RowType.field("nullCount", RowType.from(allColumns.stream().map(column -> buildNullCountType(Optional.of(column.getName()), column.getType())).collect(toImmutableList()))));
MapType stringMap = (MapType) typeManager.getType(TypeSignature.mapType(VarcharType.VARCHAR.getTypeSignature(), VarcharType.VARCHAR.getTypeSignature()));
List<RowType.Field> addFields = ImmutableList.of(RowType.field("path", VarcharType.createUnboundedVarcharType()), RowType.field("partitionValues", stringMap), RowType.field("size", BigintType.BIGINT), RowType.field("modificationTime", BigintType.BIGINT), RowType.field("dataChange", BooleanType.BOOLEAN), RowType.field("stats", VarcharType.createUnboundedVarcharType()), RowType.field("stats_parsed", RowType.from(statsColumns.build())), RowType.field("tags", stringMap));
return RowType.from(addFields);
}
use of io.trino.spi.type.TimestampWithTimeZoneType in project trino by trinodb.
the class DeltaLakeParquetStatisticsUtils method getMin.
private static Optional<Object> getMin(Type type, Statistics<?> statistics) {
if (statistics.genericGetMin() == null) {
return Optional.empty();
}
if (type.equals(DateType.DATE)) {
checkArgument(statistics instanceof IntStatistics, "Column with DATE type contained invalid statistics: %s", statistics);
IntStatistics intStatistics = (IntStatistics) statistics;
LocalDate date = LocalDate.ofEpochDay(intStatistics.genericGetMin());
return Optional.of(date.format(ISO_LOCAL_DATE));
}
if (type instanceof TimestampWithTimeZoneType) {
if (statistics instanceof LongStatistics) {
Instant ts = Instant.ofEpochMilli(((LongStatistics) statistics).genericGetMin());
return Optional.of(ISO_INSTANT.format(ZonedDateTime.ofInstant(ts, UTC)));
} else if (statistics instanceof BinaryStatistics) {
DecodedTimestamp decodedTimestamp = decodeInt96Timestamp(((BinaryStatistics) statistics).genericGetMin());
Instant ts = Instant.ofEpochSecond(decodedTimestamp.getEpochSeconds(), decodedTimestamp.getNanosOfSecond());
return Optional.of(ISO_INSTANT.format(ZonedDateTime.ofInstant(ts, UTC).truncatedTo(MILLIS)));
}
}
if (type.equals(BIGINT) || type.equals(TINYINT) || type.equals(SMALLINT) || type.equals(INTEGER)) {
checkArgument(statistics instanceof IntStatistics || statistics instanceof LongStatistics, "Column with %s type contained invalid statistics: %s", type, statistics);
return Optional.of(statistics.genericGetMin());
}
if (type.equals(REAL)) {
checkArgument(statistics instanceof FloatStatistics, "Column with REAL type contained invalid statistics: %s", statistics);
Float min = ((FloatStatistics) statistics).genericGetMin();
return Optional.of(min.compareTo(-0.0f) == 0 ? 0.0f : min);
}
if (type.equals(DOUBLE)) {
checkArgument(statistics instanceof DoubleStatistics, "Column with DOUBLE type contained invalid statistics: %s", statistics);
Double min = ((DoubleStatistics) statistics).genericGetMin();
return Optional.of(min.compareTo(-0.0d) == 0 ? 0.0d : min);
}
if (type instanceof DecimalType) {
LogicalTypeAnnotation logicalType = statistics.type().getLogicalTypeAnnotation();
checkArgument(logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation, "DECIMAL column had invalid Parquet Logical Type: %s", logicalType);
int scale = ((LogicalTypeAnnotation.DecimalLogicalTypeAnnotation) logicalType).getScale();
BigDecimal min;
if (statistics instanceof IntStatistics) {
min = BigDecimal.valueOf(((IntStatistics) statistics).getMin()).movePointLeft(scale);
return Optional.of(min.toPlainString());
} else if (statistics instanceof LongStatistics) {
min = BigDecimal.valueOf(((LongStatistics) statistics).getMin()).movePointLeft(scale);
return Optional.of(min.toPlainString());
} else if (statistics instanceof BinaryStatistics) {
BigInteger base = new BigInteger(((BinaryStatistics) statistics).genericGetMin().getBytes());
min = new BigDecimal(base, scale);
return Optional.of(min.toPlainString());
}
}
if (type instanceof VarcharType) {
return Optional.of(new String(((BinaryStatistics) statistics).genericGetMin().getBytes(), UTF_8));
}
if (type.equals(BOOLEAN)) {
// Boolean columns do not collect min/max stats
return Optional.empty();
}
LOG.warn("Accumulating Parquet statistics with Trino type: %s and Parquet statistics of type: %s is not supported", type, statistics);
return Optional.empty();
}
use of io.trino.spi.type.TimestampWithTimeZoneType in project trino by trinodb.
the class CheckpointEntryIterator method readMinMax.
private Map<String, Object> readMinMax(Block block, int blockPosition, List<ColumnMetadata> eligibleColumns) {
if (block.isNull(blockPosition)) {
// Statistics were not collected
return ImmutableMap.of();
}
Block valuesBlock = block.getObject(blockPosition, Block.class);
ImmutableMap.Builder<String, Object> values = ImmutableMap.builder();
for (int i = 0; i < eligibleColumns.size(); i++) {
ColumnMetadata metadata = eligibleColumns.get(i);
String name = metadata.getName();
Type type = metadata.getType();
if (valuesBlock.isNull(i)) {
continue;
}
if (type instanceof RowType) {
if (checkpointRowStatisticsWritingEnabled) {
// RowType column statistics are not used for query planning, but need to be copied when writing out new Checkpoint files.
values.put(name, valuesBlock.getSingleValueBlock(i));
}
continue;
}
if (type instanceof TimestampWithTimeZoneType) {
Instant instant = Instant.ofEpochMilli(LongMath.divide((Long) readNativeValue(TIMESTAMP_MILLIS, valuesBlock, i), MICROSECONDS_PER_MILLISECOND, UNNECESSARY));
if (!instant.atZone(UTC).toLocalDate().isBefore(START_OF_MODERN_ERA)) {
values.put(name, packDateTimeWithZone(instant.toEpochMilli(), UTC_KEY));
}
continue;
}
values.put(name, readNativeValue(type, valuesBlock, i));
}
return values.buildOrThrow();
}
Aggregations