[ 
https://issues.apache.org/jira/browse/AVRO-2636?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16985323#comment-16985323
 ] 

Valentin Nikotin commented on AVRO-2636:
----------------------------------------

Hi!

Return of {{bb.duplicate }}solves my problem. The way I use 
{{getDefaultValue(field)}} is to get default values during converting 
GenericRecords into another format. I have unit tests with random Avro schemas 
with random default for every possible type, and realized it failed on defaults 
for Byte type. Decimal was just more real-world example of the problem.

I agree about Fixed too, strong warning should be enough to preserve people 
from the optimization to reuse the same {{byte[]}}, while I can't think any 
reasonable way to reuse, there might be some possible security issues though. 
On the other hand copying arrays just for safety reason may affect performance, 
having safe/unsafe {{getDefaultValue}} methods would be confusing.

> GenericData defaultValueCache caches mutable ByteBuffers
> --------------------------------------------------------
>
>                 Key: AVRO-2636
>                 URL: https://issues.apache.org/jira/browse/AVRO-2636
>             Project: Apache Avro
>          Issue Type: Bug
>          Components: java
>            Reporter: Valentin Nikotin
>            Priority: Minor
>
> It appears that for default value for Byte type (and Decimal logical type if 
> it uses underlying Bytes type) value rendered with getDefaultValue is cached. 
> This leads to bugs when you read the same value (for example if converted 
> with DecimalConversion). For single thread environment workaround would be to 
> reset ByteBuffer after read, but in concurrent environment we should not 
> cache mutable objects.
>  
> {code:java}
> @Test(expected=NumberFormatException.class)
> public void testReuse() {
>     Conversions.DecimalConversion decimalConversion =
>             new Conversions.DecimalConversion();
>     LogicalType logicalDecimal =
>             LogicalTypes.decimal(38, 9);
>     ByteBuffer defaultValue =
>             decimalConversion.toBytes(
>                     BigDecimal.valueOf(42L).setScale(9),
>                     null,
>                     logicalDecimal);
>     Schema schema = SchemaBuilder
>             .record("test")
>             .fields()
>             .name("decimal")
>             
> .type(logicalDecimal.addToSchema(SchemaBuilder.builder().bytesType()))
>             .withDefault(defaultValue)
>             .endRecord();
>     BigDecimal firstRead = decimalConversion
>             .fromBytes(
>                     (ByteBuffer) 
> GenericData.get().getDefaultValue(schema.getField("decimal")),
>                     null,
>                     logicalDecimal);
>     BigDecimal secondRead = decimalConversion
>             .fromBytes(
>                     (ByteBuffer) 
> GenericData.get().getDefaultValue(schema.getField("decimal")),
>                     null,
>                     logicalDecimal);
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to