ORC: Fail when initial default support is required. (#12026)

pull/12010/merge
Ryan Blue 18 hours ago committed by GitHub
parent 9a46890e17
commit 5091e5752f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -19,7 +19,6 @@
package org.apache.iceberg.orc;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
@ -264,11 +263,11 @@ public final class ORCSchemaUtil {
public static TypeDescription buildOrcProjection(
Schema schema, TypeDescription originalOrcSchema) {
final Map<Integer, OrcField> icebergToOrc = icebergToOrcMapping("root", originalOrcSchema);
return buildOrcProjection(Integer.MIN_VALUE, schema.asStruct(), true, icebergToOrc);
return buildOrcProjection(schema, Integer.MIN_VALUE, schema.asStruct(), true, icebergToOrc);
}
private static TypeDescription buildOrcProjection(
Integer fieldId, Type type, boolean isRequired, Map<Integer, OrcField> mapping) {
Schema root, Integer fieldId, Type type, boolean isRequired, Map<Integer, OrcField> mapping) {
final TypeDescription orcType;
switch (type.typeId()) {
@ -284,6 +283,7 @@ public final class ORCSchemaUtil {
.orElseGet(() -> nestedField.name() + "_r" + nestedField.fieldId());
TypeDescription childType =
buildOrcProjection(
root,
nestedField.fieldId(),
nestedField.type(),
isRequired && nestedField.isRequired(),
@ -295,6 +295,7 @@ public final class ORCSchemaUtil {
Types.ListType list = (Types.ListType) type;
TypeDescription elementType =
buildOrcProjection(
root,
list.elementId(),
list.elementType(),
isRequired && list.isElementRequired(),
@ -304,10 +305,10 @@ public final class ORCSchemaUtil {
case MAP:
Types.MapType map = (Types.MapType) type;
TypeDescription keyType =
buildOrcProjection(map.keyId(), map.keyType(), isRequired, mapping);
buildOrcProjection(root, map.keyId(), map.keyType(), isRequired, mapping);
TypeDescription valueType =
buildOrcProjection(
map.valueId(), map.valueType(), isRequired && map.isValueRequired(), mapping);
root, map.valueId(), map.valueType(), isRequired && map.isValueRequired(), mapping);
orcType = TypeDescription.createMap(keyType, valueType);
break;
default:
@ -326,13 +327,20 @@ public final class ORCSchemaUtil {
orcType = originalType.clone();
}
} else {
Types.NestedField field = root.findField(fieldId);
if (isRequired) {
throw new IllegalArgumentException(
Preconditions.checkArgument(
field.initialDefault() != null,
"Missing required field: %s (%s)",
root.findColumnName(fieldId),
type);
}
if (field.initialDefault() != null) {
throw new UnsupportedOperationException(
String.format(
Locale.ROOT,
"Field %d of type %s is required and was not found.",
fieldId,
type));
"ORC cannot read default value for field %s (%s): %s",
root.findColumnName(fieldId), type, field.initialDefault()));
}
orcType = convert(fieldId, type, false);

@ -162,6 +162,33 @@ public class TestBuildOrcProjection {
assertThatThrownBy(() -> ORCSchemaUtil.buildOrcProjection(evolvedSchema, baseOrcSchema))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Field 4 of type long is required and was not found.");
.hasMessage("Missing required field: b.d (long)");
}
@Test
public void testRequiredNestedFieldWithDefaultMissingInFile() {
Schema baseSchema =
new Schema(
required(1, "a", Types.IntegerType.get()),
required(2, "b", Types.StructType.of(required(3, "c", Types.LongType.get()))));
TypeDescription baseOrcSchema = ORCSchemaUtil.convert(baseSchema);
Schema evolvedSchema =
new Schema(
required(1, "a", Types.IntegerType.get()),
required(
2,
"b",
Types.StructType.of(
required(3, "c", Types.LongType.get()),
Types.NestedField.required("d")
.withId(4)
.ofType(Types.LongType.get())
.withInitialDefault(34L)
.build())));
assertThatThrownBy(() -> ORCSchemaUtil.buildOrcProjection(evolvedSchema, baseOrcSchema))
.isInstanceOf(UnsupportedOperationException.class)
.hasMessage("ORC cannot read default value for field b.d (long): 34");
}
}

Loading…
Cancel
Save