diff --git a/datafusion/physical-expr/src/expressions/case.rs b/datafusion/physical-expr/src/expressions/case.rs index dd98029c739a8..c4849ffcc2ec9 100644 --- a/datafusion/physical-expr/src/expressions/case.rs +++ b/datafusion/physical-expr/src/expressions/case.rs @@ -3500,6 +3500,52 @@ mod tests { ); } + #[test] + fn test_case_when_literal_lookup_fixed_size_binary_to_int32() { + let lookup_map = vec![ + ( + ScalarValue::FixedSizeBinary(1, Some(vec![1])), + ScalarValue::Int32(Some(10)), + ), + ( + ScalarValue::FixedSizeBinary(1, Some(vec![2])), + ScalarValue::Int32(Some(20)), + ), + ]; + + let input_values = ScalarValue::iter_to_array(vec![ + ScalarValue::FixedSizeBinary(1, Some(vec![1])), + ScalarValue::FixedSizeBinary(1, Some(vec![2])), + ScalarValue::FixedSizeBinary(1, Some(vec![3])), + ScalarValue::FixedSizeBinary(1, None), + ]) + .expect("valid fixed size binary array"); + + let expected_no_else = + Arc::new(Int32Array::from(vec![Some(10), Some(20), None, None])) as ArrayRef; + + test_case_when_literal_lookup( + Arc::clone(&input_values), + &lookup_map, + None, + expected_no_else, + ); + + let expected_with_else = Arc::new(Int32Array::from(vec![ + Some(10), + Some(20), + Some(99), + Some(99), + ])) as ArrayRef; + + test_case_when_literal_lookup( + input_values, + &lookup_map, + Some(ScalarValue::Int32(Some(99))), + expected_with_else, + ); + } + /// Reproduces https://github.com/apache/datafusion/issues/22173 /// /// Nested self-referential CASE chains (common in rewrite-style projections) diff --git a/datafusion/physical-expr/src/expressions/case/literal_lookup_table/bytes_like_lookup_table.rs b/datafusion/physical-expr/src/expressions/case/literal_lookup_table/bytes_like_lookup_table.rs index e5cf3f84fd919..658d9cdaeec69 100644 --- a/datafusion/physical-expr/src/expressions/case/literal_lookup_table/bytes_like_lookup_table.rs +++ b/datafusion/physical-expr/src/expressions/case/literal_lookup_table/bytes_like_lookup_table.rs @@ -106,7 +106,7 @@ fn try_get_bytes_iterator( DataType::LargeBinary => Box::new(array.as_binary::().into_iter()), - DataType::FixedSizeBinary(_) => Box::new(array.as_binary::().into_iter()), + DataType::FixedSizeBinary(_) => Box::new(array.as_fixed_size_binary().iter()), DataType::Utf8View => Box::new( array diff --git a/datafusion/sqllogictest/test_files/case.slt b/datafusion/sqllogictest/test_files/case.slt index 3f9058bce865b..712981ed8313b 100644 --- a/datafusion/sqllogictest/test_files/case.slt +++ b/datafusion/sqllogictest/test_files/case.slt @@ -846,6 +846,66 @@ drop table letters; statement ok drop table letters_binary; +# Regression test for https://github.com/apache/datafusion/issues/26012 +# CASE with two or more FixedSizeBinary WHEN literals +query I +SELECT CASE x + WHEN arrow_cast(X'01', 'FixedSizeBinary(1)') THEN 1 + WHEN arrow_cast(X'02', 'FixedSizeBinary(1)') THEN 2 + ELSE 3 + END AS r +FROM (SELECT arrow_cast(X'03', 'FixedSizeBinary(1)') AS x); +---- +3 + +query I +SELECT CASE x + WHEN arrow_cast(X'01', 'FixedSizeBinary(1)') THEN 1 + WHEN arrow_cast(X'02', 'FixedSizeBinary(1)') THEN 2 + ELSE 3 + END AS r +FROM (SELECT arrow_cast(X'02', 'FixedSizeBinary(1)') AS x); +---- +2 + +query I +SELECT CASE x + WHEN arrow_cast(X'01', 'FixedSizeBinary(1)') THEN 1 + WHEN arrow_cast(X'02', 'FixedSizeBinary(1)') THEN 2 + ELSE 3 + END AS r +FROM (SELECT arrow_cast(X'01', 'FixedSizeBinary(1)') AS x); +---- +1 + +query I +SELECT CASE x + WHEN arrow_cast(X'01', 'FixedSizeBinary(1)') THEN 1 + WHEN arrow_cast(X'02', 'FixedSizeBinary(1)') THEN 2 + ELSE 3 + END AS r +FROM (SELECT arrow_cast(NULL, 'FixedSizeBinary(1)') AS x); +---- +3 + +query I +SELECT CASE x + WHEN arrow_cast(X'01', 'FixedSizeBinary(1)') THEN 10 + WHEN arrow_cast(X'02', 'FixedSizeBinary(1)') THEN 20 + ELSE 99 + END AS r +FROM (VALUES + (arrow_cast(X'01', 'FixedSizeBinary(1)')), + (arrow_cast(X'02', 'FixedSizeBinary(1)')), + (arrow_cast(X'03', 'FixedSizeBinary(1)')), + (arrow_cast(NULL, 'FixedSizeBinary(1)')) +) t(x); +---- +10 +20 +99 +99 + # Tests for CASE with boolean expressions statement ok create table booleans (b boolean) as values (true), (false), (null), (true), (null), (false);