Skip to content

Commit 1ff12ec

Browse files
committed
Fix decimal issue
1 parent 835daed commit 1ff12ec

2 files changed

Lines changed: 29 additions & 8 deletions

File tree

parquet-avro/src/test/java/org/apache/parquet/avro/TestWriteVariant.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,16 @@ public TestWriteVariant() throws Exception {
305305
fullVariant(b -> b.appendTimestampNtz(-1234567890L)),
306306
fullVariant(b -> b.appendDecimal(new BigDecimal("123456.789"))), // decimal4
307307
fullVariant(b -> b.appendDecimal(new BigDecimal("-123456.789"))), // decimal4
308+
fullVariant(b -> b.appendDecimal(new BigDecimal("123456.7"))), // decimal4
309+
fullVariant(b -> b.appendDecimal(new BigDecimal("-123456.7"))), // decimal4
308310
fullVariant(b -> b.appendDecimal(new BigDecimal("123456789.987654321"))), // decimal8
309311
fullVariant(b -> b.appendDecimal(new BigDecimal("-123456789.987654321"))), // decimal8
312+
fullVariant(b -> b.appendDecimal(new BigDecimal("123456789.9876543"))), // decimal8
313+
fullVariant(b -> b.appendDecimal(new BigDecimal("-123456789.9876543"))), // decimal8
310314
fullVariant(b -> b.appendDecimal(new BigDecimal("9876543210.123456789"))), // decimal16
311315
fullVariant(b -> b.appendDecimal(new BigDecimal("-9876543210.123456789"))), // decimal16
316+
fullVariant(b -> b.appendDecimal(new BigDecimal("9876543210.12345678912345"))), // decimal16
317+
fullVariant(b -> b.appendDecimal(new BigDecimal("-9876543210.12345678912345"))), // decimal16
312318
fullVariant(b -> b.appendBinary(ByteBuffer.wrap(new byte[] {0x0a, 0x0b, 0x0c, 0x0d}))),
313319
fullVariant(b -> b.appendString("iceberg")),
314320
fullVariant(b -> b.appendTime(1234567890)),

parquet-variant/src/main/java/org/apache/parquet/variant/VariantValueWriter.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.parquet.variant;
2020

21+
import java.math.BigDecimal;
2122
import java.nio.ByteBuffer;
2223
import org.apache.parquet.Preconditions;
2324
import org.apache.parquet.io.api.Binary;
@@ -79,7 +80,7 @@ void write(GroupType schema, Variant value) {
7980
Variant.Type variantType = value.getType();
8081

8182
// Handle typed_value if present
82-
if (isTypeCompatible(variantType, typedValueField)) {
83+
if (isTypeCompatible(variantType, typedValueField, value)) {
8384
int typedValueIdx = schema.getFieldIndex("typed_value");
8485
recordConsumer.startField("typed_value", typedValueIdx);
8586
ByteBuffer residual = null;
@@ -107,7 +108,21 @@ void write(GroupType schema, Variant value) {
107108
}
108109
}
109110

110-
private boolean isTypeCompatible(Variant.Type variantType, Type typedValueField) {
111+
// Return true if the logical type is a decimal with the same scale as the provided value, with enough
112+
// precision to hold the value. The provided value must be a decimal.
113+
private boolean compatibleDecimalType(Variant value, LogicalTypeAnnotation logicalType) {
114+
if (!(logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation)) {
115+
return false;
116+
}
117+
LogicalTypeAnnotation.DecimalLogicalTypeAnnotation decimalType =
118+
(LogicalTypeAnnotation.DecimalLogicalTypeAnnotation) logicalType;
119+
120+
BigDecimal decimal = value.getDecimal();
121+
return decimal.scale() == decimalType.getScale() &&
122+
decimal.precision() <= decimalType.getPrecision();
123+
}
124+
125+
private boolean isTypeCompatible(Variant.Type variantType, Type typedValueField, Variant value) {
111126
if (typedValueField == null) {
112127
return false;
113128
}
@@ -145,14 +160,14 @@ private boolean isTypeCompatible(Variant.Type variantType, Type typedValueField)
145160
case DOUBLE:
146161
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.DOUBLE;
147162
case DECIMAL4:
148-
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT32
149-
&& logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation;
163+
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT32 &&
164+
compatibleDecimalType(value, logicalType);
150165
case DECIMAL8:
151-
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT64
152-
&& logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation;
166+
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT64 &&
167+
compatibleDecimalType(value, logicalType);
153168
case DECIMAL16:
154-
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.BINARY
155-
&& logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation;
169+
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.BINARY &&
170+
compatibleDecimalType(value, logicalType);
156171
case DATE:
157172
return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT32
158173
&& logicalType instanceof LogicalTypeAnnotation.DateLogicalTypeAnnotation;

0 commit comments

Comments
 (0)