Search in sources :

Example 1 with CollectionDataType

use of org.apache.flink.table.types.CollectionDataType in project flink by apache.

the class DataFormatConverters method getConverterForDataType.

/**
 * Get {@link DataFormatConverter} for {@link DataType}.
 *
 * @param originDataType DataFormatConverter is oriented to Java format, while LogicalType has
 *     lost its specific Java format. Only DataType retains all its Java format information.
 */
public static DataFormatConverter getConverterForDataType(DataType originDataType) {
    DataType dataType = originDataType.nullable();
    DataFormatConverter converter = TYPE_TO_CONVERTER.get(dataType);
    if (converter != null) {
        return converter;
    }
    Class<?> clazz = dataType.getConversionClass();
    LogicalType logicalType = dataType.getLogicalType();
    switch(logicalType.getTypeRoot()) {
        case CHAR:
        case VARCHAR:
            if (clazz == String.class) {
                return StringConverter.INSTANCE;
            } else if (clazz == StringData.class) {
                return StringDataConverter.INSTANCE;
            } else {
                throw new RuntimeException("Not support class for VARCHAR: " + clazz);
            }
        case BINARY:
        case VARBINARY:
            return PrimitiveByteArrayConverter.INSTANCE;
        case DECIMAL:
            Tuple2<Integer, Integer> ps = getPrecision(logicalType);
            if (clazz == BigDecimal.class) {
                return new BigDecimalConverter(ps.f0, ps.f1);
            } else if (clazz == DecimalData.class) {
                return new DecimalDataConverter(ps.f0, ps.f1);
            } else {
                throw new RuntimeException("Not support conversion class for DECIMAL: " + clazz);
            }
        case TIMESTAMP_WITHOUT_TIME_ZONE:
            int precisionOfTS = getDateTimePrecision(logicalType);
            if (clazz == Timestamp.class) {
                return new TimestampConverter(precisionOfTS);
            } else if (clazz == LocalDateTime.class) {
                return new LocalDateTimeConverter(precisionOfTS);
            } else if (clazz == TimestampData.class) {
                return new TimestampDataConverter(precisionOfTS);
            } else {
                throw new RuntimeException("Not support conversion class for TIMESTAMP WITHOUT TIME ZONE: " + clazz);
            }
        case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
            int precisionOfLZTS = getDateTimePrecision(logicalType);
            if (clazz == Instant.class) {
                return new InstantConverter(precisionOfLZTS);
            } else if (clazz == Long.class || clazz == long.class) {
                return new LongTimestampDataConverter(precisionOfLZTS);
            } else if (clazz == TimestampData.class) {
                return new TimestampDataConverter(precisionOfLZTS);
            } else if (clazz == Timestamp.class) {
                return new TimestampLtzConverter(precisionOfLZTS);
            } else {
                throw new RuntimeException("Not support conversion class for TIMESTAMP WITH LOCAL TIME ZONE: " + clazz);
            }
        case ARRAY:
            if (clazz == ArrayData.class) {
                return ArrayDataConverter.INSTANCE;
            } else if (clazz == boolean[].class) {
                return PrimitiveBooleanArrayConverter.INSTANCE;
            } else if (clazz == short[].class) {
                return PrimitiveShortArrayConverter.INSTANCE;
            } else if (clazz == int[].class) {
                return PrimitiveIntArrayConverter.INSTANCE;
            } else if (clazz == long[].class) {
                return PrimitiveLongArrayConverter.INSTANCE;
            } else if (clazz == float[].class) {
                return PrimitiveFloatArrayConverter.INSTANCE;
            } else if (clazz == double[].class) {
                return PrimitiveDoubleArrayConverter.INSTANCE;
            }
            if (dataType instanceof CollectionDataType) {
                return new ObjectArrayConverter(((CollectionDataType) dataType).getElementDataType().bridgedTo(clazz.getComponentType()));
            } else {
                BasicArrayTypeInfo typeInfo = (BasicArrayTypeInfo) ((LegacyTypeInformationType) dataType.getLogicalType()).getTypeInformation();
                return new ObjectArrayConverter(fromLegacyInfoToDataType(typeInfo.getComponentInfo()).bridgedTo(clazz.getComponentType()));
            }
        case MAP:
            if (clazz == MapData.class) {
                return MapDataConverter.INSTANCE;
            }
            KeyValueDataType keyValueDataType = (KeyValueDataType) dataType;
            return new MapConverter(keyValueDataType.getKeyDataType(), keyValueDataType.getValueDataType());
        case MULTISET:
            if (clazz == MapData.class) {
                return MapDataConverter.INSTANCE;
            }
            CollectionDataType collectionDataType = (CollectionDataType) dataType;
            return new MapConverter(collectionDataType.getElementDataType(), DataTypes.INT().bridgedTo(Integer.class));
        case ROW:
        case STRUCTURED_TYPE:
            TypeInformation<?> asTypeInfo = fromDataTypeToTypeInfo(dataType);
            if (asTypeInfo instanceof InternalTypeInfo && clazz == RowData.class) {
                LogicalType realLogicalType = ((InternalTypeInfo<?>) asTypeInfo).toLogicalType();
                return new RowDataConverter(getFieldCount(realLogicalType));
            }
            // legacy
            CompositeType compositeType = (CompositeType) asTypeInfo;
            DataType[] fieldTypes = Stream.iterate(0, x -> x + 1).limit(compositeType.getArity()).map((Function<Integer, TypeInformation>) compositeType::getTypeAt).map(TypeConversions::fromLegacyInfoToDataType).toArray(DataType[]::new);
            if (clazz == RowData.class) {
                return new RowDataConverter(compositeType.getArity());
            } else if (clazz == Row.class) {
                return new RowConverter(fieldTypes);
            } else if (Tuple.class.isAssignableFrom(clazz)) {
                return new TupleConverter((Class<Tuple>) clazz, fieldTypes);
            } else if (CaseClassConverter.PRODUCT_CLASS != null && CaseClassConverter.PRODUCT_CLASS.isAssignableFrom(clazz)) {
                return new CaseClassConverter((TupleTypeInfoBase) compositeType, fieldTypes);
            } else if (compositeType instanceof PojoTypeInfo) {
                return new PojoConverter((PojoTypeInfo) compositeType, fieldTypes);
            } else {
                throw new IllegalStateException("Cannot find a converter for type " + compositeType + ". If the target should be a converter to scala.Product, then you might have a scala classpath issue.");
            }
        case RAW:
            if (logicalType instanceof RawType) {
                final RawType<?> rawType = (RawType<?>) logicalType;
                if (clazz == RawValueData.class) {
                    return RawValueDataConverter.INSTANCE;
                } else {
                    return new GenericConverter<>(rawType.getTypeSerializer());
                }
            }
            // legacy
            TypeInformation typeInfo = logicalType instanceof LegacyTypeInformationType ? ((LegacyTypeInformationType) logicalType).getTypeInformation() : ((TypeInformationRawType) logicalType).getTypeInformation();
            // planner type info
            if (typeInfo instanceof StringDataTypeInfo) {
                return StringDataConverter.INSTANCE;
            } else if (typeInfo instanceof DecimalDataTypeInfo) {
                DecimalDataTypeInfo decimalType = (DecimalDataTypeInfo) typeInfo;
                return new DecimalDataConverter(decimalType.precision(), decimalType.scale());
            } else if (typeInfo instanceof BigDecimalTypeInfo) {
                BigDecimalTypeInfo decimalType = (BigDecimalTypeInfo) typeInfo;
                return new BigDecimalConverter(decimalType.precision(), decimalType.scale());
            } else if (typeInfo instanceof TimestampDataTypeInfo) {
                TimestampDataTypeInfo timestampDataTypeInfo = (TimestampDataTypeInfo) typeInfo;
                return new TimestampDataConverter(timestampDataTypeInfo.getPrecision());
            } else if (typeInfo instanceof LegacyLocalDateTimeTypeInfo) {
                LegacyLocalDateTimeTypeInfo dateTimeType = (LegacyLocalDateTimeTypeInfo) typeInfo;
                return new LocalDateTimeConverter(dateTimeType.getPrecision());
            } else if (typeInfo instanceof LegacyTimestampTypeInfo) {
                LegacyTimestampTypeInfo timestampType = (LegacyTimestampTypeInfo) typeInfo;
                return new TimestampConverter(timestampType.getPrecision());
            } else if (typeInfo instanceof LegacyInstantTypeInfo) {
                LegacyInstantTypeInfo instantTypeInfo = (LegacyInstantTypeInfo) typeInfo;
                return new InstantConverter(instantTypeInfo.getPrecision());
            }
            if (clazz == RawValueData.class) {
                return RawValueDataConverter.INSTANCE;
            }
            return new GenericConverter(typeInfo.createSerializer(new ExecutionConfig()));
        default:
            throw new RuntimeException("Not support dataType: " + dataType);
    }
}
Also used : DecimalDataTypeInfo(org.apache.flink.table.runtime.typeutils.DecimalDataTypeInfo) LogicalType(org.apache.flink.table.types.logical.LogicalType) PojoTypeInfo(org.apache.flink.api.java.typeutils.PojoTypeInfo) TypeInformation(org.apache.flink.api.common.typeinfo.TypeInformation) RawType(org.apache.flink.table.types.logical.RawType) TypeInformationRawType(org.apache.flink.table.types.logical.TypeInformationRawType) BigDecimalTypeInfo(org.apache.flink.table.runtime.typeutils.BigDecimalTypeInfo) InternalTypeInfo(org.apache.flink.table.runtime.typeutils.InternalTypeInfo) LegacyTimestampTypeInfo(org.apache.flink.table.runtime.typeutils.LegacyTimestampTypeInfo) Row(org.apache.flink.types.Row) BasicArrayTypeInfo(org.apache.flink.api.common.typeinfo.BasicArrayTypeInfo) LocalDateTime(java.time.LocalDateTime) CollectionDataType(org.apache.flink.table.types.CollectionDataType) ExecutionConfig(org.apache.flink.api.common.ExecutionConfig) Timestamp(java.sql.Timestamp) DecimalData(org.apache.flink.table.data.DecimalData) LegacyInstantTypeInfo(org.apache.flink.table.runtime.typeutils.LegacyInstantTypeInfo) GenericRowData(org.apache.flink.table.data.GenericRowData) RowData(org.apache.flink.table.data.RowData) TupleTypeInfoBase(org.apache.flink.api.java.typeutils.TupleTypeInfoBase) DataType(org.apache.flink.table.types.DataType) CollectionDataType(org.apache.flink.table.types.CollectionDataType) KeyValueDataType(org.apache.flink.table.types.KeyValueDataType) TypeConversions.fromLegacyInfoToDataType(org.apache.flink.table.types.utils.TypeConversions.fromLegacyInfoToDataType) TimestampDataTypeInfo(org.apache.flink.table.runtime.typeutils.TimestampDataTypeInfo) KeyValueDataType(org.apache.flink.table.types.KeyValueDataType) StringDataTypeInfo(org.apache.flink.table.runtime.typeutils.StringDataTypeInfo) LegacyTypeInformationType(org.apache.flink.table.types.logical.LegacyTypeInformationType) LegacyLocalDateTimeTypeInfo(org.apache.flink.table.runtime.typeutils.LegacyLocalDateTimeTypeInfo) StringData(org.apache.flink.table.data.StringData) Tuple(org.apache.flink.api.java.tuple.Tuple) CompositeType(org.apache.flink.api.common.typeutils.CompositeType)

