in xtable-core/src/main/java/org/apache/xtable/iceberg/IcebergSchemaExtractor.java [257:379]
private InternalSchema fromIcebergType(
Type iceType, String fieldPath, String doc, boolean isOptional) {
InternalType type;
List<InternalField> fields = null;
Map<InternalSchema.MetadataKey, Object> metadata = null;
switch (iceType.typeId()) {
case STRING:
type = InternalType.STRING;
break;
case INTEGER:
type = InternalType.INT;
break;
case LONG:
type = InternalType.LONG;
break;
case BINARY:
type = InternalType.BYTES;
break;
case BOOLEAN:
type = InternalType.BOOLEAN;
break;
case FLOAT:
type = InternalType.FLOAT;
break;
case DATE:
type = InternalType.DATE;
break;
case TIMESTAMP:
Types.TimestampType timestampType = (Types.TimestampType) iceType;
type =
timestampType.shouldAdjustToUTC() ? InternalType.TIMESTAMP : InternalType.TIMESTAMP_NTZ;
metadata =
Collections.singletonMap(
InternalSchema.MetadataKey.TIMESTAMP_PRECISION,
InternalSchema.MetadataValue.MICROS);
break;
case DOUBLE:
type = InternalType.DOUBLE;
break;
case DECIMAL:
Types.DecimalType decimalType = (Types.DecimalType) iceType;
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 FIXED:
type = InternalType.FIXED;
Types.FixedType fixedType = (Types.FixedType) iceType;
metadata =
Collections.singletonMap(
InternalSchema.MetadataKey.FIXED_BYTES_SIZE, fixedType.length());
break;
case UUID:
type = InternalType.UUID;
metadata = Collections.singletonMap(InternalSchema.MetadataKey.FIXED_BYTES_SIZE, 16);
break;
case STRUCT:
Types.StructType structType = (Types.StructType) iceType;
fields = fromIceberg(structType.fields(), fieldPath);
type = InternalType.RECORD;
break;
case MAP:
Types.MapType mapType = (Types.MapType) iceType;
InternalSchema keySchema =
fromIcebergType(
mapType.keyType(),
getFullyQualifiedPath(fieldPath, InternalField.Constants.MAP_KEY_FIELD_NAME),
null,
false);
InternalField keyField =
InternalField.builder()
.name(InternalField.Constants.MAP_KEY_FIELD_NAME)
.parentPath(fieldPath)
.schema(keySchema)
.fieldId(mapType.keyId())
.build();
InternalSchema valueSchema =
fromIcebergType(
mapType.valueType(),
getFullyQualifiedPath(fieldPath, InternalField.Constants.MAP_VALUE_FIELD_NAME),
null,
mapType.isValueOptional());
InternalField valueField =
InternalField.builder()
.name(InternalField.Constants.MAP_VALUE_FIELD_NAME)
.parentPath(fieldPath)
.schema(valueSchema)
.fieldId(mapType.valueId())
.build();
type = InternalType.MAP;
fields = Arrays.asList(keyField, valueField);
break;
case LIST:
Types.ListType listType = (Types.ListType) iceType;
InternalSchema elementSchema =
fromIcebergType(
listType.elementType(),
getFullyQualifiedPath(fieldPath, InternalField.Constants.ARRAY_ELEMENT_FIELD_NAME),
null,
listType.isElementOptional());
InternalField elementField =
InternalField.builder()
.name(InternalField.Constants.ARRAY_ELEMENT_FIELD_NAME)
.parentPath(fieldPath)
.schema(elementSchema)
.fieldId(listType.elementId())
.build();
type = InternalType.LIST;
fields = Collections.singletonList(elementField);
break;
default:
throw new NotSupportedException("Unsupported type: " + iceType.typeId());
}
return InternalSchema.builder()
.name(iceType.typeId().name().toLowerCase())
.dataType(type)
.comment(doc)
.isNullable(isOptional)
.metadata(metadata)
.fields(fields)
.build();
}