Skip to content

Commit d6c80d7

Browse files
GH-3114: Fix LogicalType conversions for nested records on Avro <= 1.8 (#3111)
* Fix LogicalType conversions for nested records on Avro <= 1.8 * Move inner field traversal outside finally block
1 parent 7f77908 commit d6c80d7

File tree

2 files changed

+38
-7
lines changed

2 files changed

+38
-7
lines changed

parquet-avro/src/main/java/org/apache/parquet/avro/AvroRecordConverter.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,13 +194,13 @@ private static void addLogicalTypeConversion(SpecificData model, Schema schema,
194194
model.addLogicalTypeConversion(conversion);
195195
}
196196
}
197-
198-
for (Schema.Field field : schema.getFields()) {
199-
addLogicalTypeConversion(model, field.schema(), seenSchemas);
200-
}
201197
} catch (NoSuchFieldException e) {
202198
// Avro classes without logical types (denoted by the "conversions" field)
203199
}
200+
201+
for (Schema.Field field : schema.getFields()) {
202+
addLogicalTypeConversion(model, field.schema(), seenSchemas);
203+
}
204204
}
205205
break;
206206
case MAP:

parquet-avro/src/test/java/org/apache/parquet/avro/TestAvroRecordConverter.java

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,22 @@ public void testModelForGenericRecord() {
8888
public void testModelForSpecificRecordWithLogicalTypesWithDeprecatedAvro1_8() {
8989
Mockito.when(AvroRecordConverter.getRuntimeAvroVersion()).thenReturn("1.8.2");
9090

91-
// Test that model is generated correctly
92-
final SpecificData model = AvroRecordConverter.getModelForSchema(LogicalTypesTestDeprecated.SCHEMA$);
91+
// Test that model is generated correctly when record contains both top-level and nested logical types
92+
SpecificData model = AvroRecordConverter.getModelForSchema(LogicalTypesTestDeprecated.SCHEMA$);
9393
// Test that model is generated correctly
9494
Collection<Conversion<?>> conversions = model.getConversions();
95-
assertEquals(conversions.size(), 3);
95+
assertEquals(3, conversions.size());
9696
assertNotNull(model.getConversionByClass(Instant.class));
9797
assertNotNull(model.getConversionByClass(LocalDate.class));
9898
assertNotNull(model.getConversionByClass(LocalTime.class));
99+
100+
// Test that model is generated correctly when record contains only nested logical types
101+
model = AvroRecordConverter.getModelForSchema(NestedOnlyLogicalTypesDeprecated.SCHEMA$);
102+
// Test that model is generated correctly
103+
conversions = model.getConversions();
104+
assertEquals(2, conversions.size());
105+
assertNotNull(model.getConversionByClass(LocalDate.class));
106+
assertNotNull(model.getConversionByClass(LocalTime.class));
99107
}
100108

101109
@Test
@@ -147,6 +155,7 @@ public static org.apache.avro.Schema getClassSchema() {
147155
};
148156
}
149157

158+
// An Avro class generated from Avro 1.8 that contains both nested and top-level logical type fields
150159
@org.apache.avro.specific.AvroGenerated
151160
public abstract static class LogicalTypesTestDeprecated extends org.apache.avro.specific.SpecificRecordBase
152161
implements org.apache.avro.specific.SpecificRecord {
@@ -179,4 +188,26 @@ public static org.apache.avro.Schema getClassSchema() {
179188
new org.apache.avro.data.TimeConversions.TimestampMillisConversion(), null, null
180189
};
181190
}
191+
192+
// An Avro class generated from Avro 1.8 that contains only nested logical type fields
193+
@org.apache.avro.specific.AvroGenerated
194+
public abstract static class NestedOnlyLogicalTypesDeprecated extends org.apache.avro.specific.SpecificRecordBase
195+
implements org.apache.avro.specific.SpecificRecord {
196+
public static final org.apache.avro.Schema SCHEMA$ = SchemaBuilder.builder()
197+
.record("NestedOnlyLogicalTypesDeprecated")
198+
.namespace("org.apache.parquet.avro.TestAvroRecordConverter")
199+
.fields()
200+
.name("local_date_time")
201+
.type(LocalDateTimeTestDeprecated.getClassSchema())
202+
.noDefault()
203+
.endRecord();
204+
205+
public static org.apache.avro.Schema getClassSchema() {
206+
return SCHEMA$;
207+
}
208+
209+
private static SpecificData MODEL$ = new SpecificData();
210+
211+
// No top-level conversions field, since logical types are all nested
212+
}
182213
}

0 commit comments

Comments
 (0)