Example 2 with CollectionDataType

use of org.apache.flink.table.types.CollectionDataType in project flink by apache.

the class LegacyTypeInfoDataTypeConverter method toLegacyTypeInfo.

public static TypeInformation<?> toLegacyTypeInfo(DataType dataType) {
    // time indicators first as their hashCode/equals is shared with those of regular timestamps
    if (canConvertToTimeAttributeTypeInfo(dataType)) {
        return convertToTimeAttributeTypeInfo(dataType.getLogicalType());
    }
    // check in the map but relax the nullability constraint as every not null data type can be
    // stored in the corresponding nullable type information
    final TypeInformation<?> foundTypeInfo = dataTypeTypeInfoMap.get(dataType.nullable().bridgedTo(primitiveToWrapper(dataType.getConversionClass())));
    if (foundTypeInfo != null) {
        return foundTypeInfo;
    }
    // we are relaxing the constraint for DECIMAL, CHAR, VARCHAR, TIMESTAMP_WITHOUT_TIME_ZONE to
    // support value literals in legacy planner
    LogicalType logicalType = dataType.getLogicalType();
    if (logicalType.is(DECIMAL)) {
        return Types.BIG_DEC;
    } else if (logicalType.is(CHAR)) {
        return Types.STRING;
    } else if (logicalType.is(VARCHAR)) {
        return Types.STRING;
    } else // relax the precision constraint as Timestamp can store the highest precision
    if (logicalType.is(TIMESTAMP_WITHOUT_TIME_ZONE) && dataType.getConversionClass() == Timestamp.class) {
        return Types.SQL_TIMESTAMP;
    } else // relax the precision constraint as LocalDateTime can store the highest precision
    if (logicalType.is(TIMESTAMP_WITHOUT_TIME_ZONE) && dataType.getConversionClass() == LocalDateTime.class) {
        return Types.LOCAL_DATE_TIME;
    } else // convert proctime back
    if (logicalType.is(TIMESTAMP_WITH_LOCAL_TIME_ZONE) && dataType.getConversionClass() == Timestamp.class) {
        return Types.SQL_TIMESTAMP;
    } else // relax the precision constraint as LocalTime can store the highest precision
    if (logicalType.is(TIME_WITHOUT_TIME_ZONE) && dataType.getConversionClass() == LocalTime.class) {
        return Types.LOCAL_TIME;
    } else if (canConvertToLegacyTypeInfo(dataType)) {
        return convertToLegacyTypeInfo(dataType);
    } else if (canConvertToRowTypeInfo(dataType)) {
        return convertToRowTypeInfo((FieldsDataType) dataType);
    } else // this could also match for basic array type info but this is covered by legacy type info
    if (canConvertToObjectArrayTypeInfo(dataType)) {
        return convertToObjectArrayTypeInfo((CollectionDataType) dataType);
    } else if (canConvertToMultisetTypeInfo(dataType)) {
        return convertToMultisetTypeInfo((CollectionDataType) dataType);
    } else if (canConvertToMapTypeInfo(dataType)) {
        return convertToMapTypeInfo((KeyValueDataType) dataType);
    } else // makes the raw type accessible in the legacy planner
    if (canConvertToRawTypeInfo(dataType)) {
        return convertToRawTypeInfo(dataType);
    }
    throw new TableException(String.format("Unsupported conversion from data type '%s' (conversion class: %s) to type information. Only data types " + "that originated from type information fully support a reverse conversion.", dataType, dataType.getConversionClass().getName()));
}
Also used : LocalDateTime(java.time.LocalDateTime) TableException(org.apache.flink.table.api.TableException) LocalTime(java.time.LocalTime) CollectionDataType(org.apache.flink.table.types.CollectionDataType) KeyValueDataType(org.apache.flink.table.types.KeyValueDataType) LogicalType(org.apache.flink.table.types.logical.LogicalType)

