|
16 | 16 | */ |
17 | 17 | package org.apache.arrow.adapter.avro.producers.logical; |
18 | 18 |
|
19 | | -import org.apache.arrow.adapter.avro.producers.AvroFixedSizeBinaryProducer; |
| 19 | +import org.apache.arrow.adapter.avro.producers.BaseAvroProducer; |
20 | 20 | import org.apache.arrow.vector.DecimalVector; |
| 21 | +import org.apache.arrow.vector.util.DecimalUtility; |
| 22 | +import org.apache.avro.io.Encoder; |
| 23 | + |
| 24 | +import java.io.IOException; |
| 25 | +import java.math.BigDecimal; |
21 | 26 |
|
22 | 27 | /** |
23 | 28 | * Producer that produces decimal values from a {@link DecimalVector}, writes data to an Avro |
24 | 29 | * encoder. |
25 | 30 | */ |
26 | | -public class AvroDecimalProducer extends AvroFixedSizeBinaryProducer { |
| 31 | +public class AvroDecimalProducer extends BaseAvroProducer<DecimalVector> { |
| 32 | + |
| 33 | + // Arrow stores decimals with native endianness, but Avro requires big endian |
| 34 | + // Writing the Arrow representation as fixed bytes fails on little-end machines |
| 35 | + // Instead, we replicate the big endian logic explicitly here |
| 36 | + // See DecimalUtility.writeByteArrayToArrowBufHelper |
27 | 37 |
|
28 | | - // Decimal stored as fixed width bytes, matches Avro decimal encoding |
| 38 | + byte[] encodedBytes = new byte[DecimalVector.TYPE_WIDTH]; |
29 | 39 |
|
30 | 40 | /** Instantiate an AvroDecimalProducer. */ |
31 | 41 | public AvroDecimalProducer(DecimalVector vector) { |
32 | 42 | super(vector); |
33 | 43 | } |
| 44 | + |
| 45 | + @Override |
| 46 | + public void produce(Encoder encoder) throws IOException { |
| 47 | + // Use getObject() to go back to a BigDecimal then re-encode |
| 48 | + BigDecimal value = vector.getObject(currentIndex++); |
| 49 | + encodeDecimal(value, encodedBytes); |
| 50 | + encoder.writeFixed(encodedBytes); |
| 51 | + } |
| 52 | + |
| 53 | + static void encodeDecimal(BigDecimal value, byte[] encodedBytes) { |
| 54 | + byte[] valueBytes = value.unscaledValue().toByteArray(); |
| 55 | + byte[] padding = valueBytes[0] < 0 ? DecimalUtility.minus_one : DecimalUtility.zeroes; |
| 56 | + System.arraycopy(padding, 0, encodedBytes, 0, encodedBytes.length - valueBytes.length); |
| 57 | + System.arraycopy(valueBytes, 0, encodedBytes, encodedBytes.length - valueBytes.length, valueBytes.length); |
| 58 | + } |
34 | 59 | } |
0 commit comments