diff --git a/datafusion/core/tests/expr_api/simplification.rs b/datafusion/core/tests/expr_api/simplification.rs index 800a087587da..55c5b66e45c7 100644 --- a/datafusion/core/tests/expr_api/simplification.rs +++ b/datafusion/core/tests/expr_api/simplification.rs @@ -27,7 +27,7 @@ use datafusion_common::ScalarValue; use datafusion_common::{DFSchemaRef, ToDFSchema}; use datafusion_expr::expr::ScalarFunction; use datafusion_expr::logical_plan::builder::table_scan_with_filters; -use datafusion_expr::simplify::SimplifyInfo; +use datafusion_expr::simplify::{self, SimplifyInfo}; use datafusion_expr::{ expr, table_scan, Cast, ColumnarValue, ExprSchemable, LogicalPlan, LogicalPlanBuilder, ScalarUDF, Volatility, @@ -693,3 +693,4 @@ fn test_simplify_cycles() { let expected = lit(true); test_simplify_with_cycle_count(expr, expected, 3); } + diff --git a/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs b/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs index 9cb9a6ce0b0b..4c47b1e1bd71 100644 --- a/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs +++ b/datafusion/optimizer/src/simplify_expressions/expr_simplifier.rs @@ -3994,4 +3994,69 @@ mod tests { unimplemented!("not needed for tests") } } + #[derive(Debug)] + struct VolatileUdf { + signature: Signature, + } + + impl VolatileUdf { + pub fn new() -> Self { + Self { + signature: Signature::exact(vec![], Volatility::Volatile), + } + } + } + impl ScalarUDFImpl for VolatileUdf { + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn name(&self) -> &str { + "VolatileUdf" + } + + fn signature(&self) -> &Signature { + &self.signature + } + + fn return_type(&self, _arg_types: &[DataType]) -> Result { + Ok(DataType::Int16) + } + } + #[test] + fn test_optimize_volatile_conditions() { + let fun = Arc::new(ScalarUDF::new_from_impl(VolatileUdf::new())); + let rand = Expr::ScalarFunction(ScalarFunction::new_udf(fun, vec![])); + { + let expr = rand + .clone() + .eq(lit(0)) + .or(col("column1").eq(lit(2)).and(rand.clone().eq(lit(0)))); + + assert_eq!(simplify(expr.clone()), expr); + } + + { + let expr = col("column1") + .eq(lit(2)) + .or(col("column1").eq(lit(2)).and(rand.clone().eq(lit(0)))); + + assert_eq!(simplify(expr), col("column1").eq(lit(2))); + } + + { + let expr = (col("column1").eq(lit(2)).and(rand.clone().eq(lit(0)))).or(col( + "column1", + ) + .eq(lit(2)) + .and(rand.clone().eq(lit(0)))); + + assert_eq!( + simplify(expr), + col("column1") + .eq(lit(2)) + .and((rand.clone().eq(lit(0))).or(rand.clone().eq(lit(0)))) + ); + } + } } diff --git a/datafusion/sqllogictest/test_files/explain.slt b/datafusion/sqllogictest/test_files/explain.slt index 1c11402ae4e1..7125730bb584 100644 --- a/datafusion/sqllogictest/test_files/explain.slt +++ b/datafusion/sqllogictest/test_files/explain.slt @@ -413,38 +413,3 @@ physical_plan 02)--PlaceholderRowExec - - -query TT -explain select * from VALUES (1), (2) where random() = 0 OR (column1 = 2 AND random() = 0); ----- -logical_plan -01)Filter: random() = Float64(0) OR column1 = Int64(2) AND random() = Float64(0) -02)--Values: (Int64(1)), (Int64(2)) -physical_plan -01)CoalesceBatchesExec: target_batch_size=8192 -02)--FilterExec: random() = 0 OR column1@0 = 2 AND random() = 0 -03)----ValuesExec - -query TT -explain select * from VALUES (1), (2) where column1 = 2 OR (column1 = 2 AND random() = 0); ----- -logical_plan -01)Filter: column1 = Int64(2) -02)--Values: (Int64(1)), (Int64(2)) -physical_plan -01)CoalesceBatchesExec: target_batch_size=8192 -02)--FilterExec: column1@0 = 2 -03)----ValuesExec - - -query TT -explain select * from VALUES (1), (2) where column1 = 2 AND random() = 0 OR column1 = 2 AND random() = 0; ----- -logical_plan -01)Filter: column1 = Int64(2) AND (random() = Float64(0) OR random() = Float64(0)) -02)--Values: (Int64(1)), (Int64(2)) -physical_plan -01)CoalesceBatchesExec: target_batch_size=8192 -02)--FilterExec: column1@0 = 2 AND (random() = 0 OR random() = 0) -03)----ValuesExec