Example 3 with CollectionDataType

use of org.apache.flink.table.types.CollectionDataType in project flink by apache.

the class ValuesOperationFactory method convertArrayToExpectedType.

private Optional<ResolvedExpression> convertArrayToExpectedType(ResolvedExpression sourceExpression, CollectionDataType targetDataType, ExpressionResolver.PostResolverFactory postResolverFactory) {
    DataType elementTargetDataType = targetDataType.getElementDataType();
    List<ResolvedExpression> resolvedChildren = sourceExpression.getResolvedChildren();
    ResolvedExpression[] castedChildren = new ResolvedExpression[resolvedChildren.size()];
    for (int i = 0; i < resolvedChildren.size(); i++) {
        Optional<ResolvedExpression> castedChild = convertToExpectedType(resolvedChildren.get(i), elementTargetDataType, postResolverFactory);
        if (castedChild.isPresent()) {
            castedChildren[i] = castedChild.get();
        } else {
            return Optional.empty();
        }
    }
    return Optional.of(postResolverFactory.array(targetDataType, castedChildren));
}
Also used : ResolvedExpression(org.apache.flink.table.expressions.ResolvedExpression) DataType(org.apache.flink.table.types.DataType) KeyValueDataType(org.apache.flink.table.types.KeyValueDataType) FieldsDataType(org.apache.flink.table.types.FieldsDataType) CollectionDataType(org.apache.flink.table.types.CollectionDataType)

