@@ -444,25 +444,18 @@ pub(crate) fn append_field(
444
444
// Appending value into struct field builder of Arrow struct builder.
445
445
let field_builder = struct_builder. field_builder :: < StructBuilder > ( idx) . unwrap ( ) ;
446
446
447
- if row. is_null_row ( ) {
448
- // The row is null.
447
+ let nested_row = if row. is_null_row ( ) || row. is_null_at ( idx) {
448
+ // The row is null, or the field in the row is null, i.e., a null nested row.
449
+ // Append a null value to the row builder.
449
450
field_builder. append_null ( ) ;
451
+ SparkUnsafeRow :: default ( )
450
452
} else {
451
- let is_null = row. is_null_at ( idx) ;
453
+ field_builder. append ( true ) ;
454
+ row. get_struct ( idx, fields. len ( ) )
455
+ } ;
452
456
453
- let nested_row = if is_null {
454
- // The field in the row is null, i.e., a null nested row.
455
- // Append a null value to the row builder.
456
- field_builder. append_null ( ) ;
457
- SparkUnsafeRow :: default ( )
458
- } else {
459
- field_builder. append ( true ) ;
460
- row. get_struct ( idx, fields. len ( ) )
461
- } ;
462
-
463
- for ( field_idx, field) in fields. into_iter ( ) . enumerate ( ) {
464
- append_field ( field. data_type ( ) , field_builder, & nested_row, field_idx) ?;
465
- }
457
+ for ( field_idx, field) in fields. into_iter ( ) . enumerate ( ) {
458
+ append_field ( field. data_type ( ) , field_builder, & nested_row, field_idx) ?;
466
459
}
467
460
}
468
461
DataType :: Map ( field, _) => {
@@ -3302,3 +3295,45 @@ fn make_batch(arrays: Vec<ArrayRef>, row_count: usize) -> Result<RecordBatch, Ar
3302
3295
let options = RecordBatchOptions :: new ( ) . with_row_count ( Option :: from ( row_count) ) ;
3303
3296
RecordBatch :: try_new_with_options ( schema, arrays, & options)
3304
3297
}
3298
+
3299
+ #[ cfg( test) ]
3300
+ mod test {
3301
+ use arrow:: datatypes:: Fields ;
3302
+
3303
+ use super :: * ;
3304
+
3305
+ #[ test]
3306
+ fn test_append_null_row_to_struct_builder ( ) {
3307
+ let data_type = DataType :: Struct ( Fields :: from ( vec ! [
3308
+ Field :: new( "a" , DataType :: Boolean , true ) ,
3309
+ Field :: new( "b" , DataType :: Boolean , true ) ,
3310
+ ] ) ) ;
3311
+ let fields = Fields :: from ( vec ! [ Field :: new( "st" , data_type. clone( ) , true ) ] ) ;
3312
+ let mut struct_builder = StructBuilder :: from_fields ( fields, 1 ) ;
3313
+ let row = SparkUnsafeRow :: default ( ) ;
3314
+ append_field ( & data_type, & mut struct_builder, & row, 0 ) . expect ( "append field" ) ;
3315
+ struct_builder. append_null ( ) ;
3316
+ let struct_array = struct_builder. finish ( ) ;
3317
+ assert_eq ! ( struct_array. len( ) , 1 ) ;
3318
+ assert ! ( struct_array. is_null( 0 ) ) ;
3319
+ }
3320
+
3321
+ #[ test]
3322
+ #[ cfg_attr( miri, ignore) ] // Unaligned memory access in SparkUnsafeRow
3323
+ fn test_append_null_struct_field_to_struct_builder ( ) {
3324
+ let data_type = DataType :: Struct ( Fields :: from ( vec ! [
3325
+ Field :: new( "a" , DataType :: Boolean , true ) ,
3326
+ Field :: new( "b" , DataType :: Boolean , true ) ,
3327
+ ] ) ) ;
3328
+ let fields = Fields :: from ( vec ! [ Field :: new( "st" , data_type. clone( ) , true ) ] ) ;
3329
+ let mut struct_builder = StructBuilder :: from_fields ( fields, 1 ) ;
3330
+ let mut row = SparkUnsafeRow :: new_with_num_fields ( 1 ) ;
3331
+ let data = [ 0 ; 8 ] ;
3332
+ row. point_to_slice ( & data) ;
3333
+ append_field ( & data_type, & mut struct_builder, & row, 0 ) . expect ( "append field" ) ;
3334
+ struct_builder. append_null ( ) ;
3335
+ let struct_array = struct_builder. finish ( ) ;
3336
+ assert_eq ! ( struct_array. len( ) , 1 ) ;
3337
+ assert ! ( struct_array. is_null( 0 ) ) ;
3338
+ }
3339
+ }
0 commit comments