in xtable-core/src/main/java/org/apache/xtable/delta/DeltaSchemaExtractor.java [73:230]
private InternalSchema toInternalSchema(
DataType dataType,
String parentPath,
boolean nullable,
String comment,
Metadata originalMetadata) {
Map<InternalSchema.MetadataKey, Object> metadata = null;
List<InternalField> fields = null;
InternalType type;
String typeName = dataType.typeName();
// trims parameters to type name for matching
int openParenIndex = typeName.indexOf("(");
String trimmedTypeName = openParenIndex > 0 ? typeName.substring(0, openParenIndex) : typeName;
switch (trimmedTypeName) {
case "integer":
type = InternalType.INT;
break;
case "string":
type = InternalType.STRING;
break;
case "boolean":
type = InternalType.BOOLEAN;
break;
case "float":
type = InternalType.FLOAT;
break;
case "double":
type = InternalType.DOUBLE;
break;
case "binary":
if (originalMetadata.contains(InternalSchema.XTABLE_LOGICAL_TYPE)
&& "uuid".equals(originalMetadata.getString(InternalSchema.XTABLE_LOGICAL_TYPE))) {
type = InternalType.UUID;
} else {
type = InternalType.BYTES;
}
break;
case "long":
type = InternalType.LONG;
break;
case "date":
type = InternalType.DATE;
break;
case "timestamp":
type = InternalType.TIMESTAMP;
metadata = DEFAULT_TIMESTAMP_PRECISION_METADATA;
break;
case "timestamp_ntz":
type = InternalType.TIMESTAMP_NTZ;
metadata = DEFAULT_TIMESTAMP_PRECISION_METADATA;
break;
case "struct":
StructType structType = (StructType) dataType;
fields =
Arrays.stream(structType.fields())
.filter(
field ->
!field
.metadata()
.contains(DeltaPartitionExtractor.DELTA_GENERATION_EXPRESSION))
.map(
field -> {
Integer fieldId =
field.metadata().contains(DELTA_COLUMN_MAPPING_ID)
? (int) field.metadata().getLong(DELTA_COLUMN_MAPPING_ID)
: null;
String fieldComment =
field.getComment().isDefined() ? field.getComment().get() : null;
InternalSchema schema =
toInternalSchema(
field.dataType(),
SchemaUtils.getFullyQualifiedPath(parentPath, field.name()),
field.nullable(),
fieldComment,
field.metadata());
return InternalField.builder()
.name(field.name())
.fieldId(fieldId)
.parentPath(parentPath)
.schema(schema)
.defaultValue(
field.nullable() ? InternalField.Constants.NULL_DEFAULT_VALUE : null)
.build();
})
.collect(CustomCollectors.toList(structType.fields().length));
type = InternalType.RECORD;
break;
case "decimal":
DecimalType decimalType = (DecimalType) dataType;
metadata = new HashMap<>(2, 1.0f);
metadata.put(InternalSchema.MetadataKey.DECIMAL_PRECISION, decimalType.precision());
metadata.put(InternalSchema.MetadataKey.DECIMAL_SCALE, decimalType.scale());
type = InternalType.DECIMAL;
break;
case "array":
ArrayType arrayType = (ArrayType) dataType;
InternalSchema elementSchema =
toInternalSchema(
arrayType.elementType(),
SchemaUtils.getFullyQualifiedPath(
parentPath, InternalField.Constants.ARRAY_ELEMENT_FIELD_NAME),
arrayType.containsNull(),
null,
null);
InternalField elementField =
InternalField.builder()
.name(InternalField.Constants.ARRAY_ELEMENT_FIELD_NAME)
.parentPath(parentPath)
.schema(elementSchema)
.build();
type = InternalType.LIST;
fields = Collections.singletonList(elementField);
break;
case "map":
MapType mapType = (MapType) dataType;
InternalSchema keySchema =
toInternalSchema(
mapType.keyType(),
SchemaUtils.getFullyQualifiedPath(
parentPath, InternalField.Constants.MAP_VALUE_FIELD_NAME),
false,
null,
null);
InternalField keyField =
InternalField.builder()
.name(InternalField.Constants.MAP_KEY_FIELD_NAME)
.parentPath(parentPath)
.schema(keySchema)
.build();
InternalSchema valueSchema =
toInternalSchema(
mapType.valueType(),
SchemaUtils.getFullyQualifiedPath(
parentPath, InternalField.Constants.MAP_VALUE_FIELD_NAME),
mapType.valueContainsNull(),
null,
null);
InternalField valueField =
InternalField.builder()
.name(InternalField.Constants.MAP_VALUE_FIELD_NAME)
.parentPath(parentPath)
.schema(valueSchema)
.build();
type = InternalType.MAP;
fields = Arrays.asList(keyField, valueField);
break;
default:
throw new NotSupportedException("Unsupported type: " + dataType.typeName());
}
return InternalSchema.builder()
.name(trimmedTypeName)
.dataType(type)
.comment(comment)
.isNullable(nullable)
.metadata(metadata)
.fields(fields)
.build();
}