Example 4 with CollectionDataType

use of org.apache.flink.table.types.CollectionDataType in project flink by apache.

the class DataTypePrecisionFixer method visit.

@Override
public DataType visit(CollectionDataType collectionDataType) {
    DataType elementType = collectionDataType.getElementDataType();
    switch(logicalType.getTypeRoot()) {
        case ARRAY:
            ArrayType arrayType = (ArrayType) logicalType;
            DataType newArrayElementType = elementType.accept(new DataTypePrecisionFixer(arrayType.getElementType()));
            return DataTypes.ARRAY(newArrayElementType).bridgedTo(collectionDataType.getConversionClass());
        case MULTISET:
            MultisetType multisetType = (MultisetType) logicalType;
            DataType newMultisetElementType = elementType.accept(new DataTypePrecisionFixer(multisetType.getElementType()));
            return DataTypes.MULTISET(newMultisetElementType).bridgedTo(collectionDataType.getConversionClass());
        default:
            throw new UnsupportedOperationException("Unsupported logical type : " + logicalType);
    }
}
Also used : ArrayType(org.apache.flink.table.types.logical.ArrayType) DataType(org.apache.flink.table.types.DataType) AtomicDataType(org.apache.flink.table.types.AtomicDataType) KeyValueDataType(org.apache.flink.table.types.KeyValueDataType) CollectionDataType(org.apache.flink.table.types.CollectionDataType) FieldsDataType(org.apache.flink.table.types.FieldsDataType) MultisetType(org.apache.flink.table.types.logical.MultisetType)

