Skip to content

Commit 0a85bb4

Browse files
authored
Improve case expr constant handling, Add .slt test (#14159)
1 parent 98e8942 commit 0a85bb4

File tree

2 files changed

+90
-24
lines changed
  • datafusion

2 files changed

+90
-24
lines changed

datafusion/physical-expr/src/expressions/case.rs

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -345,34 +345,37 @@ impl CaseExpr {
345345
let when_expr = &self.when_then_expr[0].0;
346346
let then_expr = &self.when_then_expr[0].1;
347347

348-
let when_expr_value = when_expr.evaluate(batch)?;
349-
let when_expr_value = match when_expr_value {
348+
match when_expr.evaluate(batch)? {
349+
// WHEN true --> column
350+
ColumnarValue::Scalar(ScalarValue::Boolean(Some(true))) => {
351+
then_expr.evaluate(batch)
352+
}
353+
// WHEN [false | null] --> NULL
350354
ColumnarValue::Scalar(_) => {
351-
ColumnarValue::Array(when_expr_value.into_array(batch.num_rows())?)
355+
// return scalar NULL value
356+
ScalarValue::try_from(self.data_type(&batch.schema())?)
357+
.map(ColumnarValue::Scalar)
352358
}
353-
other => other,
354-
};
355-
356-
if let ColumnarValue::Array(bit_mask) = when_expr_value {
357-
let bit_mask = bit_mask
358-
.as_any()
359-
.downcast_ref::<BooleanArray>()
360-
.expect("predicate should evaluate to a boolean array");
361-
// invert the bitmask
362-
let bit_mask = match bit_mask.null_count() {
363-
0 => not(bit_mask)?,
364-
_ => not(&prep_null_mask_filter(bit_mask))?,
365-
};
366-
match then_expr.evaluate(batch)? {
367-
ColumnarValue::Array(array) => {
368-
Ok(ColumnarValue::Array(nullif(&array, &bit_mask)?))
369-
}
370-
ColumnarValue::Scalar(_) => {
371-
internal_err!("expression did not evaluate to an array")
359+
// WHEN column --> column
360+
ColumnarValue::Array(bit_mask) => {
361+
let bit_mask = bit_mask
362+
.as_any()
363+
.downcast_ref::<BooleanArray>()
364+
.expect("predicate should evaluate to a boolean array");
365+
// invert the bitmask
366+
let bit_mask = match bit_mask.null_count() {
367+
0 => not(bit_mask)?,
368+
_ => not(&prep_null_mask_filter(bit_mask))?,
369+
};
370+
match then_expr.evaluate(batch)? {
371+
ColumnarValue::Array(array) => {
372+
Ok(ColumnarValue::Array(nullif(&array, &bit_mask)?))
373+
}
374+
ColumnarValue::Scalar(_) => {
375+
internal_err!("expression did not evaluate to an array")
376+
}
372377
}
373378
}
374-
} else {
375-
internal_err!("predicate did not evaluate to an array")
376379
}
377380
}
378381

datafusion/sqllogictest/test_files/case.slt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,3 +235,66 @@ SELECT CASE WHEN a < 5 THEN a + b ELSE b - NVL(a, 0) END FROM foo
235235
NULL
236236
NULL
237237
7
238+
239+
# Reproducer for
240+
# https://github.com/apache/datafusion/issues/14099
241+
query I
242+
SELECT - 79 * + 91 * - COUNT ( * ) * + - 2 * + - NULLIF ( - 49, - COALESCE ( - + 69, - COALESCE ( + COALESCE ( - 20, ( - 18 ) * + COUNT ( * ) + - 93, - CASE 51 WHEN + COUNT ( * ) + 28 THEN 0 ELSE + 29 * + CASE ( 50 ) WHEN - ( - ( CASE WHEN NOT + 37 IS NULL THEN + COUNT ( * ) END ) ) THEN NULL WHEN - 46 + 87 * - 28 THEN 85 WHEN - COUNT ( * ) THEN NULL END END ), COUNT ( * ) - 39 ) * + 22 ) / - COUNT ( * ) )
243+
----
244+
-704522
245+
246+
247+
query B
248+
select case when true then false end from foo;
249+
----
250+
false
251+
false
252+
false
253+
false
254+
false
255+
false
256+
257+
query I
258+
select case when true then a end from foo;
259+
----
260+
1
261+
3
262+
5
263+
NULL
264+
6
265+
NULL
266+
267+
query I
268+
select case when false then a end from foo;
269+
----
270+
NULL
271+
NULL
272+
NULL
273+
NULL
274+
NULL
275+
NULL
276+
277+
query I
278+
select case when null then a end from foo;
279+
----
280+
NULL
281+
NULL
282+
NULL
283+
NULL
284+
NULL
285+
NULL
286+
287+
288+
query B
289+
select case when a=1 then false end from foo;
290+
----
291+
false
292+
false
293+
false
294+
false
295+
false
296+
false
297+
298+
299+
statement ok
300+
drop table foo

0 commit comments

Comments
 (0)