Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion datafusion/expr/src/type_coercion/functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,13 @@ fn coerced_from<'a>(
(Timestamp(_, Some(_)), Null | Timestamp(_, _) | Date32 | Utf8 | LargeUtf8) => {
Some(type_into.clone())
}
// Null can be coerced to any target type, provided the cast is valid.
// This mirrors null_coercion() in binary comparison coercion
// (expr-common/src/type_coercion/binary.rs) and is the symmetric
// counterpart of the (Null, _) arm above. Without this, untyped
// placeholders ($1, $foo) inside function calls fail signature matching
// because their Null type doesn't match any Exact(...) variant.
(_, Null) if can_cast_types(type_from, type_into) => Some(type_into.clone()),
_ => None,
}
}
Expand All @@ -937,7 +944,7 @@ mod tests {
use crate::Volatility;

use super::*;
use arrow::datatypes::Field;
use arrow::datatypes::{Field, IntervalUnit};
use datafusion_common::{
assert_contains,
types::{logical_binary, logical_int64},
Expand All @@ -956,6 +963,36 @@ mod tests {
}
}

#[test]
fn test_coerced_from_null() {
// Null should coerce to Interval (the motivating case)
assert_eq!(
coerced_from(
&DataType::Interval(IntervalUnit::MonthDayNano),
&DataType::Null
),
Some(DataType::Interval(IntervalUnit::MonthDayNano))
);

// Null should coerce to Date32
assert_eq!(
coerced_from(&DataType::Date32, &DataType::Null),
Some(DataType::Date32)
);

// Null should coerce to Timestamp with timezone
assert_eq!(
coerced_from(
&DataType::Timestamp(TimeUnit::Microsecond, Some("+00".into())),
&DataType::Null
),
Some(DataType::Timestamp(
TimeUnit::Microsecond,
Some("+00".into())
))
);
}

#[test]
fn test_maybe_data_types() {
// this vec contains: arg1, arg2, expected result
Expand Down
6 changes: 6 additions & 0 deletions datafusion/sqllogictest/test_files/datetime/timestamps.slt
Original file line number Diff line number Diff line change
Expand Up @@ -5370,3 +5370,9 @@ SELECT to_timestamp(arrow_cast(100.5, 'Float16'), name) FROM test_to_timestamp_s

statement ok
drop table test_to_timestamp_scalar

# date_bin with NULL interval should return NULL, not a planning error
query P
SELECT date_bin(NULL, TIMESTAMP '2023-01-01 12:30:00', TIMESTAMP '2023-01-01 12:00:00')
----
NULL
2 changes: 1 addition & 1 deletion datafusion/sqllogictest/test_files/nvl.slt
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ SELECT NVL(1, 3);
----
1

query I
query B
SELECT NVL(NULL, NULL);
----
NULL
Expand Down
Loading