Skip to content

Commit 1416e29

Browse files
committed
PARQUET-138: Allow merging more restrictive field in less restrictive field
1 parent e98e7fd commit 1416e29

File tree

4 files changed

+29
-10
lines changed

4 files changed

+29
-10
lines changed

parquet-column/src/main/java/org/apache/parquet/schema/GroupType.java

-3
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,6 @@ List<Type> mergeFields(GroupType toMerge, boolean strict) {
380380
Type merged;
381381
if (toMerge.containsField(type.getName())) {
382382
Type fieldToMerge = toMerge.getType(type.getName());
383-
if (fieldToMerge.getRepetition().isMoreRestrictiveThan(type.getRepetition())) {
384-
throw new IncompatibleSchemaModificationException("repetition constraint is more restrictive: can not merge type " + fieldToMerge + " into " + type);
385-
}
386383
if (type.getOriginalType() != null && fieldToMerge.getOriginalType() != type.getOriginalType()) {
387384
throw new IncompatibleSchemaModificationException("cannot merge original type " + fieldToMerge.getOriginalType() + " into " + type.getOriginalType());
388385
}

parquet-column/src/main/java/org/apache/parquet/schema/PrimitiveType.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,8 @@ protected Type union(Type toMerge, boolean strict) {
728728
}
729729
}
730730

731-
Types.PrimitiveBuilder<PrimitiveType> builder = Types.primitive(primitive, toMerge.getRepetition());
731+
Repetition repetition = Repetition.leastRestrictive(this.getRepetition(), toMerge.getRepetition());
732+
Types.PrimitiveBuilder<PrimitiveType> builder = Types.primitive(primitive, repetition);
732733

733734
if (PrimitiveTypeName.FIXED_LEN_BYTE_ARRAY == primitive) {
734735
builder.length(length);

parquet-column/src/main/java/org/apache/parquet/schema/Type.java

+22
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import static org.apache.parquet.Preconditions.checkNotNull;
2222

23+
import java.util.Arrays;
2324
import java.util.List;
2425

2526
import org.apache.parquet.io.InvalidRecordException;
@@ -111,6 +112,27 @@ public boolean isMoreRestrictiveThan(Repetition other) {
111112
*/
112113
abstract public boolean isMoreRestrictiveThan(Repetition other);
113114

115+
/**
116+
* @param repetitions repetitions to traverse
117+
* @return the least restrictive repetition of all repetitions provided
118+
*/
119+
public static Repetition leastRestrictive(Repetition... repetitions) {
120+
boolean hasOptional = false;
121+
122+
for (Repetition repetition : repetitions) {
123+
if (repetition == REPEATED) {
124+
return REPEATED;
125+
} else if (repetition == OPTIONAL) {
126+
hasOptional = true;
127+
}
128+
}
129+
130+
if (hasOptional) {
131+
return OPTIONAL;
132+
}
133+
134+
return REQUIRED;
135+
}
114136
}
115137

116138
private final String name;

parquet-column/src/test/java/org/apache/parquet/schema/TestMessageType.java

+5-6
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,11 @@ public void testMergeSchema() {
8989
MessageType t4 = new MessageType("root2",
9090
new PrimitiveType(REQUIRED, BINARY, "a"));
9191

92-
try {
93-
t3.union(t4);
94-
fail("moving from optional to required");
95-
} catch (IncompatibleSchemaModificationException e) {
96-
assertEquals("repetition constraint is more restrictive: can not merge type required binary a into optional binary a", e.getMessage());
97-
}
92+
assertEquals(
93+
t3.union(t4),
94+
new MessageType("root1",
95+
new PrimitiveType(OPTIONAL, BINARY, "a"))
96+
);
9897

9998
assertEquals(
10099
t4.union(t3),

0 commit comments

Comments
 (0)