|
18 | 18 | */ |
19 | 19 | package org.apache.parquet.variant; |
20 | 20 |
|
| 21 | +import java.math.BigDecimal; |
21 | 22 | import java.nio.ByteBuffer; |
22 | 23 | import org.apache.parquet.Preconditions; |
23 | 24 | import org.apache.parquet.io.api.Binary; |
@@ -79,7 +80,7 @@ void write(GroupType schema, Variant value) { |
79 | 80 | Variant.Type variantType = value.getType(); |
80 | 81 |
|
81 | 82 | // Handle typed_value if present |
82 | | - if (isTypeCompatible(variantType, typedValueField)) { |
| 83 | + if (isTypeCompatible(variantType, typedValueField, value)) { |
83 | 84 | int typedValueIdx = schema.getFieldIndex("typed_value"); |
84 | 85 | recordConsumer.startField("typed_value", typedValueIdx); |
85 | 86 | ByteBuffer residual = null; |
@@ -107,7 +108,21 @@ void write(GroupType schema, Variant value) { |
107 | 108 | } |
108 | 109 | } |
109 | 110 |
|
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) { |
111 | 126 | if (typedValueField == null) { |
112 | 127 | return false; |
113 | 128 | } |
@@ -145,14 +160,14 @@ private boolean isTypeCompatible(Variant.Type variantType, Type typedValueField) |
145 | 160 | case DOUBLE: |
146 | 161 | return primitiveTypeName == PrimitiveType.PrimitiveTypeName.DOUBLE; |
147 | 162 | case DECIMAL4: |
148 | | - return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT32 |
149 | | - && logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation; |
| 163 | + return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT32 && |
| 164 | + compatibleDecimalType(value, logicalType); |
150 | 165 | case DECIMAL8: |
151 | | - return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT64 |
152 | | - && logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation; |
| 166 | + return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT64 && |
| 167 | + compatibleDecimalType(value, logicalType); |
153 | 168 | case DECIMAL16: |
154 | | - return primitiveTypeName == PrimitiveType.PrimitiveTypeName.BINARY |
155 | | - && logicalType instanceof LogicalTypeAnnotation.DecimalLogicalTypeAnnotation; |
| 169 | + return primitiveTypeName == PrimitiveType.PrimitiveTypeName.BINARY && |
| 170 | + compatibleDecimalType(value, logicalType); |
156 | 171 | case DATE: |
157 | 172 | return primitiveTypeName == PrimitiveType.PrimitiveTypeName.INT32 |
158 | 173 | && logicalType instanceof LogicalTypeAnnotation.DateLogicalTypeAnnotation; |
|
0 commit comments