This is an automated email from the ASF dual-hosted git repository.
jayzhan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion.git
The following commit(s) were added to refs/heads/main by this push:
new 0a85bb43a0 Improve case expr constant handling, Add .slt test (#14159)
0a85bb43a0 is described below
commit 0a85bb43a035417f24d06684b9b9f7675430f5ee
Author: Andrew Lamb <[email protected]>
AuthorDate: Sun Jan 19 20:13:16 2025 -0500
Improve case expr constant handling, Add .slt test (#14159)
---
datafusion/physical-expr/src/expressions/case.rs | 51 ++++++++++---------
datafusion/sqllogictest/test_files/case.slt | 63 ++++++++++++++++++++++++
2 files changed, 90 insertions(+), 24 deletions(-)
diff --git a/datafusion/physical-expr/src/expressions/case.rs
b/datafusion/physical-expr/src/expressions/case.rs
index be1043d09c..78606f05ae 100644
--- a/datafusion/physical-expr/src/expressions/case.rs
+++ b/datafusion/physical-expr/src/expressions/case.rs
@@ -345,34 +345,37 @@ impl CaseExpr {
let when_expr = &self.when_then_expr[0].0;
let then_expr = &self.when_then_expr[0].1;
- let when_expr_value = when_expr.evaluate(batch)?;
- let when_expr_value = match when_expr_value {
+ match when_expr.evaluate(batch)? {
+ // WHEN true --> column
+ ColumnarValue::Scalar(ScalarValue::Boolean(Some(true))) => {
+ then_expr.evaluate(batch)
+ }
+ // WHEN [false | null] --> NULL
ColumnarValue::Scalar(_) => {
-
ColumnarValue::Array(when_expr_value.into_array(batch.num_rows())?)
+ // return scalar NULL value
+ ScalarValue::try_from(self.data_type(&batch.schema())?)
+ .map(ColumnarValue::Scalar)
}
- other => other,
- };
-
- if let ColumnarValue::Array(bit_mask) = when_expr_value {
- let bit_mask = bit_mask
- .as_any()
- .downcast_ref::<BooleanArray>()
- .expect("predicate should evaluate to a boolean array");
- // invert the bitmask
- let bit_mask = match bit_mask.null_count() {
- 0 => not(bit_mask)?,
- _ => not(&prep_null_mask_filter(bit_mask))?,
- };
- match then_expr.evaluate(batch)? {
- ColumnarValue::Array(array) => {
- Ok(ColumnarValue::Array(nullif(&array, &bit_mask)?))
- }
- ColumnarValue::Scalar(_) => {
- internal_err!("expression did not evaluate to an array")
+ // WHEN column --> column
+ ColumnarValue::Array(bit_mask) => {
+ let bit_mask = bit_mask
+ .as_any()
+ .downcast_ref::<BooleanArray>()
+ .expect("predicate should evaluate to a boolean array");
+ // invert the bitmask
+ let bit_mask = match bit_mask.null_count() {
+ 0 => not(bit_mask)?,
+ _ => not(&prep_null_mask_filter(bit_mask))?,
+ };
+ match then_expr.evaluate(batch)? {
+ ColumnarValue::Array(array) => {
+ Ok(ColumnarValue::Array(nullif(&array, &bit_mask)?))
+ }
+ ColumnarValue::Scalar(_) => {
+ internal_err!("expression did not evaluate to an
array")
+ }
}
}
- } else {
- internal_err!("predicate did not evaluate to an array")
}
}
diff --git a/datafusion/sqllogictest/test_files/case.slt
b/datafusion/sqllogictest/test_files/case.slt
index 6b4dffd12c..157bfb8a02 100644
--- a/datafusion/sqllogictest/test_files/case.slt
+++ b/datafusion/sqllogictest/test_files/case.slt
@@ -235,3 +235,66 @@ SELECT CASE WHEN a < 5 THEN a + b ELSE b - NVL(a, 0) END
FROM foo
NULL
NULL
7
+
+# Reproducer for
+# https://github.com/apache/datafusion/issues/14099
+query I
+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 ( * ) )
+----
+-704522
+
+
+query B
+select case when true then false end from foo;
+----
+false
+false
+false
+false
+false
+false
+
+query I
+select case when true then a end from foo;
+----
+1
+3
+5
+NULL
+6
+NULL
+
+query I
+select case when false then a end from foo;
+----
+NULL
+NULL
+NULL
+NULL
+NULL
+NULL
+
+query I
+select case when null then a end from foo;
+----
+NULL
+NULL
+NULL
+NULL
+NULL
+NULL
+
+
+query B
+select case when a=1 then false end from foo;
+----
+false
+false
+false
+false
+false
+false
+
+
+statement ok
+drop table foo
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]