Skip to content

Commit e9c156d

Browse files
authored
[Kernel] Add isNested method to DataType class (delta-io#4722)
#### Which Delta project/connector is this regarding? - [ ] Spark - [ ] Standalone - [ ] Flink - [x] Kernel - [ ] Other (fill in here) ## Description This method centralizes the concept of isNested to the DataType class instead of individual helper methods. Resolves delta-io#4571 ## How was this patch tested? Unit tests. ## Does this PR introduce _any_ user-facing changes? Yes, it adds a new API method isNested.
1 parent e69ce07 commit e9c156d

File tree

9 files changed

+102
-15
lines changed

9 files changed

+102
-15
lines changed

kernel/kernel-api/src/main/java/io/delta/kernel/internal/types/DataTypeJsonSerDe.java

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ private static StructField fixupFieldLevelMetadata(
282282
}
283283
List<TypeChange> changes = pathToTypeChanges.get(pathFromAncestor);
284284
if (changes != null) {
285-
if (isNested(element.getField().getDataType())) {
285+
if (element.getField().getDataType().isNested()) {
286286
throw new KernelException(
287287
format("Invalid data type for type change: \"%s\"", element.getField()));
288288
}
@@ -304,12 +304,6 @@ private static StructField fixupFieldLevelMetadata(
304304
return structField;
305305
}
306306

307-
private static boolean isNested(DataType dataType) {
308-
return dataType instanceof StructType
309-
|| dataType instanceof MapType
310-
|| dataType instanceof ArrayType;
311-
}
312-
313307
private static void updateCollation(
314308
SchemaIterable.MutableSchemaElement element,
315309
FieldMetadata collationsMetadata,

kernel/kernel-api/src/main/java/io/delta/kernel/internal/util/SchemaUtils.java

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,8 @@ static SchemaChanges computeSchemaChangesById(StructType currentSchema, StructTy
412412
}
413413

414414
if (!existingField.equals(newField)) {
415-
if (!isNestedType(existingField)
416-
&& !isNestedType(newField)
415+
if (!existingField.getDataType().isNested()
416+
&& !newField.getDataType().isNested()
417417
&& !existingField.getDataType().equivalent(newField.getDataType())) {
418418
// Type changes only apply to non-nested types. This loop evaluates both
419419
// nested and non-nested, so we narrow down updates here. Actual type differences
@@ -434,12 +434,6 @@ static SchemaChanges computeSchemaChangesById(StructType currentSchema, StructTy
434434
return schemaDiff.build();
435435
}
436436

437-
private static boolean isNestedType(StructField existingField) {
438-
// TODO: Make is nested a centralized concept
439-
DataType d = existingField.getDataType();
440-
return d instanceof StructType || d instanceof ArrayType || d instanceof MapType;
441-
}
442-
443437
private static Map<SchemaElementId, StructField> fieldsByElementId(StructType schema) {
444438
Map<SchemaElementId, StructField> fieldIdToField = new HashMap<>();
445439
for (SchemaIterable.SchemaElement element : new SchemaIterable(schema)) {

kernel/kernel-api/src/main/java/io/delta/kernel/types/ArrayType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ public boolean equivalent(DataType dataType) {
5555
&& ((ArrayType) dataType).getElementType().equivalent(getElementType());
5656
}
5757

58+
@Override
59+
public boolean isNested() {
60+
return true;
61+
}
62+
5863
@Override
5964
public boolean equals(Object o) {
6065
if (this == o) {

kernel/kernel-api/src/main/java/io/delta/kernel/types/BasePrimitiveType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ public boolean equals(Object o) {
8282
return primitiveTypeName.equals(that.primitiveTypeName);
8383
}
8484

85+
@Override
86+
public boolean isNested() {
87+
return false;
88+
}
89+
8590
@Override
8691
public int hashCode() {
8792
return Objects.hash(primitiveTypeName);

kernel/kernel-api/src/main/java/io/delta/kernel/types/DataType.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ public boolean equivalent(DataType dataType) {
3636
return equals(dataType);
3737
}
3838

39+
/**
40+
* Returns true iff this data is a nested data type (it logically parameterized by other types).
41+
*
42+
* <p>For example StructType, ArrayType, MapType are nested data types.
43+
*/
44+
public abstract boolean isNested();
45+
3946
@Override
4047
public abstract int hashCode();
4148

kernel/kernel-api/src/main/java/io/delta/kernel/types/DecimalType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ public int getScale() {
5757
return scale;
5858
}
5959

60+
@Override
61+
public boolean isNested() {
62+
return false;
63+
}
64+
6065
@Override
6166
public String toString() {
6267
return String.format("Decimal(%d, %d)", precision, scale);

kernel/kernel-api/src/main/java/io/delta/kernel/types/MapType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public boolean equals(Object o) {
8383
&& Objects.equals(valueField, mapType.valueField);
8484
}
8585

86+
@Override
87+
public boolean isNested() {
88+
return true;
89+
}
90+
8691
@Override
8792
public int hashCode() {
8893
return Objects.hash(keyField, valueField);

kernel/kernel-api/src/main/java/io/delta/kernel/types/StructType.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,11 @@ public boolean equivalent(DataType dataType) {
134134
.allMatch(result -> result);
135135
}
136136

137+
@Override
138+
public boolean isNested() {
139+
return true;
140+
}
141+
137142
@Override
138143
public String toString() {
139144
return String.format(
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (2025) The Delta Lake Project Authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.delta.kernel.types
17+
18+
import java.util.Arrays
19+
20+
import org.scalatest.funsuite.AnyFunSuite
21+
22+
class TypesSuite extends AnyFunSuite {
23+
test("isNested - false") {
24+
// All primitive types should return false for isNested
25+
val primitiveTypes = Seq(
26+
BinaryType.BINARY,
27+
BooleanType.BOOLEAN,
28+
ByteType.BYTE,
29+
DateType.DATE,
30+
new DecimalType(10, 2),
31+
DoubleType.DOUBLE,
32+
FloatType.FLOAT,
33+
IntegerType.INTEGER,
34+
LongType.LONG,
35+
ShortType.SHORT,
36+
StringType.STRING,
37+
TimestampType.TIMESTAMP,
38+
TimestampNTZType.TIMESTAMP_NTZ,
39+
VariantType.VARIANT)
40+
41+
primitiveTypes.foreach { dataType =>
42+
assert(!dataType.isNested(), s"Expected $dataType to not be nested")
43+
}
44+
}
45+
46+
test("isNested - nested types") {
47+
// Create instances of nested types
48+
val structFields = Arrays.asList(
49+
new StructField("field1", IntegerType.INTEGER, true),
50+
new StructField("field2", StringType.STRING, true))
51+
val structType = new StructType(structFields)
52+
53+
val arrayType = new ArrayType(
54+
new StructField("element", IntegerType.INTEGER, true))
55+
56+
val mapType = new MapType(
57+
new StructField("key", StringType.STRING, false),
58+
new StructField("value", IntegerType.INTEGER, true))
59+
60+
// All nested types should return true for isNested
61+
val nestedTypes = Seq(structType, arrayType, mapType)
62+
63+
nestedTypes.foreach { dataType =>
64+
assert(dataType.isNested(), s"Expected $dataType to be nested")
65+
}
66+
}
67+
}

0 commit comments

Comments
 (0)