This is an automated email from the ASF dual-hosted git repository.
findepi 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 424cf5afbb Restore lazy evaluation of fallible CASE (#15390)
424cf5afbb is described below
commit 424cf5afbbe772eb1f4819f3740ec7a9b58ffad9
Author: Piotr Findeisen <[email protected]>
AuthorDate: Tue Mar 25 10:24:11 2025 +0100
Restore lazy evaluation of fallible CASE (#15390)
* Restore lazy evaluation of fallible CASE
Commit 0f4b8b136ceb9132fd6b6595bd6a09a09707f5d9 introduced a new
optimized evaluation mode for CASE expression with exactly one WHEN-THEN
clause and ELSE clause being present. Apparently, the new mode did not
take into account expensive or fallible expressions, as it
unconditionally evaluated both branches. This is definitely incorrect
for fallible expressions. For these, fallback to the original execution
mode.
* Workaround for running sqllogictests in RustRover
---
datafusion/physical-expr/src/expressions/case.rs | 34 +++++++++++++-----------
datafusion/sqllogictest/bin/sqllogictests.rs | 6 +++++
datafusion/sqllogictest/test_files/case.slt | 11 ++++++++
3 files changed, 35 insertions(+), 16 deletions(-)
diff --git a/datafusion/physical-expr/src/expressions/case.rs
b/datafusion/physical-expr/src/expressions/case.rs
index 67fab3912c..854c715eb0 100644
--- a/datafusion/physical-expr/src/expressions/case.rs
+++ b/datafusion/physical-expr/src/expressions/case.rs
@@ -156,7 +156,10 @@ impl CaseExpr {
&& else_expr.as_ref().unwrap().as_any().is::<Literal>()
{
EvalMethod::ScalarOrScalar
- } else if when_then_expr.len() == 1 && else_expr.is_some() {
+ } else if when_then_expr.len() == 1
+ && is_cheap_and_infallible(&(when_then_expr[0].1))
+ && else_expr.as_ref().is_some_and(is_cheap_and_infallible)
+ {
EvalMethod::ExpressionOrExpression
} else {
EvalMethod::NoExpression
@@ -813,9 +816,18 @@ mod tests {
}
fn case_test_batch1() -> Result<RecordBatch> {
- let schema = Schema::new(vec![Field::new("a", DataType::Int32, true)]);
+ let schema = Schema::new(vec![
+ Field::new("a", DataType::Int32, true),
+ Field::new("b", DataType::Int32, true),
+ Field::new("c", DataType::Int32, true),
+ ]);
let a = Int32Array::from(vec![Some(1), Some(0), None, Some(5)]);
- let batch = RecordBatch::try_new(Arc::new(schema), vec![Arc::new(a)])?;
+ let b = Int32Array::from(vec![Some(3), None, Some(14), Some(7)]);
+ let c = Int32Array::from(vec![Some(0), Some(-3), Some(777), None]);
+ let batch = RecordBatch::try_new(
+ Arc::new(schema),
+ vec![Arc::new(a), Arc::new(b), Arc::new(c)],
+ )?;
Ok(batch)
}
@@ -1306,18 +1318,8 @@ mod tests {
lit(2i32),
&batch.schema(),
)?;
- let then = binary(
- col("a", &schema)?,
- Operator::Plus,
- lit(1i32),
- &batch.schema(),
- )?;
- let else_expr = binary(
- col("a", &schema)?,
- Operator::Minus,
- lit(1i32),
- &batch.schema(),
- )?;
+ let then = col("b", &schema)?;
+ let else_expr = col("c", &schema)?;
let expr = CaseExpr::try_new(None, vec![(when, then)],
Some(else_expr))?;
assert!(matches!(
expr.eval_method,
@@ -1329,7 +1331,7 @@ mod tests {
.expect("Failed to convert to array");
let result = as_int32_array(&result).expect("failed to downcast to
Int32Array");
- let expected = &Int32Array::from(vec![Some(2), Some(1), None,
Some(4)]);
+ let expected = &Int32Array::from(vec![Some(3), None, Some(777), None]);
assert_eq!(expected, result);
Ok(())
diff --git a/datafusion/sqllogictest/bin/sqllogictests.rs
b/datafusion/sqllogictest/bin/sqllogictests.rs
index bbb88819ef..5894ec056a 100644
--- a/datafusion/sqllogictest/bin/sqllogictests.rs
+++ b/datafusion/sqllogictest/bin/sqllogictests.rs
@@ -581,6 +581,12 @@ struct Options {
help = "IGNORED (for compatibility with built-in rust test runner)"
)]
ignored: bool,
+
+ #[clap(
+ long,
+ help = "IGNORED (for compatibility with built-in rust test runner)"
+ )]
+ nocapture: bool,
}
impl Options {
diff --git a/datafusion/sqllogictest/test_files/case.slt
b/datafusion/sqllogictest/test_files/case.slt
index 8e470fe988..21913005e2 100644
--- a/datafusion/sqllogictest/test_files/case.slt
+++ b/datafusion/sqllogictest/test_files/case.slt
@@ -467,7 +467,18 @@ FROM t;
----
[{foo: blarg}]
+query II
+SELECT v, CASE WHEN v != 0 THEN 10/v ELSE 42 END FROM (VALUES (0), (1), (2))
t(v)
+----
+0 42
+1 10
+2 5
+query II
+SELECT v, CASE WHEN v < 0 THEN 10/0 ELSE 1 END FROM (VALUES (1), (2)) t(v)
+----
+1 1
+2 1
statement ok
drop table t
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]