flink-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From GitBox <...@apache.org>
Subject [GitHub] [flink] dawidwys commented on a change in pull request #8555: [FLINK-12254][table-common] More preparation for using the new type system
Date Tue, 28 May 2019 09:26:08 GMT
dawidwys commented on a change in pull request #8555: [FLINK-12254][table-common] More preparation
for using the new type system
URL: https://github.com/apache/flink/pull/8555#discussion_r287961719
 
 

 ##########
 File path: flink-table/flink-table-common/src/main/java/org/apache/flink/table/types/utils/ValueDataTypeConverter.java
 ##########
 @@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.flink.table.types.utils;
+
+import org.apache.flink.annotation.Internal;
+import org.apache.flink.table.api.DataTypes;
+import org.apache.flink.table.types.AtomicDataType;
+import org.apache.flink.table.types.DataType;
+import org.apache.flink.table.types.logical.BinaryType;
+import org.apache.flink.table.types.logical.CharType;
+import org.apache.flink.table.types.logical.LogicalTypeFamily;
+
+import java.math.BigDecimal;
+import java.util.Optional;
+
+/**
+ * Value-based data type extractor that supports extraction of clearly identifiable data
types for
+ * input conversion.
+ *
+ * <p>This converter is more precise than {@link ClassDataTypeConverter} because it
also considers
+ * nullability, length, precision, and scale of values.
+ */
+@Internal
+public final class ValueDataTypeConverter {
+
+	/**
+	 * Returns the clearly identifiable data type if possible. For example, {@code 12L} can
be
+	 * expressed as {@code DataTypes.BIGINT().notNull()}. However, for example, {@code null}
could
+	 * be any type and is not supported.
+	 *
+	 * <p>All types of the {@link LogicalTypeFamily#PREDEFINED} family and arrays are
supported.
+	 */
+	public static Optional<DataType> extractDataType(Object value) {
+		if (value == null) {
+			return Optional.empty();
+		}
+
+		DataType convertedDataType = null;
+
+		if (value instanceof String) {
+			convertedDataType = convertToCharType((String) value);
+		}
+
+		// byte arrays have higher priority than regular arrays
+		else if (value instanceof byte[]) {
+			convertedDataType = convertToBinaryType((byte[]) value);
+		}
+
+		else if (value instanceof BigDecimal) {
+			convertedDataType = convertToDecimalType((BigDecimal) value);
+		}
+
+		else if (value instanceof java.time.LocalTime) {
+			convertedDataType = convertToTimeType((java.time.LocalTime) value);
+		}
+
+		else if (value instanceof java.time.LocalDateTime) {
+			convertedDataType = convertToTimestampType(((java.time.LocalDateTime) value).getNano());
+		}
+
+		else if (value instanceof java.sql.Timestamp) {
+			convertedDataType = convertToTimestampType(((java.sql.Timestamp) value).getNanos());
+		}
+
+		else if (value instanceof java.time.ZonedDateTime) {
+			convertedDataType = convertToZonedTimestampType(((java.time.ZonedDateTime) value).getNano());
+		}
+
+		else if (value instanceof java.time.OffsetDateTime) {
+			convertedDataType = convertToZonedTimestampType(((java.time.OffsetDateTime) value).getNano());
+		}
+
+		else if (value instanceof java.time.Instant) {
+			convertedDataType = convertToLocalZonedTimestampType(((java.time.Instant) value).getNano());
+		}
+
+		else if (value instanceof java.time.Period) {
+			convertedDataType = convertToYearMonthIntervalType(((java.time.Period) value).getYears());
+		}
+
+		else if (value instanceof java.time.Duration) {
+			final java.time.Duration duration = (java.time.Duration) value;
+			convertedDataType = convertToDayTimeIntervalType(duration.toDays(), duration.getNano());
+		}
+
+		else if (value instanceof Object[]) {
+			// don't let the class-based extraction kick in if array elements differ
+			return convertToArrayType((Object[]) value)
+				.map(dt -> dt.notNull().bridgedTo(value.getClass()));
+		}
+
+		final Optional<DataType> resultType;
+		if (convertedDataType != null) {
+			resultType = Optional.of(convertedDataType);
+		} else {
+			// class-based extraction is possible for BOOLEAN, TINYINT, SMALLINT, INT, FLOAT, DOUBLE,
+			// DATE, TIME with java.sql.Time, and arrays of primitive types
+			resultType = ClassDataTypeConverter.extractDataType(value.getClass());
+		}
+		return resultType.map(dt -> dt.notNull().bridgedTo(value.getClass()));
+	}
+
+	private static DataType convertToCharType(String string) {
+		if (string.isEmpty()) {
+			return new AtomicDataType(CharType.ofEmptyLiteral());
+		}
+		return DataTypes.CHAR(string.length());
+	}
+
+	private static DataType convertToBinaryType(byte[] bytes) {
+		if (bytes.length == 0) {
+			return new AtomicDataType(BinaryType.ofEmptyLiteral());
+		}
+		return DataTypes.BINARY(bytes.length);
+	}
+
+	private static DataType convertToDecimalType(BigDecimal decimal) {
+		// let underlying layers check if precision and scale are supported
+		return DataTypes.DECIMAL(decimal.precision(), decimal.scale());
+	}
+
+	private static DataType convertToTimeType(java.time.LocalTime time) {
+		return DataTypes.TIME(fractionalSecondPrecision(time.getNano()));
+	}
+
+	private static DataType convertToTimestampType(int nanos) {
+		return DataTypes.TIMESTAMP(fractionalSecondPrecision(nanos));
+	}
+
+	private static DataType convertToZonedTimestampType(int nanos) {
+		return DataTypes.TIMESTAMP_WITH_TIME_ZONE(fractionalSecondPrecision(nanos));
+	}
+
+	private static DataType convertToLocalZonedTimestampType(int nanos) {
+		return DataTypes.TIMESTAMP_WITH_LOCAL_TIME_ZONE(fractionalSecondPrecision(nanos));
+	}
+
+	private static DataType convertToYearMonthIntervalType(int years) {
+		return DataTypes.INTERVAL(DataTypes.YEAR(yearPrecision(years)), DataTypes.MONTH());
+	}
+
+	private static DataType convertToDayTimeIntervalType(long days, int nanos) {
+		return DataTypes.INTERVAL(
+			DataTypes.DAY(dayPrecision(days)),
+			DataTypes.SECOND(fractionalSecondPrecision(nanos)));
+	}
+
+	private static Optional<DataType> convertToArrayType(Object[] array) {
+		DataType elementType = null;
+
+		// fallback to class based-extraction if no elements exist
+		if (array.length == 0) {
+			final Optional<DataType> possibleElementType =
+				ClassDataTypeConverter.extractDataType(array.getClass().getComponentType());
+
+			if (possibleElementType.isPresent()) {
+				// for simplification, we assume that array elements can always be nullable
+				elementType = possibleElementType.get().nullable();
+			}
+		}
+
+		for (Object element : array) {
+			// null values are wildcard array elements
+			if (element == null) {
+				continue;
 
 Review comment:
   Shouldn't we fallback to the component class type backed type if all the elements are `null`?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

Mime
View raw message