use of org.apache.flink.table.types.logical.LogicalTypeRoot in project flink by apache.
the class LogicalTypeMerging method findCommonNullableType.
@SuppressWarnings("ConstantConditions")
@Nullable
private static LogicalType findCommonNullableType(List<LogicalType> normalizedTypes, boolean hasRawType, boolean hasNullType) {
// all RAW types must be equal
if (hasRawType) {
return findExactlySameType(normalizedTypes);
}
LogicalType resultType = null;
for (LogicalType type : normalizedTypes) {
final LogicalTypeRoot typeRoot = type.getTypeRoot();
// NULL does not affect the result of this loop
if (typeRoot == NULL) {
continue;
}
// result type candidate
if (resultType == null) {
resultType = type;
}
// find special patterns
final LogicalType patternType = findCommonTypePattern(resultType, type);
if (patternType != null) {
resultType = patternType;
continue;
}
// for types of family CONSTRUCTED
if (typeRoot == ARRAY) {
return findCommonArrayType(normalizedTypes);
} else if (typeRoot == MULTISET) {
return findCommonMultisetType(normalizedTypes);
} else if (typeRoot == MAP) {
return findCommonMapType(normalizedTypes);
} else if (typeRoot == ROW) {
return findCommonRowType(normalizedTypes);
}
// this simplifies the following lines as we compare same interval families for example
if (!areSimilarTypes(resultType, type)) {
return null;
}
// for types of family CHARACTER_STRING or BINARY_STRING
if (type.is(CHARACTER_STRING) | type.is(BINARY_STRING)) {
final int length = combineLength(resultType, type);
if (resultType.isAnyOf(VARCHAR, VARBINARY)) {
// variable length types remain variable length types
resultType = createStringType(resultType.getTypeRoot(), length);
} else if (getLength(resultType) != getLength(type)) {
// padding/modification of strings
if (resultType.is(CHAR)) {
resultType = createStringType(VARCHAR, length);
} else if (resultType.is(BINARY)) {
resultType = createStringType(VARBINARY, length);
}
} else {
// for same type with same length
resultType = createStringType(typeRoot, length);
}
} else // for EXACT_NUMERIC types
if (type.is(EXACT_NUMERIC)) {
if (resultType.is(EXACT_NUMERIC)) {
resultType = createCommonExactNumericType(resultType, type);
} else if (resultType.is(APPROXIMATE_NUMERIC)) {
// the result is already approximate
if (typeRoot == DECIMAL) {
// in case of DECIMAL we enforce DOUBLE
resultType = new DoubleType();
}
} else {
return null;
}
} else // for APPROXIMATE_NUMERIC types
if (type.is(APPROXIMATE_NUMERIC)) {
if (resultType.is(APPROXIMATE_NUMERIC)) {
resultType = createCommonApproximateNumericType(resultType, type);
} else if (resultType.is(EXACT_NUMERIC)) {
// the result was exact so far
if (typeRoot == DECIMAL) {
// in case of DECIMAL we enforce DOUBLE
resultType = new DoubleType();
} else {
// enforce an approximate result
resultType = type;
}
} else {
return null;
}
} else // for DATE
if (type.is(DATE)) {
if (resultType.is(DATE)) {
// for enabling findCommonTypePattern
resultType = new DateType();
} else {
return null;
}
} else // for TIME
if (type.is(TIME)) {
if (resultType.is(TIME)) {
resultType = new TimeType(combinePrecision(resultType, type));
} else {
return null;
}
} else // for TIMESTAMP
if (type.is(TIMESTAMP)) {
if (resultType.is(TIMESTAMP)) {
resultType = createCommonTimestampType(resultType, type);
} else {
return null;
}
} else // for day-time intervals
if (typeRoot == INTERVAL_DAY_TIME) {
resultType = createCommonDayTimeIntervalType((DayTimeIntervalType) resultType, (DayTimeIntervalType) type);
} else // for year-month intervals
if (typeRoot == INTERVAL_YEAR_MONTH) {
resultType = createCommonYearMonthIntervalType((YearMonthIntervalType) resultType, (YearMonthIntervalType) type);
} else // other types are handled by findCommonCastableType
{
return null;
}
}
// NULL type only
if (resultType == null && hasNullType) {
return new NullType();
}
return resultType;
}
use of org.apache.flink.table.types.logical.LogicalTypeRoot in project flink by apache.
the class CommonExecSink method getFieldInfoForLengthEnforcer.
/**
* Returns a List of {@link ConstraintEnforcer.FieldInfo}, each containing the info needed to
* determine whether a string or binary value needs trimming and/or padding.
*/
private List<ConstraintEnforcer.FieldInfo> getFieldInfoForLengthEnforcer(RowType physicalType, LengthEnforcerType enforcerType) {
LogicalTypeRoot staticType = null;
LogicalTypeRoot variableType = null;
int maxLength = 0;
switch(enforcerType) {
case CHAR:
staticType = LogicalTypeRoot.CHAR;
variableType = LogicalTypeRoot.VARCHAR;
maxLength = CharType.MAX_LENGTH;
break;
case BINARY:
staticType = LogicalTypeRoot.BINARY;
variableType = LogicalTypeRoot.VARBINARY;
maxLength = BinaryType.MAX_LENGTH;
}
final List<ConstraintEnforcer.FieldInfo> fieldsAndLengths = new ArrayList<>();
for (int i = 0; i < physicalType.getFieldCount(); i++) {
LogicalType type = physicalType.getTypeAt(i);
boolean isStatic = type.is(staticType);
// Should trim and possibly pad
if ((isStatic && (LogicalTypeChecks.getLength(type) < maxLength)) || (type.is(variableType) && (LogicalTypeChecks.getLength(type) < maxLength))) {
fieldsAndLengths.add(new ConstraintEnforcer.FieldInfo(i, LogicalTypeChecks.getLength(type), isStatic));
} else if (isStatic) {
// Should pad
fieldsAndLengths.add(new ConstraintEnforcer.FieldInfo(i, null, isStatic));
}
}
return fieldsAndLengths;
}
use of org.apache.flink.table.types.logical.LogicalTypeRoot in project flink by apache.
the class IndexGeneratorFactory method createRuntimeIndexGenerator.
private static IndexGenerator createRuntimeIndexGenerator(String index, String[] fieldNames, DataType[] fieldTypes, IndexHelper indexHelper, ZoneId localTimeZoneId) {
final String dynamicIndexPatternStr = indexHelper.extractDynamicIndexPatternStr(index);
final String indexPrefix = index.substring(0, index.indexOf(dynamicIndexPatternStr));
final String indexSuffix = index.substring(indexPrefix.length() + dynamicIndexPatternStr.length());
if (indexHelper.checkIsDynamicIndexWithSystemTimeFormat(index)) {
final String dateTimeFormat = indexHelper.extractDateFormat(index, LogicalTypeRoot.TIMESTAMP_WITH_LOCAL_TIME_ZONE);
return new AbstractTimeIndexGenerator(index, dateTimeFormat) {
@Override
public String generate(RowData row) {
return indexPrefix.concat(LocalDateTime.now(localTimeZoneId).format(dateTimeFormatter)).concat(indexSuffix);
}
};
}
final boolean isDynamicIndexWithFormat = indexHelper.checkIsDynamicIndexWithFormat(index);
final int indexFieldPos = indexHelper.extractIndexFieldPos(index, fieldNames, isDynamicIndexWithFormat);
final LogicalType indexFieldType = fieldTypes[indexFieldPos].getLogicalType();
final LogicalTypeRoot indexFieldLogicalTypeRoot = indexFieldType.getTypeRoot();
// validate index field type
indexHelper.validateIndexFieldType(indexFieldLogicalTypeRoot);
// time extract dynamic index pattern
final RowData.FieldGetter fieldGetter = RowData.createFieldGetter(indexFieldType, indexFieldPos);
if (isDynamicIndexWithFormat) {
final String dateTimeFormat = indexHelper.extractDateFormat(index, indexFieldLogicalTypeRoot);
DynamicFormatter formatFunction = createFormatFunction(indexFieldType, indexFieldLogicalTypeRoot);
return new AbstractTimeIndexGenerator(index, dateTimeFormat) {
@Override
public String generate(RowData row) {
Object fieldOrNull = fieldGetter.getFieldOrNull(row);
final String formattedField;
// TODO we can possibly optimize it to use the nullability of the field
if (fieldOrNull != null) {
formattedField = formatFunction.format(fieldOrNull, dateTimeFormatter);
} else {
formattedField = "null";
}
return indexPrefix.concat(formattedField).concat(indexSuffix);
}
};
}
// general dynamic index pattern
return new IndexGeneratorBase(index) {
@Override
public String generate(RowData row) {
Object indexField = fieldGetter.getFieldOrNull(row);
return indexPrefix.concat(indexField == null ? "null" : indexField.toString()).concat(indexSuffix);
}
};
}
use of org.apache.flink.table.types.logical.LogicalTypeRoot in project flink by apache.
the class LogicalTypeMerging method findCommonChildrenTypes.
@Nullable
private static List<LogicalType> findCommonChildrenTypes(List<LogicalType> normalizedTypes) {
final LogicalType firstType = normalizedTypes.get(0);
final LogicalTypeRoot typeRoot = firstType.getTypeRoot();
final int numberOfChildren = firstType.getChildren().size();
for (LogicalType type : normalizedTypes) {
// all types must have the same root
if (type.getTypeRoot() != typeRoot) {
return null;
}
// all types must have the same number of children
if (type.getChildren().size() != numberOfChildren) {
return null;
}
}
// recursively compute column-wise least restrictive
final List<LogicalType> resultChildren = new ArrayList<>(numberOfChildren);
for (int i = 0; i < numberOfChildren; i++) {
final Optional<LogicalType> childType = findCommonType(new ChildTypeView(normalizedTypes, i));
if (!childType.isPresent()) {
return null;
}
resultChildren.add(childType.get());
}
// no child should be empty at this point
return resultChildren;
}
use of org.apache.flink.table.types.logical.LogicalTypeRoot in project flink by apache.
the class LogicalTypeMerging method findCommonType.
/**
* Returns the most common, more general {@link LogicalType} for a given set of types. If such a
* type exists, all given types can be casted to this more general type.
*
* <p>For example: {@code [INT, BIGINT, DECIMAL(2, 2)]} would lead to {@code DECIMAL(21, 2)}.
*
* <p>This class aims to be compatible with the SQL standard. It is inspired by Apache Calcite's
* {@code SqlTypeFactoryImpl#leastRestrictive} method.
*/
public static Optional<LogicalType> findCommonType(List<LogicalType> types) {
Preconditions.checkArgument(types.size() > 0, "List of types must not be empty.");
// collect statistics first
boolean hasRawType = false;
boolean hasNullType = false;
boolean hasNullableTypes = false;
for (LogicalType type : types) {
final LogicalTypeRoot typeRoot = type.getTypeRoot();
if (typeRoot == RAW) {
hasRawType = true;
} else if (typeRoot == NULL) {
hasNullType = true;
}
if (type.isNullable()) {
hasNullableTypes = true;
}
}
final List<LogicalType> normalizedTypes = types.stream().map(t -> t.copy(true)).collect(Collectors.toList());
LogicalType foundType = findCommonNullableType(normalizedTypes, hasRawType, hasNullType);
if (foundType == null) {
foundType = findCommonCastableType(normalizedTypes);
}
if (foundType != null) {
final LogicalType typeWithNullability = foundType.copy(hasNullableTypes);
// NULL is reserved for untyped literals only
if (typeWithNullability.is(NULL)) {
return Optional.empty();
}
return Optional.of(typeWithNullability);
}
return Optional.empty();
}
Aggregations