3232 * Class to write Variant values to a shredded schema.
3333 */
3434public class VariantValueWriter {
35- private ByteBuffer metadataBuffer ;
36- // We defer initializing the ImmutableMetata until it's needed. It has some construction cost, and if all
37- // object fields are shredded into typed_value, it will never be used.
38- private ImmutableMetadata metadata = null ;
39- private RecordConsumer recordConsumer ;
40-
4135 private static final String LIST_REPEATED_NAME = "list" ;
4236 private static final String LIST_ELEMENT_NAME = "element" ;
4337
38+ private final ByteBuffer metadataBuffer ;
39+ private final RecordConsumer recordConsumer ;
40+
41+ // We defer initializing the ImmutableMetata until it's needed. There is a construction cost to deserialize the
42+ // metadata binary into a Map, and if all object fields are shredded into typed_value, it will never be used.
43+ private ImmutableMetadata metadata = null ;
44+
4445 VariantValueWriter (RecordConsumer recordConsumer , ByteBuffer metadata ) {
4546 this .recordConsumer = recordConsumer ;
4647 this .metadataBuffer = metadata ;
@@ -85,12 +86,12 @@ void write(GroupType schema, Variant value) {
8586 recordConsumer .startField ("typed_value" , typedValueIdx );
8687 ByteBuffer residual = null ;
8788 if (typedValueField .isPrimitive ()) {
88- writeScalarValue (recordConsumer , value , typedValueField . asPrimitiveType () );
89+ writeScalarValue (value );
8990 } else if (typedValueField .getLogicalTypeAnnotation ()
9091 instanceof LogicalTypeAnnotation .ListLogicalTypeAnnotation ) {
91- writeArrayValue (recordConsumer , value , typedValueField .asGroupType ());
92+ writeArrayValue (value , typedValueField .asGroupType ());
9293 } else {
93- residual = writeObjectValue (recordConsumer , value , typedValueField .asGroupType ());
94+ residual = writeObjectValue (value , typedValueField .asGroupType ());
9495 }
9596 recordConsumer .endField ("typed_value" , typedValueIdx );
9697
@@ -110,7 +111,7 @@ void write(GroupType schema, Variant value) {
110111
111112 // Return true if the logical type is a decimal with the same scale as the provided value, with enough
112113 // precision to hold the value. The provided value must be a decimal.
113- private boolean compatibleDecimalType (Variant value , LogicalTypeAnnotation logicalType ) {
114+ private static boolean compatibleDecimalType (Variant value , LogicalTypeAnnotation logicalType ) {
114115 if (!(logicalType instanceof LogicalTypeAnnotation .DecimalLogicalTypeAnnotation )) {
115116 return false ;
116117 }
@@ -121,7 +122,7 @@ private boolean compatibleDecimalType(Variant value, LogicalTypeAnnotation logic
121122 return decimal .scale () == decimalType .getScale () && decimal .precision () <= decimalType .getPrecision ();
122123 }
123124
124- private boolean isTypeCompatible (Variant .Type variantType , Type typedValueField , Variant value ) {
125+ private static boolean isTypeCompatible (Variant .Type variantType , Type typedValueField , Variant value ) {
125126 if (typedValueField == null ) {
126127 return false ;
127128 }
@@ -155,8 +156,10 @@ private boolean isTypeCompatible(Variant.Type variantType, Type typedValueField,
155156 return primitiveTypeName == PrimitiveType .PrimitiveTypeName .INT64
156157 && (logicalType == null
157158 || (logicalType instanceof LogicalTypeAnnotation .IntLogicalTypeAnnotation
159+ && ((LogicalTypeAnnotation .IntLogicalTypeAnnotation ) logicalType ).isSigned ()
158160 && ((LogicalTypeAnnotation .IntLogicalTypeAnnotation ) logicalType )
159- .isSigned ()));
161+ .getBitWidth ()
162+ == 64 ));
160163 case FLOAT :
161164 return primitiveTypeName == PrimitiveType .PrimitiveTypeName .FLOAT ;
162165 case DOUBLE :
@@ -210,7 +213,7 @@ private boolean isTypeCompatible(Variant.Type variantType, Type typedValueField,
210213 }
211214 }
212215
213- private void writeScalarValue (RecordConsumer recordConsumer , Variant variant , PrimitiveType type ) {
216+ private void writeScalarValue (Variant variant ) {
214217 switch (variant .getType ()) {
215218 case BOOLEAN :
216219 recordConsumer .addBoolean (variant .getBoolean ());
@@ -272,7 +275,7 @@ private void writeScalarValue(RecordConsumer recordConsumer, Variant variant, Pr
272275 }
273276 }
274277
275- private void writeArrayValue (RecordConsumer recordConsumer , Variant variant , GroupType arrayType ) {
278+ private void writeArrayValue (Variant variant , GroupType arrayType ) {
276279 Preconditions .checkArgument (
277280 variant .getType () == Variant .Type .ARRAY ,
278281 "Cannot write variant type " + variant .getType () + " as array" );
@@ -328,10 +331,10 @@ private void writeArrayValue(RecordConsumer recordConsumer, Variant variant, Gro
328331 * @return the residual value that must be written to the value column, or null if all values were written
329332 * to typed_value.
330333 */
331- private ByteBuffer writeObjectValue (RecordConsumer recordConsumer , Variant variant , GroupType objectType ) {
332- if ( variant . getType () != Variant . Type . OBJECT ) {
333- throw new IllegalArgumentException ( "Expected object type but got: " + variant .getType ());
334- }
334+ private ByteBuffer writeObjectValue (Variant variant , GroupType objectType ) {
335+ Preconditions . checkArgument (
336+ variant .getType () == Variant . Type . OBJECT ,
337+ "Cannot write variant type " + variant . getType () + " as object" );
335338
336339 VariantBuilder residualBuilder = null ;
337340 // The residualBuilder, if created, is always a single object. This is that object's builder.
0 commit comments