@@ -308,6 +308,14 @@ impl LogicalPlanBuilder {
308308 let mut nullable = false ;
309309 for ( i, row) in values. iter ( ) . enumerate ( ) {
310310 let value = & row[ j] ;
311+ if !nullable && value. nullable ( & schema) ? {
312+ nullable = true ;
313+ }
314+ let data_type = value. get_type ( & schema) ?;
315+ if data_type == DataType :: Null {
316+ continue ;
317+ }
318+
311319 let metadata = value. metadata ( & schema) ?;
312320 if let Some ( ref cm) = common_metadata {
313321 if & metadata != cm {
@@ -320,13 +328,6 @@ impl LogicalPlanBuilder {
320328 } else {
321329 common_metadata = Some ( metadata. clone ( ) ) ;
322330 }
323- if !nullable && value. nullable ( & schema) ? {
324- nullable = true ;
325- }
326- let data_type = value. get_type ( & schema) ?;
327- if data_type == DataType :: Null {
328- continue ;
329- }
330331
331332 if let Some ( prev_type) = common_type {
332333 // Widen the running type so that it can hold both the
@@ -3252,6 +3253,25 @@ mod tests {
32523253 . is_err( )
32533254 ) ;
32543255
3256+ // Untyped NULL values adopt the type and metadata inferred from
3257+ // concrete values, regardless of their position in the column.
3258+ for values in [
3259+ vec ! [
3260+ vec![ lit( ScalarValue :: Null ) ] ,
3261+ vec![ lit_with_metadata( 1 , Some ( metadata. clone( ) ) ) ] ,
3262+ ] ,
3263+ vec ! [
3264+ vec![ lit_with_metadata( 1 , Some ( metadata. clone( ) ) ) ] ,
3265+ vec![ lit( ScalarValue :: Null ) ] ,
3266+ ] ,
3267+ ] {
3268+ let plan = LogicalPlanBuilder :: values ( values) ?. build ( ) ?;
3269+ let field = plan. schema ( ) . field ( 0 ) ;
3270+ assert_eq ! ( field. data_type( ) , & DataType :: Int32 ) ;
3271+ assert ! ( field. is_nullable( ) ) ;
3272+ assert_eq ! ( * field. metadata( ) , metadata. to_hashmap( ) ) ;
3273+ }
3274+
32553275 Ok ( ( ) )
32563276 }
32573277
0 commit comments