@@ -225,8 +225,9 @@ impl VariantBuilderExt for VariantArrayBuilder {
225225/// // Create a variant value builder for 10 rows
226226/// let mut builder = VariantValueArrayBuilder::new(10);
227227///
228- /// // Append some values with their corresponding metadata
229- /// // In practice, some of the variant values would be objects with internal metadata.
228+ /// // Append some values with their corresponding metadata. In practice, some of the variant
229+ /// // values would be objects with internal references to pre-existing metadata, which the
230+ /// // builder takes advantage of to avoid creating new metadata.
230231/// builder.append_value(Variant::from(42));
231232/// builder.append_null();
232233/// builder.append_value(Variant::from("hello"));
@@ -268,7 +269,7 @@ impl VariantValueArrayBuilder {
268269
269270 /// Append a null row to the builder
270271 ///
271- /// WARNING: It is only safe to call this method when building the `value` field of a shredded
272+ /// WARNING: It is only valid to call this method when building the `value` field of a shredded
272273 /// variant column (which is nullable). The `value` field of a binary (unshredded) variant
273274 /// column is non-nullable, and callers should instead invoke [`Self::append_value`] with
274275 /// `Variant::Null`, passing the appropriate metadata value.
@@ -322,7 +323,7 @@ impl VariantValueArrayBuilder {
322323 /// object_builder.insert_bytes(field_name, field_value);
323324 /// }
324325 /// }
325- /// object_builder.finish(); // appends the new object
326+ /// object_builder.finish(); // appends the filtered object
326327 /// ```
327328 pub fn parent_state < ' a > (
328329 & ' a mut self ,
@@ -380,7 +381,7 @@ fn binary_view_array_from_buffers(buffer: Vec<u8>, offsets: Vec<usize>) -> Binar
380381mod test {
381382 use super :: * ;
382383 use arrow:: array:: Array ;
383- use parquet_variant:: { Variant , VariantBuilder , VariantMetadata } ;
384+ use parquet_variant:: Variant ;
384385
385386 /// Test that both the metadata and value buffers are non nullable
386387 #[ test]
@@ -457,30 +458,76 @@ mod test {
457458
458459 #[ test]
459460 fn test_variant_value_array_builder_with_objects ( ) {
460- // Create metadata with field names
461- let mut metadata_builder = WritableMetadataBuilder :: default ( ) ;
462- metadata_builder. upsert_field_name ( "name" ) ;
463- metadata_builder. upsert_field_name ( "age" ) ;
464- metadata_builder. finish ( ) ;
465- let metadata_bytes = metadata_builder. into_inner ( ) ;
466- let metadata = VariantMetadata :: try_new ( & metadata_bytes) . unwrap ( ) ;
467-
468- // Create a variant with an object using the same metadata
469- let mut variant_builder = VariantBuilder :: new ( ) . with_metadata ( metadata) ;
470- variant_builder
461+ // Populate a variant array with objects
462+ let mut builder = VariantArrayBuilder :: new ( 3 ) ;
463+ builder
471464 . new_object ( )
472465 . with_field ( "name" , "Alice" )
473466 . with_field ( "age" , 30i32 )
474467 . finish ( ) ;
475- let ( _, value_bytes) = variant_builder. finish ( ) ;
476- let variant = Variant :: try_new ( & metadata_bytes, & value_bytes) . unwrap ( ) ;
477468
478- // Now use the value array builder
479- let mut builder = VariantValueArrayBuilder :: new ( 10 ) ;
480- builder. append_value ( variant) ;
481- builder. append_null ( ) ;
469+ builder
470+ . new_object ( )
471+ . with_field ( "name" , "Bob" )
472+ . with_field ( "age" , 42i32 )
473+ . with_field ( "city" , "Wonderland" )
474+ . finish ( ) ;
482475
483- let value_array = builder. build ( ) . unwrap ( ) ;
484- assert_eq ! ( value_array. len( ) , 2 ) ;
476+ builder
477+ . new_object ( )
478+ . with_field ( "name" , "Charlie" )
479+ . with_field ( "age" , 1i32 )
480+ . finish ( ) ;
481+
482+ let array = builder. build ( ) ;
483+
484+ // Copy (some of) the objects over to the value array builder
485+ //
486+ // NOTE: Because we will reuse the metadata column, we cannot reorder rows. We can only
487+ // filter or manipulate values within a row.
488+ let mut builder = VariantValueArrayBuilder :: new ( 3 ) ;
489+
490+ // straight copy
491+ builder. append_value ( array. value ( 0 ) ) ;
492+
493+ // filtering fields takes more work because we need to manually create an object builder
494+ let value = array. value ( 1 ) ;
495+ let mut metadata_builder = ReadOnlyMetadataBuilder :: new ( value. metadata ( ) . unwrap ( ) . clone ( ) ) ;
496+ let state = builder. parent_state ( & mut metadata_builder) ;
497+ ObjectBuilder :: new ( state, false )
498+ . with_field ( "name" , value. get_object_field ( "name" ) . unwrap ( ) )
499+ . with_field ( "age" , value. get_object_field ( "age" ) . unwrap ( ) )
500+ . finish ( ) ;
501+
502+ // same bytes, but now nested and duplicated inside a list
503+ let value = array. value ( 2 ) ;
504+ let mut metadata_builder = ReadOnlyMetadataBuilder :: new ( value. metadata ( ) . unwrap ( ) . clone ( ) ) ;
505+ let state = builder. parent_state ( & mut metadata_builder) ;
506+ ListBuilder :: new ( state, false )
507+ . with_value ( value. clone ( ) )
508+ . with_value ( value. clone ( ) )
509+ . finish ( ) ;
510+
511+ let array2 = VariantArray :: from_parts (
512+ array. metadata_field ( ) . clone ( ) ,
513+ Some ( builder. build ( ) . unwrap ( ) ) ,
514+ None ,
515+ None ,
516+ ) ;
517+
518+ assert_eq ! ( array2. len( ) , 3 ) ;
519+ assert_eq ! ( array. value( 0 ) , array2. value( 0 ) ) ;
520+
521+ assert_eq ! (
522+ array. value( 1 ) . get_object_field( "name" ) ,
523+ array2. value( 1 ) . get_object_field( "name" )
524+ ) ;
525+ assert_eq ! (
526+ array. value( 1 ) . get_object_field( "age" ) ,
527+ array2. value( 1 ) . get_object_field( "age" )
528+ ) ;
529+
530+ assert_eq ! ( array. value( 2 ) , array2. value( 2 ) . get_list_element( 0 ) . unwrap( ) ) ;
531+ assert_eq ! ( array. value( 2 ) , array2. value( 2 ) . get_list_element( 1 ) . unwrap( ) ) ;
485532 }
486533}
0 commit comments