@@ -486,3 +486,129 @@ fn make_map_array_internal<O: OffsetSizeTrait>(
486486 let map_data = map_data_builder. build ( ) ?;
487487 Ok ( ColumnarValue :: Array ( Arc :: new ( MapArray :: from ( map_data) ) ) )
488488}
489+
490+ #[ cfg( test) ]
491+ mod tests {
492+ use super :: * ;
493+ use arrow:: array:: { ListArray , Int32Array , StringArray } ;
494+ use arrow:: datatypes:: Field ;
495+
496+ #[ test]
497+ fn test_make_map_with_null_maps ( ) {
498+ // Test that NULL map values (entire map is NULL) are correctly handled
499+ // This test directly calls make_map_batch with a List containing NULL elements
500+ // On main branch: Would fail at line 66 with "map key cannot be null"
501+ // With fix: Correctly handles NULL maps by routing to make_map_array_internal
502+
503+ // Create a List<List<String>> where one element is NULL (representing a NULL map)
504+ // keys = [['a'], NULL, ['b']]
505+ let key_values: Vec < Option < Vec < Option < & str > > > > = vec ! [
506+ Some ( vec![ Some ( "a" ) ] ) ,
507+ None , // This is a NULL map, not a null key
508+ Some ( vec![ Some ( "b" ) ] ) ,
509+ ] ;
510+
511+ let mut key_builder = arrow:: array:: ListBuilder :: new (
512+ arrow:: array:: StringBuilder :: new ( )
513+ ) ;
514+
515+ for key_list in key_values {
516+ match key_list {
517+ Some ( keys) => {
518+ for key in keys {
519+ key_builder. values ( ) . append_option ( key) ;
520+ }
521+ key_builder. append ( true ) ;
522+ }
523+ None => {
524+ key_builder. append ( false ) ; // NULL map
525+ }
526+ }
527+ }
528+ let keys_array = Arc :: new ( key_builder. finish ( ) ) ;
529+
530+ // Create corresponding values = [[1], [2], [3]]
531+ let value_values: Vec < Option < Vec < Option < i32 > > > > = vec ! [
532+ Some ( vec![ Some ( 1 ) ] ) ,
533+ Some ( vec![ Some ( 2 ) ] ) ,
534+ Some ( vec![ Some ( 3 ) ] ) ,
535+ ] ;
536+
537+ let mut value_builder = arrow:: array:: ListBuilder :: new (
538+ arrow:: array:: Int32Builder :: new ( )
539+ ) ;
540+
541+ for value_list in value_values {
542+ match value_list {
543+ Some ( values) => {
544+ for value in values {
545+ value_builder. values ( ) . append_option ( value) ;
546+ }
547+ value_builder. append ( true ) ;
548+ }
549+ None => {
550+ value_builder. append ( false ) ;
551+ }
552+ }
553+ }
554+ let values_array = Arc :: new ( value_builder. finish ( ) ) ;
555+
556+ // Call make_map_batch - this should succeed with the fix
557+ let result = make_map_batch ( & [
558+ ColumnarValue :: Array ( keys_array) ,
559+ ColumnarValue :: Array ( values_array) ,
560+ ] ) ;
561+
562+ assert ! ( result. is_ok( ) , "Should handle NULL maps correctly" ) ;
563+
564+ if let Ok ( ColumnarValue :: Array ( map_array) ) = result {
565+ assert_eq ! ( map_array. len( ) , 3 ) ;
566+ assert ! ( map_array. is_null( 1 ) , "Second map should be NULL" ) ;
567+ assert ! ( !map_array. is_null( 0 ) , "First map should not be NULL" ) ;
568+ assert ! ( !map_array. is_null( 2 ) , "Third map should not be NULL" ) ;
569+ } else {
570+ panic ! ( "Expected Array result" ) ;
571+ }
572+ }
573+
574+ #[ test]
575+ fn test_make_map_with_null_key_within_map_should_fail ( ) {
576+ // Test that null keys WITHIN a map are properly rejected
577+ // keys = [['a', NULL, 'b']] -- NULL here is a null key, should fail
578+ let mut key_builder = arrow:: array:: ListBuilder :: new (
579+ arrow:: array:: StringBuilder :: new ( )
580+ ) ;
581+
582+ key_builder. values ( ) . append_value ( "a" ) ;
583+ key_builder. values ( ) . append_null ( ) ; // NULL key within the map
584+ key_builder. values ( ) . append_value ( "b" ) ;
585+ key_builder. append ( true ) ;
586+
587+ let keys_array = Arc :: new ( key_builder. finish ( ) ) ;
588+
589+ // values = [[1, 2, 3]]
590+ let mut value_builder = arrow:: array:: ListBuilder :: new (
591+ arrow:: array:: Int32Builder :: new ( )
592+ ) ;
593+ value_builder. values ( ) . append_value ( 1 ) ;
594+ value_builder. values ( ) . append_value ( 2 ) ;
595+ value_builder. values ( ) . append_value ( 3 ) ;
596+ value_builder. append ( true ) ;
597+
598+ let values_array = Arc :: new ( value_builder. finish ( ) ) ;
599+
600+ // Call make_map_batch - this should fail
601+ let result = make_map_batch ( & [
602+ ColumnarValue :: Array ( keys_array) ,
603+ ColumnarValue :: Array ( values_array) ,
604+ ] ) ;
605+
606+ assert ! ( result. is_err( ) , "Should reject null keys within maps" ) ;
607+ let err = result. unwrap_err ( ) ;
608+ assert ! (
609+ err. to_string( ) . contains( "cannot be null" ) ,
610+ "Error should mention null keys, got: {}" ,
611+ err
612+ ) ;
613+ }
614+ }
0 commit comments