[
https://issues.apache.org/jira/browse/AVRO-3989?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Oscar Westra van Holthe - Kind updated AVRO-3989:
-------------------------------------------------
Fix Version/s: 1.13.0
> Schema conversion for logical types ignored when type is part of union
> ----------------------------------------------------------------------
>
> Key: AVRO-3989
> URL: https://issues.apache.org/jira/browse/AVRO-3989
> Project: Apache Avro
> Issue Type: Bug
> Components: java
> Affects Versions: 1.11.3
> Reporter: Jacob Stampe Mikkelsen
> Priority: Major
> Labels: pull-request-available
> Fix For: 1.12.1, 1.13.0
>
> Attachments: image-2024-06-02-21-32-25-461.png
>
> Time Spent: 2h
> Remaining Estimate: 0h
>
> I have a schema with an optional timestamp which is to be rendered as millis
> and the generated Java class fails to get the conversions array and method
> added, which means that at runtime I get a ClassCastException when an
> "Instant" object is cast to a "Long" because there was no registered
> converter:
> The element with an optional timestamp in my schema:
> {{{}}
> {{ "name": "DecisionStartTime",}}
> {{ "type": [}}
> {{ "null",}}
> {{ {}}
> {{ "type": "long",}}
> {{ "logicalType": "timestamp-millis"}}
> {{ }}}
> {{ ],}}
> {{ "default": null}}
> {{}}}
> The problem seems to be here:
> [https://github.com/apache/avro/blame/5a60b5c43fe9c3bb40f4a1303913fdb3598bd4a5/lang/java/compiler/src/main/velocity/org/apache/avro/compiler/specific/templates/java/classic/record.vm#L198]
> Which only renders the conversion part if any of the fields has logicalType
> set and the actual method:
> [https://github.com/apache/avro/blob/5a60b5c43fe9c3bb40f4a1303913fdb3598bd4a5/lang/java/compiler/src/main/java/org/apache/avro/compiler/specific/SpecificCompiler.java#L976C3-L983C4]
> Does not take into account that a field which is a union does not have a
> logical type, however one of the union types might.
> *Proposed solution* - replace method
> {{ public boolean hasLogicalTypeField(Schema schema) {}}
> {{ for (Schema.Field field : schema.getFields()) {}}
> {{ if (field.schema().getLogicalType() != null) {}}
> {{ return true;}}
> {{ }}}
> {{ }}}
> {{ return false;}}
> {{ }}}
> With a method like this:
> {{ public boolean hasLogicalTypeField(Schema schema) {}}
> {{ for (Schema.Field field : schema.getFields()) {}}
> {{ if (field.schema().getLogicalType() != null) {}}
> {{ return true;}}
> {{ } else if (field.schema().type == Type.UNION) {}}
> {{ for (Schema type : field.schema().getTypes()) {}}
> {{ if (type.getLogicalType() != null) {}}
> {{ return true;}}
> {{ }}}
> {{ }}}
> {{ }}}
> {{ }}}
> {{ return false;}}
> {{ }}}
> The conversionInstance() method might also need tweaking in order to identify
> that the given type has a logical type as part of the union.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)