From b223a09decf015942bbfd2fc9d1bc3a1d863a450 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Sun, 7 Dec 2025 07:58:33 -0500 Subject: [PATCH 1/2] slt test coverage for `CASE` exprs with constant value lookup tables --- datafusion/sqllogictest/test_files/case.slt | 129 ++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/datafusion/sqllogictest/test_files/case.slt b/datafusion/sqllogictest/test_files/case.slt index 3905575d22dc9..035092a0535fb 100644 --- a/datafusion/sqllogictest/test_files/case.slt +++ b/datafusion/sqllogictest/test_files/case.slt @@ -703,3 +703,132 @@ logical_plan physical_plan 01)ProjectionExec: expr=[column1@0 as CASE WHEN CASE WHEN t.a IS NOT NULL THEN t.a ELSE Int64(1) END IS NOT NULL THEN t.a ELSE Int64(1) END] 02)--DataSourceExec: partitions=1, partition_sizes=[1] + +##### +# CASE with literal characters (to test lookup table CASE optimization) +##### +statement ok +create table source (letter varchar) as values ('a'), ('b'), (NULL), ('c'), ('a'), ('c'), ('d'); + +# Table with different string types +statement ok +create table letters as +select + arrow_cast(letter, 'Utf8') as letter_utf8, + arrow_cast(letter, 'LargeUtf8') as letter_large_utf8, + arrow_cast(letter, 'Utf8View') as letter_utf8_view, + arrow_cast(letter, 'Dictionary(Int32, Utf8)') as letter_string_dict, +from source; + + +query TIIIII +select + letter_utf8 as letter + ,CASE letter_utf8 WHEN 'b' THEN 1 WHEN 'a' THEN 2 WHEN 'd' THEN 3 ELSE 0 END as utf8 + ,CASE letter_large_utf8 WHEN 'b' THEN 1 WHEN 'a' THEN 2 WHEN 'd' THEN 3 ELSE 0 END as large_utf8 + ,CASE letter_utf8_view WHEN 'b' THEN 1 WHEN 'a' THEN 2 WHEN 'd' THEN 3 ELSE 0 END as utf8_view + ,CASE letter_string_dict WHEN 'b' THEN 1 WHEN 'a' THEN 2 WHEN 'd' THEN 3 ELSE 0 END as string_dict + ,CASE letter_utf8 WHEN 'b' THEN 1 WHEN NULL THEN 2 WHEN 'd' THEN 3 ELSE 0 END as utf8_with_null +FROM letters; +---- +a 2 2 2 2 0 +b 1 1 1 1 1 +NULL 0 0 0 0 0 +c 0 0 0 0 0 +a 2 2 2 2 0 +c 0 0 0 0 0 +d 3 3 3 3 3 + +statement ok +create table letters_binary as +select + arrow_cast(letter, 'Binary') as letter_binary, + arrow_cast(letter, 'LargeBinary') as letter_large_binary, + arrow_cast(letter, 'BinaryView') as letter_binary_view, + arrow_cast(letter, 'Dictionary(Int32, Binary)') as letter_binary_dict, + arrow_cast(arrow_cast(letter, 'Binary'), 'FixedSizeBinary(1)') as letter_fsb +from source; + +query ?IIIII +select + letter_binary as letter + ,CASE letter_binary WHEN X'62' THEN 1 WHEN X'61' THEN 2 WHEN X'64' THEN 3 ELSE 0 END as binary + ,CASE letter_large_binary WHEN X'62' THEN 1 WHEN X'61' THEN 2 WHEN X'64' THEN 3 ELSE 0 END as large_binary + ,CASE letter_binary_view WHEN X'62' THEN 1 WHEN X'61' THEN 2 WHEN X'64' THEN 3 ELSE 0 END as binary_view + ,CASE letter_binary_dict WHEN X'62' THEN 1 WHEN X'61' THEN 2 WHEN X'64' THEN 3 ELSE 0 END as binary_dict + ,CASE letter_fsb WHEN X'62' THEN 1 WHEN X'61' THEN 2 WHEN X'64' THEN 3 ELSE 0 END as fsb +FROM letters_binary; +---- +61 2 2 2 2 2 +62 1 1 1 1 1 +NULL 0 0 0 0 0 +63 0 0 0 0 0 +61 2 2 2 2 2 +63 0 0 0 0 0 +64 3 3 3 3 3 + +statement ok +drop table source; + + +statement ok +drop table letters; + +statement ok +drop table letters_binary; + +# Tests for CASE with boolean expressions +statement ok +create table booleans (b boolean) as values (true), (false), (null), (true), (null), (false); + +query BIII +select + b as boolean_value + ,CASE b WHEN true THEN 1 WHEN false THEN 2 ELSE 0 END as boolean_case + ,CASE b WHEN false THEN 1 WHEN true THEN 2 ELSE 0 END as boolean_case_rev + ,CASE b WHEN true THEN 1 WHEN NULL THEN 2 WHEN false THEN 3 ELSE 0 END as boolean_with_nulls +FROM booleans; +---- +true 1 2 1 +false 2 1 3 +NULL 0 0 0 +true 1 2 1 +NULL 0 0 0 +false 2 1 3 + +statement ok +drop table booleans; + +# Tests for CASE with floating point literals +statement ok +create table float_source (f float) as values (1.0), (2.0), (null), (3.5), (2.0), (null); + +statement ok +create table floats as +select + arrow_cast(f, 'Float16') as f16, + arrow_cast(f, 'Float32') as f32, + arrow_cast(f, 'Float64') as f64, + arrow_cast(f, 'Dictionary(Int32, Float32)') as f32_dict, +from float_source; + +query RTTTT +select + f32 as float_value + ,CASE f16 WHEN 1.0 THEN 'one' WHEN 3.5 THEN 'three_point_five' WHEN 2.0 THEN 'two' ELSE 'N/A' END as f16_case + ,CASE f32 WHEN 1.0 THEN 'one' WHEN 3.5 THEN 'three_point_five' WHEN 2.0 THEN 'two' ELSE 'N/A' END as f32_case + ,CASE f64 WHEN 1.0 THEN 'one' WHEN 3.5 THEN 'three_point_five' WHEN 2.0 THEN 'two' ELSE 'N/A' END as f64_case + ,CASE f32_dict WHEN 1.0 THEN 'one' WHEN 3.5 THEN 'three_point_five' WHEN 2.0 THEN 'two' ELSE 'N/A' END as f32_dict_case +FROM floats; +---- +1 one one one one +2 two two two two +NULL N/A N/A N/A N/A +3.5 three_point_five three_point_five three_point_five three_point_five +2 two two two two +NULL N/A N/A N/A N/A + + +##### +# End of lookup table CASE tests +##### From f47de113302a9934997effe26dd99c2dbaae9b51 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Sun, 7 Dec 2025 08:03:01 -0500 Subject: [PATCH 2/2] cleanup --- datafusion/sqllogictest/test_files/case.slt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/datafusion/sqllogictest/test_files/case.slt b/datafusion/sqllogictest/test_files/case.slt index 035092a0535fb..074d216ac7524 100644 --- a/datafusion/sqllogictest/test_files/case.slt +++ b/datafusion/sqllogictest/test_files/case.slt @@ -828,6 +828,11 @@ NULL N/A N/A N/A N/A 2 two two two two NULL N/A N/A N/A N/A +statement ok +drop table float_source; + +statement ok +drop table floats; ##### # End of lookup table CASE tests