@@ -391,19 +391,25 @@ async fn test_list_utf8view_roundtrip() {
391391 Field :: new( "tags" , DataType :: List ( item_field. clone( ) ) , true ) ,
392392 ] ) ) ;
393393
394- // Two rows, each a list of Utf8View strings (including a null element).
394+ // Four rows exercising: a populated list with a null element, another
395+ // populated list, a NULL list cell, and an empty list.
395396 let mut lb = ListBuilder :: new ( StringViewBuilder :: new ( ) ) . with_field ( item_field) ;
396397 lb. values ( ) . append_value ( "red" ) ;
397398 lb. values ( ) . append_null ( ) ;
398- lb. append ( true ) ;
399+ lb. append ( true ) ; // rowid 1: ["red", null]
399400 lb. values ( ) . append_value ( "blue" ) ;
400401 lb. values ( ) . append_value ( "green" ) ;
401- lb. append ( true ) ;
402+ lb. append ( true ) ; // rowid 2: ["blue", "green"]
403+ lb. append ( false ) ; // rowid 3: NULL list
404+ lb. append ( true ) ; // rowid 4: [] (empty list)
402405 let tags = lb. finish ( ) ;
403406
404407 let batch = RecordBatch :: try_new (
405408 schema. clone ( ) ,
406- vec ! [ Arc :: new( Int64Array :: from( vec![ 1_i64 , 2 ] ) ) , Arc :: new( tags) ] ,
409+ vec ! [
410+ Arc :: new( Int64Array :: from( vec![ 1_i64 , 2 , 3 , 4 ] ) ) ,
411+ Arc :: new( tags) ,
412+ ] ,
407413 )
408414 . unwrap ( ) ;
409415
@@ -431,6 +437,45 @@ async fn test_list_utf8view_roundtrip() {
431437 assert_eq ! ( strs. len( ) , 2 ) ;
432438 assert_eq ! ( strs. value( 0 ) , "red" ) ;
433439 assert ! ( strs. is_null( 1 ) ) ;
440+
441+ // A NULL list cell survives as a null list entry; an empty list survives
442+ // as a present-but-empty list (length 0), not as null.
443+ let nullable = provider
444+ . fetch_by_keys ( & [ 3 , 4 ] , "rowid" , None )
445+ . await
446+ . unwrap ( ) ;
447+ let mut null_lists = 0usize ;
448+ let mut empty_lists = 0usize ;
449+ for b in & nullable {
450+ let rowid = b
451+ . column_by_name ( "rowid" )
452+ . unwrap ( )
453+ . as_any ( )
454+ . downcast_ref :: < Int64Array > ( )
455+ . unwrap ( ) ;
456+ let list = b
457+ . column_by_name ( "tags" )
458+ . unwrap ( )
459+ . as_any ( )
460+ . downcast_ref :: < ListArray > ( )
461+ . unwrap ( ) ;
462+ for i in 0 ..b. num_rows ( ) {
463+ match rowid. value ( i) {
464+ 3 => {
465+ assert ! ( list. is_null( i) , "rowid 3 should be a NULL list" ) ;
466+ null_lists += 1 ;
467+ }
468+ 4 => {
469+ assert ! ( list. is_valid( i) , "rowid 4 should be a present empty list" ) ;
470+ assert_eq ! ( list. value( i) . len( ) , 0 , "rowid 4 should be empty" ) ;
471+ empty_lists += 1 ;
472+ }
473+ other => panic ! ( "unexpected rowid {other}" ) ,
474+ }
475+ }
476+ }
477+ assert_eq ! ( null_lists, 1 ) ;
478+ assert_eq ! ( empty_lists, 1 ) ;
434479}
435480
436481/// A `List<LargeUtf8>` payload must reconstruct with a `LargeStringArray` child.
0 commit comments