Skip to content

Commit 66c2988

Browse files
authored
Fix: to_char Function Now Correctly Handles DATE Values in DataFusion (#14970)
* revert _to_char_scalar to before #14908 * Amend formatted loop - handle null * revert _to_char_array to before #14908 * add slt test
1 parent d288b80 commit 66c2988

File tree

2 files changed

+31
-47
lines changed

2 files changed

+31
-47
lines changed

datafusion/functions/src/datetime/to_char.rs

Lines changed: 11 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,6 @@ 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-
}
223215
if format.is_none() {
224216
if is_scalar_expression {
225217
return Ok(ColumnarValue::Scalar(ScalarValue::Utf8(None)));
@@ -234,15 +226,21 @@ fn _to_char_scalar(
234226
};
235227

236228
let formatter = ArrayFormatter::try_new(array.as_ref(), &format_options)?;
237-
let formatted: Result<Vec<_>, ArrowError> = (0..array.len())
238-
.map(|i| formatter.value(i).try_to_string())
229+
let formatted: Result<Vec<Option<String>>, ArrowError> = (0..array.len())
230+
.map(|i| {
231+
if array.is_null(i) {
232+
Ok(None)
233+
} else {
234+
formatter.value(i).try_to_string().map(Some)
235+
}
236+
})
239237
.collect();
240238

241239
if let Ok(formatted) = formatted {
242240
if is_scalar_expression {
243-
Ok(ColumnarValue::Scalar(ScalarValue::Utf8(Some(
244-
formatted.first().unwrap().to_string(),
245-
))))
241+
Ok(ColumnarValue::Scalar(ScalarValue::Utf8(
242+
formatted.first().unwrap().clone(),
243+
)))
246244
} else {
247245
Ok(ColumnarValue::Array(
248246
Arc::new(StringArray::from(formatted)) as ArrayRef
@@ -260,13 +258,6 @@ fn _to_char_array(args: &[ColumnarValue]) -> Result<ColumnarValue> {
260258
let data_type = arrays[0].data_type();
261259

262260
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-
270261
let format = if format_array.is_null(idx) {
271262
None
272263
} else {
@@ -678,31 +669,4 @@ mod tests {
678669
"Execution error: Format for `to_char` must be non-null Utf8, received Timestamp(Nanosecond, None)"
679670
);
680671
}
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-
}
708672
}

datafusion/sqllogictest/test_files/timestamps.slt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2847,6 +2847,26 @@ SELECT to_char(null, '%d-%m-%Y');
28472847
----
28482848
NULL
28492849

2850+
query T
2851+
SELECT to_char(date_column, '%Y-%m-%d')
2852+
FROM (VALUES
2853+
(DATE '2020-09-01'),
2854+
(NULL)
2855+
) AS t(date_column);
2856+
----
2857+
2020-09-01
2858+
NULL
2859+
2860+
query T
2861+
SELECT to_char(date_column, '%Y-%m-%d')
2862+
FROM (VALUES
2863+
(NULL),
2864+
(DATE '2020-09-01')
2865+
) AS t(date_column);
2866+
----
2867+
NULL
2868+
2020-09-01
2869+
28502870
query T
28512871
SELECT to_char(column1, column2)
28522872
FROM

0 commit comments

Comments
 (0)