pvary commented on code in PR #17513:
URL: https://github.com/apache/iceberg/pull/17513#discussion_r3715530260
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
Review Comment:
```suggestion
// a required field is not nullable when every field that contains it is
required
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
Review Comment:
```suggestion
// an optional field is nullable regardless of the fields that contain it
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
Review Comment:
```suggestion
// a required field nested in an optional struct is nullable
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 8)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 9)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithListsAndMaps() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_points",
+ Types.ListType.ofRequired(
+ 4, Types.StructType.of(required(5, "required_x",
Types.LongType.get())))),
+ optional(
+ 2,
+ "optional_points",
+ Types.ListType.ofOptional(
+ 6, Types.StructType.of(required(7, "required_x",
Types.LongType.get())))),
+ required(
+ 3,
+ "locations",
+ Types.MapType.ofRequired(
+ 8,
+ 9,
+ Types.StringType.get(),
+ Types.StructType.of(required(10, "required_lat",
Types.DoubleType.get())))),
+ optional(
+ 11,
+ "optional_lines",
+ Types.ListType.ofRequired(
+ 12, Types.StructType.of(required(13, "required_x",
Types.LongType.get())))),
+ required(
+ 14,
+ "required_shapes",
+ Types.ListType.ofOptional(
+ 15, Types.StructType.of(required(16, "required_x",
Types.LongType.get())))),
+ optional(
+ 17,
+ "optional_locations",
+ Types.MapType.ofRequired(
+ 18,
+ 19,
+ Types.StringType.get(),
+ Types.StructType.of(required(20, "required_lat",
Types.DoubleType.get())))),
+ required(
+ 21,
+ "required_locations",
+ Types.MapType.ofOptional(
+ 22,
+ 23,
+ Types.StringType.get(),
+ Types.StructType.of(required(24, "required_lat",
Types.DoubleType.get())))));
+
+ // a required element of a required list is not null, nor is anything it
contains
Review Comment:
```suggestion
// a required element of a required list is not nullable, nor is
anything it contains
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 8)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 9)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithListsAndMaps() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_points",
+ Types.ListType.ofRequired(
+ 4, Types.StructType.of(required(5, "required_x",
Types.LongType.get())))),
+ optional(
+ 2,
+ "optional_points",
+ Types.ListType.ofOptional(
+ 6, Types.StructType.of(required(7, "required_x",
Types.LongType.get())))),
+ required(
+ 3,
+ "locations",
+ Types.MapType.ofRequired(
+ 8,
+ 9,
+ Types.StringType.get(),
+ Types.StructType.of(required(10, "required_lat",
Types.DoubleType.get())))),
+ optional(
+ 11,
+ "optional_lines",
+ Types.ListType.ofRequired(
+ 12, Types.StructType.of(required(13, "required_x",
Types.LongType.get())))),
+ required(
+ 14,
+ "required_shapes",
+ Types.ListType.ofOptional(
+ 15, Types.StructType.of(required(16, "required_x",
Types.LongType.get())))),
+ optional(
+ 17,
+ "optional_locations",
+ Types.MapType.ofRequired(
+ 18,
+ 19,
+ Types.StringType.get(),
+ Types.StructType.of(required(20, "required_lat",
Types.DoubleType.get())))),
+ required(
+ 21,
+ "required_locations",
+ Types.MapType.ofOptional(
+ 22,
+ 23,
+ Types.StringType.get(),
+ Types.StructType.of(required(24, "required_lat",
Types.DoubleType.get())))));
+
+ // a required element of a required list is not null, nor is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 4)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+
+ // an optional element is null, as is anything it contains
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 6)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+
+ // required map keys and values are not null
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 8)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 9)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 10)).isFalse();
+
+ // a required element of an optional list is null when the list is null
Review Comment:
```suggestion
// a required element of an optional list is nullable
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 8)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 9)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithListsAndMaps() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_points",
+ Types.ListType.ofRequired(
+ 4, Types.StructType.of(required(5, "required_x",
Types.LongType.get())))),
+ optional(
+ 2,
+ "optional_points",
+ Types.ListType.ofOptional(
+ 6, Types.StructType.of(required(7, "required_x",
Types.LongType.get())))),
+ required(
+ 3,
+ "locations",
+ Types.MapType.ofRequired(
+ 8,
+ 9,
+ Types.StringType.get(),
+ Types.StructType.of(required(10, "required_lat",
Types.DoubleType.get())))),
+ optional(
+ 11,
+ "optional_lines",
+ Types.ListType.ofRequired(
+ 12, Types.StructType.of(required(13, "required_x",
Types.LongType.get())))),
+ required(
+ 14,
+ "required_shapes",
+ Types.ListType.ofOptional(
+ 15, Types.StructType.of(required(16, "required_x",
Types.LongType.get())))),
+ optional(
+ 17,
+ "optional_locations",
+ Types.MapType.ofRequired(
+ 18,
+ 19,
+ Types.StringType.get(),
+ Types.StructType.of(required(20, "required_lat",
Types.DoubleType.get())))),
+ required(
+ 21,
+ "required_locations",
+ Types.MapType.ofOptional(
+ 22,
+ 23,
+ Types.StringType.get(),
+ Types.StructType.of(required(24, "required_lat",
Types.DoubleType.get())))));
+
+ // a required element of a required list is not null, nor is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 4)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+
+ // an optional element is null, as is anything it contains
Review Comment:
```suggestion
// an optional element is nullable, as is anything it contains
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 8)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 9)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithListsAndMaps() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_points",
+ Types.ListType.ofRequired(
+ 4, Types.StructType.of(required(5, "required_x",
Types.LongType.get())))),
+ optional(
+ 2,
+ "optional_points",
+ Types.ListType.ofOptional(
+ 6, Types.StructType.of(required(7, "required_x",
Types.LongType.get())))),
+ required(
+ 3,
+ "locations",
+ Types.MapType.ofRequired(
+ 8,
+ 9,
+ Types.StringType.get(),
+ Types.StructType.of(required(10, "required_lat",
Types.DoubleType.get())))),
+ optional(
+ 11,
+ "optional_lines",
+ Types.ListType.ofRequired(
+ 12, Types.StructType.of(required(13, "required_x",
Types.LongType.get())))),
+ required(
+ 14,
+ "required_shapes",
+ Types.ListType.ofOptional(
+ 15, Types.StructType.of(required(16, "required_x",
Types.LongType.get())))),
+ optional(
+ 17,
+ "optional_locations",
+ Types.MapType.ofRequired(
+ 18,
+ 19,
+ Types.StringType.get(),
+ Types.StructType.of(required(20, "required_lat",
Types.DoubleType.get())))),
+ required(
+ 21,
+ "required_locations",
+ Types.MapType.ofOptional(
+ 22,
+ 23,
+ Types.StringType.get(),
+ Types.StructType.of(required(24, "required_lat",
Types.DoubleType.get())))));
+
+ // a required element of a required list is not null, nor is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 4)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+
+ // an optional element is null, as is anything it contains
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 6)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+
+ // required map keys and values are not null
Review Comment:
```suggestion
// required map keys and values are not nullable
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 8)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 9)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithListsAndMaps() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_points",
+ Types.ListType.ofRequired(
+ 4, Types.StructType.of(required(5, "required_x",
Types.LongType.get())))),
+ optional(
+ 2,
+ "optional_points",
+ Types.ListType.ofOptional(
+ 6, Types.StructType.of(required(7, "required_x",
Types.LongType.get())))),
+ required(
+ 3,
+ "locations",
+ Types.MapType.ofRequired(
+ 8,
+ 9,
+ Types.StringType.get(),
+ Types.StructType.of(required(10, "required_lat",
Types.DoubleType.get())))),
+ optional(
+ 11,
+ "optional_lines",
+ Types.ListType.ofRequired(
+ 12, Types.StructType.of(required(13, "required_x",
Types.LongType.get())))),
+ required(
+ 14,
+ "required_shapes",
+ Types.ListType.ofOptional(
+ 15, Types.StructType.of(required(16, "required_x",
Types.LongType.get())))),
+ optional(
+ 17,
+ "optional_locations",
+ Types.MapType.ofRequired(
+ 18,
+ 19,
+ Types.StringType.get(),
+ Types.StructType.of(required(20, "required_lat",
Types.DoubleType.get())))),
+ required(
+ 21,
+ "required_locations",
+ Types.MapType.ofOptional(
+ 22,
+ 23,
+ Types.StringType.get(),
+ Types.StructType.of(required(24, "required_lat",
Types.DoubleType.get())))));
+
+ // a required element of a required list is not null, nor is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 4)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+
+ // an optional element is null, as is anything it contains
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 6)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+
+ // required map keys and values are not null
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 8)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 9)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 10)).isFalse();
+
+ // a required element of an optional list is null when the list is null
+ assertThat(TypeUtil.isNullable(schema, 11)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 12)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 13)).isTrue();
+
+ // an optional element of a required list is null, as is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 14)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 15)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 16)).isTrue();
+
+ // required keys and values of an optional map are null when the map is
null
Review Comment:
```suggestion
// required keys and values of an optional map are nullable
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 8)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 9)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithListsAndMaps() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_points",
+ Types.ListType.ofRequired(
+ 4, Types.StructType.of(required(5, "required_x",
Types.LongType.get())))),
+ optional(
+ 2,
+ "optional_points",
+ Types.ListType.ofOptional(
+ 6, Types.StructType.of(required(7, "required_x",
Types.LongType.get())))),
+ required(
+ 3,
+ "locations",
+ Types.MapType.ofRequired(
+ 8,
+ 9,
+ Types.StringType.get(),
+ Types.StructType.of(required(10, "required_lat",
Types.DoubleType.get())))),
+ optional(
+ 11,
+ "optional_lines",
+ Types.ListType.ofRequired(
+ 12, Types.StructType.of(required(13, "required_x",
Types.LongType.get())))),
+ required(
+ 14,
+ "required_shapes",
+ Types.ListType.ofOptional(
+ 15, Types.StructType.of(required(16, "required_x",
Types.LongType.get())))),
+ optional(
+ 17,
+ "optional_locations",
+ Types.MapType.ofRequired(
+ 18,
+ 19,
+ Types.StringType.get(),
+ Types.StructType.of(required(20, "required_lat",
Types.DoubleType.get())))),
+ required(
+ 21,
+ "required_locations",
+ Types.MapType.ofOptional(
+ 22,
+ 23,
+ Types.StringType.get(),
+ Types.StructType.of(required(24, "required_lat",
Types.DoubleType.get())))));
+
+ // a required element of a required list is not null, nor is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 4)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+
+ // an optional element is null, as is anything it contains
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 6)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+
+ // required map keys and values are not null
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 8)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 9)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 10)).isFalse();
+
+ // a required element of an optional list is null when the list is null
+ assertThat(TypeUtil.isNullable(schema, 11)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 12)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 13)).isTrue();
+
+ // an optional element of a required list is null, as is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 14)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 15)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 16)).isTrue();
+
+ // required keys and values of an optional map are null when the map is
null
+ assertThat(TypeUtil.isNullable(schema, 17)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 18)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 19)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 20)).isTrue();
+
+ // an optional value of a required map is null, as is anything it
contains, but keys are not
Review Comment:
```suggestion
// an optional value of a required map is nullable, as is anything it
contains, but keys are not
```
##########
api/src/test/java/org/apache/iceberg/types/TestTypeUtil.java:
##########
@@ -972,6 +972,151 @@ public void ancestorFieldsInNestedSchema() {
assertThat(TypeUtil.ancestorFields(schema,
17)).containsExactly(pointsElement, points);
}
+ @Test
+ public void isNullableWithUnknownFieldId() {
+ Schema schema = new Schema(required(1, "id", IntegerType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithTopLevelFields() {
+ Schema schema =
+ new Schema(
+ required(1, "id", IntegerType.get()), optional(2, "data",
Types.StringType.get()));
+
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithNestedStructs() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_location",
+ Types.StructType.of(
+ required(3, "required_lat", Types.DoubleType.get()),
+ optional(4, "optional_lon", Types.DoubleType.get()),
+ required(
+ 5,
+ "required_inner",
+ Types.StructType.of(required(6, "required_zip",
IntegerType.get()))))),
+ optional(
+ 2,
+ "optional_location",
+ Types.StructType.of(
+ required(7, "required_lat", Types.DoubleType.get()),
+ required(
+ 8,
+ "required_inner",
+ Types.StructType.of(required(9, "required_zip",
IntegerType.get()))))));
+
+ // a required field is not null when every field that contains it is
required
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 6)).isFalse();
+
+ // an optional field is null regardless of the fields that contain it
+ assertThat(TypeUtil.isNullable(schema, 4)).isTrue();
+
+ // a required field nested in an optional struct is null when the struct
is null
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 8)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 9)).isTrue();
+ }
+
+ @Test
+ public void isNullableWithListsAndMaps() {
+ Schema schema =
+ new Schema(
+ required(
+ 1,
+ "required_points",
+ Types.ListType.ofRequired(
+ 4, Types.StructType.of(required(5, "required_x",
Types.LongType.get())))),
+ optional(
+ 2,
+ "optional_points",
+ Types.ListType.ofOptional(
+ 6, Types.StructType.of(required(7, "required_x",
Types.LongType.get())))),
+ required(
+ 3,
+ "locations",
+ Types.MapType.ofRequired(
+ 8,
+ 9,
+ Types.StringType.get(),
+ Types.StructType.of(required(10, "required_lat",
Types.DoubleType.get())))),
+ optional(
+ 11,
+ "optional_lines",
+ Types.ListType.ofRequired(
+ 12, Types.StructType.of(required(13, "required_x",
Types.LongType.get())))),
+ required(
+ 14,
+ "required_shapes",
+ Types.ListType.ofOptional(
+ 15, Types.StructType.of(required(16, "required_x",
Types.LongType.get())))),
+ optional(
+ 17,
+ "optional_locations",
+ Types.MapType.ofRequired(
+ 18,
+ 19,
+ Types.StringType.get(),
+ Types.StructType.of(required(20, "required_lat",
Types.DoubleType.get())))),
+ required(
+ 21,
+ "required_locations",
+ Types.MapType.ofOptional(
+ 22,
+ 23,
+ Types.StringType.get(),
+ Types.StructType.of(required(24, "required_lat",
Types.DoubleType.get())))));
+
+ // a required element of a required list is not null, nor is anything it
contains
+ assertThat(TypeUtil.isNullable(schema, 1)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 4)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 5)).isFalse();
+
+ // an optional element is null, as is anything it contains
+ assertThat(TypeUtil.isNullable(schema, 2)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 6)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 7)).isTrue();
+
+ // required map keys and values are not null
+ assertThat(TypeUtil.isNullable(schema, 3)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 8)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 9)).isFalse();
+ assertThat(TypeUtil.isNullable(schema, 10)).isFalse();
+
+ // a required element of an optional list is null when the list is null
+ assertThat(TypeUtil.isNullable(schema, 11)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 12)).isTrue();
+ assertThat(TypeUtil.isNullable(schema, 13)).isTrue();
+
+ // an optional element of a required list is null, as is anything it
contains
Review Comment:
```suggestion
// an optional element of a required list is nullable, as is anything it
contains
```
--
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.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]