Jacob Stampe Mikkelsen created AVRO-3989:
--------------------------------------------

             Summary: 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


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)

Reply via email to