Example 5 with CollectionDataType

use of org.apache.flink.table.types.CollectionDataType in project flink by apache.

the class ValuesOperationFactory method convertToExpectedType.

private Optional<ResolvedExpression> convertToExpectedType(ResolvedExpression sourceExpression, DataType targetDataType, ExpressionResolver.PostResolverFactory postResolverFactory) {
    LogicalType sourceLogicalType = sourceExpression.getOutputDataType().getLogicalType();
    LogicalType targetLogicalType = targetDataType.getLogicalType();
    // if the expression is a literal try converting the literal in place instead of casting
    if (sourceExpression instanceof ValueLiteralExpression) {
        // Assign a type to a null literal
        if (sourceLogicalType.is(NULL)) {
            return Optional.of(valueLiteral(null, targetDataType));
        }
        // Check if the source value class is a valid input conversion class of the target type
        // It may happen that a user wanted to use a secondary input conversion class as a value
        // for
        // a different type than what we derived.
        // 
        // Example: we interpreted 1L as BIGINT, but user wanted to interpret it as a TIMESTAMP
        // In this case long is a valid conversion class for TIMESTAMP, but a
        // cast from BIGINT to TIMESTAMP is an invalid operation.
        Optional<Object> value = ((ValueLiteralExpression) sourceExpression).getValueAs(Object.class);
        if (value.isPresent() && targetLogicalType.supportsInputConversion(value.get().getClass())) {
            ValueLiteralExpression convertedLiteral = valueLiteral(value.get(), targetDataType.notNull().bridgedTo(value.get().getClass()));
            if (targetLogicalType.isNullable()) {
                return Optional.of(postResolverFactory.cast(convertedLiteral, targetDataType));
            } else {
                return Optional.of(convertedLiteral);
            }
        }
    }
    if (sourceExpression instanceof CallExpression) {
        FunctionDefinition functionDefinition = ((CallExpression) sourceExpression).getFunctionDefinition();
        if (functionDefinition == BuiltInFunctionDefinitions.ROW && targetLogicalType.is(ROW)) {
            return convertRowToExpectedType(sourceExpression, (FieldsDataType) targetDataType, postResolverFactory);
        } else if (functionDefinition == BuiltInFunctionDefinitions.ARRAY && targetLogicalType.is(ARRAY)) {
            return convertArrayToExpectedType(sourceExpression, (CollectionDataType) targetDataType, postResolverFactory);
        } else if (functionDefinition == BuiltInFunctionDefinitions.MAP && targetLogicalType.is(MAP)) {
            return convertMapToExpectedType(sourceExpression, (KeyValueDataType) targetDataType, postResolverFactory);
        }
    }
    // might know that a certain function will not produce nullable values for a given input
    if (supportsExplicitCast(sourceLogicalType.copy(true), targetLogicalType.copy(true))) {
        return Optional.of(postResolverFactory.cast(sourceExpression, targetDataType));
    } else {
        return Optional.empty();
    }
}
Also used : ValueLiteralExpression(org.apache.flink.table.expressions.ValueLiteralExpression) CollectionDataType(org.apache.flink.table.types.CollectionDataType) LogicalType(org.apache.flink.table.types.logical.LogicalType) FunctionDefinition(org.apache.flink.table.functions.FunctionDefinition) CallExpression(org.apache.flink.table.expressions.CallExpression)

Aggregations

CollectionDataType (org.apache.flink.table.types.CollectionDataType)8 KeyValueDataType (org.apache.flink.table.types.KeyValueDataType)7 DataType (org.apache.flink.table.types.DataType)5 LogicalType (org.apache.flink.table.types.logical.LogicalType)5 LocalDateTime (java.time.LocalDateTime)3 IOException (java.io.IOException)2 List (java.util.List)2 Collectors (java.util.stream.Collectors)2 Internal (org.apache.flink.annotation.Internal)2 DecimalData (org.apache.flink.table.data.DecimalData)2 StringData (org.apache.flink.table.data.StringData)2 FieldsDataType (org.apache.flink.table.types.FieldsDataType)2 Timestamp (java.sql.Timestamp)1 Instant (java.time.Instant)1 LocalTime (java.time.LocalTime)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 Objects (java.util.Objects)1 IntStream (java.util.stream.IntStream)1 Nullable (javax.annotation.Nullable)1