@@ -212,6 +212,14 @@ fn _to_char_scalar(
212212 let is_scalar_expression = matches ! ( & expression, ColumnarValue :: Scalar ( _) ) ;
213213 let array = expression. into_array ( 1 ) ?;
214214
215+ // fix https://github.com/apache/datafusion/issues/14884
216+ // If the input date/time is null, return a null Utf8 result.
217+ if array. is_null ( 0 ) {
218+ return Ok ( match is_scalar_expression {
219+ true => ColumnarValue :: Scalar ( ScalarValue :: Utf8 ( None ) ) ,
220+ false => ColumnarValue :: Array ( new_null_array ( & Utf8 , array. len ( ) ) ) ,
221+ } ) ;
222+ }
215223 if format. is_none ( ) {
216224 if is_scalar_expression {
217225 return Ok ( ColumnarValue :: Scalar ( ScalarValue :: Utf8 ( None ) ) ) ;
@@ -252,6 +260,13 @@ fn _to_char_array(args: &[ColumnarValue]) -> Result<ColumnarValue> {
252260 let data_type = arrays[ 0 ] . data_type ( ) ;
253261
254262 for idx in 0 ..arrays[ 0 ] . len ( ) {
263+ // fix https://github.com/apache/datafusion/issues/14884
264+ // If the date/time value is null, push None.
265+ if arrays[ 0 ] . is_null ( idx) {
266+ results. push ( None ) ;
267+ continue ;
268+ }
269+
255270 let format = if format_array. is_null ( idx) {
256271 None
257272 } else {
@@ -663,4 +678,31 @@ mod tests {
663678 "Execution error: Format for `to_char` must be non-null Utf8, received Timestamp(Nanosecond, None)"
664679 ) ;
665680 }
681+
682+ #[ test]
683+ fn test_to_char_input_none_array ( ) {
684+ let date_array = Arc :: new ( Date32Array :: from ( vec ! [ Some ( 18506 ) , None ] ) ) as ArrayRef ;
685+ let format_array =
686+ StringArray :: from ( vec ! [ "%Y-%m-%d" . to_string( ) , "%Y-%m-%d" . to_string( ) ] ) ;
687+ let args = datafusion_expr:: ScalarFunctionArgs {
688+ args : vec ! [
689+ ColumnarValue :: Array ( date_array) ,
690+ ColumnarValue :: Array ( Arc :: new( format_array) as ArrayRef ) ,
691+ ] ,
692+ number_rows : 2 ,
693+ return_type : & DataType :: Utf8 ,
694+ } ;
695+ let result = ToCharFunc :: new ( )
696+ . invoke_with_args ( args)
697+ . expect ( "Expected no error" ) ;
698+ if let ColumnarValue :: Array ( result) = result {
699+ let result = result. as_any ( ) . downcast_ref :: < StringArray > ( ) . unwrap ( ) ;
700+ assert_eq ! ( result. len( ) , 2 ) ;
701+ // The first element is valid, second is null.
702+ assert ! ( !result. is_null( 0 ) ) ;
703+ assert ! ( result. is_null( 1 ) ) ;
704+ } else {
705+ panic ! ( "Expected an array value" ) ;
706+ }
707+ }
666708}
0 commit comments