Skip to content

Commit cea41a4

Browse files
authored
AVRO-3940: [java] Allow schema redefinition when equal (#3304)
ParseContext.put accept known schemas when strictly identical. Call to this method was made before schema was fully parsed avoiding exact schema redefinition in files. Call ParseContext.put when schema is fully parsed. This has an inpact on the schemas ordering returned by the parser.
1 parent b545ed5 commit cea41a4

File tree

6 files changed

+47
-15
lines changed

6 files changed

+47
-15
lines changed

lang/java/avro/src/main/java/org/apache/avro/ParseContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ public void rollback() {
277277
* references, even if parsed from different files. Note: the context must be
278278
* committed for this method to work.
279279
*
280-
* @return all parsed schemas, in the order they were parsed
280+
* @return all parsed schemas
281281
* @throws AvroTypeException if a schema reference cannot be resolved
282282
*/
283283
public List<Schema> resolveAllSchemas() {

lang/java/avro/src/main/java/org/apache/avro/Schema.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1863,7 +1863,6 @@ private static Schema parseRecord(JsonNode schema, ParseContext context, String
18631863
Name name = parseName(schema, currentNameSpace);
18641864
String doc = parseDoc(schema);
18651865
Schema result = new RecordSchema(name, doc, isTypeError);
1866-
context.put(result);
18671866

18681867
JsonNode fieldsNode = schema.get("fields");
18691868
if (fieldsNode == null || !fieldsNode.isArray())
@@ -1880,6 +1879,7 @@ private static Schema parseRecord(JsonNode schema, ParseContext context, String
18801879
result.setFields(fields);
18811880
parsePropertiesAndLogicalType(schema, result, SCHEMA_RESERVED);
18821881
parseAliases(schema, result);
1882+
context.put(result);
18831883
return result;
18841884
}
18851885

@@ -1925,9 +1925,9 @@ private static Schema parseEnum(JsonNode schema, ParseContext context, String cu
19251925
}
19261926

19271927
Schema result = new EnumSchema(name, doc, symbols, defaultSymbol);
1928-
context.put(result);
19291928
parsePropertiesAndLogicalType(schema, result, ENUM_RESERVED);
19301929
parseAliases(schema, result);
1930+
context.put(result);
19311931
return result;
19321932
}
19331933

@@ -1960,9 +1960,9 @@ private static Schema parseFixed(JsonNode schema, ParseContext context, String c
19601960
throw new SchemaParseException("Invalid or no size: " + schema);
19611961

19621962
Schema result = new FixedSchema(name, doc, sizeNode.intValue());
1963-
context.put(result);
19641963
parsePropertiesAndLogicalType(schema, result, SCHEMA_RESERVED);
19651964
parseAliases(schema, result);
1965+
context.put(result);
19661966
return result;
19671967
}
19681968

lang/java/avro/src/main/java/org/apache/avro/reflect/ReflectData.java

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,6 @@ protected Schema createSchema(Type type, Map<String, Schema> names) {
723723
boolean error = Throwable.class.isAssignableFrom(c);
724724
schema = Schema.createRecord(name, doc, space, error);
725725
consumeAvroAliasAnnotation(c, schema);
726-
names.put(c.getName(), schema);
727726
for (Field field : getCachedFields(c))
728727
if ((field.getModifiers() & (Modifier.TRANSIENT | Modifier.STATIC)) == 0
729728
&& !field.isAnnotationPresent(AvroIgnore.class)) {
@@ -769,6 +768,7 @@ protected Schema createSchema(Type type, Map<String, Schema> names) {
769768
}
770769
names.put(fullName, schema);
771770
}
771+
names.put(c.getName(), schema);
772772
return schema;
773773
}
774774
return super.createSchema(type, names);
@@ -907,11 +907,7 @@ public Protocol getProtocol(Class iface) {
907907
}
908908
}
909909

910-
// reverse types, since they were defined in reference order
911-
List<Schema> types = new ArrayList<>(names.values());
912-
Collections.reverse(types);
913-
protocol.setTypes(types);
914-
910+
protocol.setTypes(new ArrayList<>(names.values()));
915911
return protocol;
916912
}
917913

lang/java/avro/src/test/java/org/apache/avro/TestSchema.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,10 @@
3232
import java.util.Arrays;
3333
import java.util.Collections;
3434
import java.util.List;
35+
import java.util.Map;
3536
import java.util.Set;
37+
import java.util.function.Function;
38+
import java.util.stream.Collectors;
3639

3740
import com.fasterxml.jackson.core.JsonProcessingException;
3841
import com.fasterxml.jackson.databind.JsonNode;
@@ -606,13 +609,14 @@ void testParseMultipleFile() throws IOException {
606609
parser.parse(f1);
607610
parser.parse(f2);
608611
parser.parse(f3);
609-
final List<Schema> schemas = parser.getParsedNamedSchemas();
612+
final Map<String, Schema> schemas = parser.getParsedNamedSchemas().stream()
613+
.collect(Collectors.toMap(Schema::getName, Function.identity()));
610614
Assertions.assertEquals(3, schemas.size());
611-
Schema schemaAppEvent = schemas.get(0);
612-
Schema schemaDocInfo = schemas.get(1);
613-
Schema schemaResponse = schemas.get(2);
615+
Schema schemaAppEvent = schemas.get("ApplicationEvent");
616+
Schema schemaDocInfo = schemas.get("DocumentInfo");
617+
Schema schemaResponse = schemas.get("MyResponse");
614618
Assertions.assertNotNull(schemaAppEvent);
615-
Assertions.assertEquals(3, schemaAppEvent.getFields().size());
619+
Assertions.assertEquals(4, schemaAppEvent.getFields().size());
616620
Field documents = schemaAppEvent.getField("documents");
617621
Schema docSchema = documents.schema().getTypes().get(1).getElementType();
618622
Assertions.assertEquals(docSchema, schemaDocInfo);

lang/java/avro/src/test/resources/multipleFile/ApplicationEvent.avsc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@
2222
}],
2323
"doc": "",
2424
"default": null
25+
},
26+
{
27+
"name": "response",
28+
"type": {
29+
"namespace": "model",
30+
"type": "record",
31+
"doc": "",
32+
"name": "MyResponse",
33+
"fields": [
34+
{
35+
"name": "isSuccessful",
36+
"type": "boolean",
37+
"doc": "Indicator for successful or unsuccessful call"
38+
}
39+
]
40+
}
2541
}
2642
]
2743

lang/java/maven-plugin/src/test/avro/multipleSchemas/ApplicationEvent.avsc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@
2222
}],
2323
"doc": "",
2424
"default": null
25+
},
26+
{
27+
"name": "response",
28+
"type": {
29+
"namespace": "model",
30+
"type": "record",
31+
"doc": "",
32+
"name": "MyResponse",
33+
"fields": [
34+
{
35+
"name": "isSuccessful",
36+
"type": "boolean",
37+
"doc": "Indicator for successful or unsuccessful call"
38+
}
39+
]
40+
}
2541
}
2642
]
2743

0 commit comments

Comments
 (0)