@@ -4,7 +4,7 @@ use std::{ops::ControlFlow, sync::Arc};
44use arrow:: {
55 array:: {
66 Array , ArrayRef , BinaryBuilder , BooleanBuilder , Date32Builder , DurationMicrosecondBuilder ,
7- Float64Builder , Int64Builder , StringBuilder , Time64MicrosecondBuilder ,
7+ Float64Builder , Int64Builder , NullBuilder , StringBuilder , Time64MicrosecondBuilder ,
88 TimestampMicrosecondBuilder ,
99 } ,
1010 datatypes:: { DataType , TimeUnit } ,
@@ -13,8 +13,8 @@ use chrono::{DateTime, Datelike, NaiveDate, TimeZone, Timelike, Utc};
1313use datafusion_common:: {
1414 cast:: {
1515 as_binary_array, as_boolean_array, as_date32_array, as_duration_microsecond_array,
16- as_float64_array, as_int64_array, as_string_array , as_time64_microsecond_array ,
17- as_timestamp_microsecond_array,
16+ as_float64_array, as_int64_array, as_null_array , as_string_array ,
17+ as_time64_microsecond_array , as_timestamp_microsecond_array,
1818 } ,
1919 error:: Result as DataFusionResult ,
2020 exec_datafusion_err, exec_err,
@@ -53,6 +53,7 @@ impl PythonType {
5353 Self :: DateTime => DataType :: Timestamp ( TimeUnit :: Microsecond , None ) ,
5454 Self :: Float => DataType :: Float64 ,
5555 Self :: Int => DataType :: Int64 ,
56+ Self :: None => DataType :: Null ,
5657 Self :: Str => DataType :: Utf8 ,
5758 Self :: Bytes => DataType :: Binary ,
5859 Self :: Date => DataType :: Date32 ,
@@ -166,6 +167,16 @@ impl PythonType {
166167
167168 Ok ( Box :: new ( it) )
168169 }
170+ Self :: None => {
171+ let array = as_null_array ( array) ?;
172+
173+ let val = PyNone :: get ( py)
174+ . into_bound_py_any ( py)
175+ . map_err ( |e| exec_datafusion_err ! ( "cannot build Python None value: {e}" ) ) ?;
176+ let it = std:: iter:: repeat_n ( Some ( val) , array. len ( ) ) . map ( Ok ) ;
177+
178+ Ok ( Box :: new ( it) )
179+ }
169180 Self :: Str => {
170181 let array = as_string_array ( array) ?;
171182
@@ -294,6 +305,7 @@ impl PythonType {
294305 Self :: DateTime => Box :: new ( TimestampMicrosecondBuilder :: with_capacity ( num_rows) ) ,
295306 Self :: Float => Box :: new ( Float64Builder :: with_capacity ( num_rows) ) ,
296307 Self :: Int => Box :: new ( Int64Builder :: with_capacity ( num_rows) ) ,
308+ Self :: None => Box :: new ( NullBuilder :: new ( ) ) ,
297309 Self :: Str => Box :: new ( StringBuilder :: with_capacity ( num_rows, 1024 ) ) ,
298310 Self :: Bytes => Box :: new ( BinaryBuilder :: with_capacity ( num_rows, 1024 ) ) ,
299311 Self :: Date => Box :: new ( Date32Builder :: with_capacity ( num_rows) ) ,
@@ -467,6 +479,24 @@ impl<'py> ArrayBuilder<'py> for Int64Builder {
467479 }
468480}
469481
482+ impl < ' py > ArrayBuilder < ' py > for NullBuilder {
483+ fn push ( & mut self , val : Bound < ' py , PyAny > ) -> DataFusionResult < ( ) > {
484+ val. cast_exact :: < PyNone > ( ) . map_err ( |_| {
485+ exec_datafusion_err ! ( "expected `None` but got {}" , py_representation( & val) )
486+ } ) ?;
487+ self . append_empty_value ( ) ;
488+ Ok ( ( ) )
489+ }
490+
491+ fn skip ( & mut self ) {
492+ self . append_empty_value ( ) ;
493+ }
494+
495+ fn finish ( & mut self ) -> ArrayRef {
496+ Arc :: new ( self . finish ( ) )
497+ }
498+ }
499+
470500impl < ' py > ArrayBuilder < ' py > for StringBuilder {
471501 fn push ( & mut self , val : Bound < ' py , PyAny > ) -> DataFusionResult < ( ) > {
472502 let val: & str = val. extract ( ) . map_err ( |_| {
0 commit comments