Skip to main content

datafusion_optimizer/simplify_expressions/
expr_simplifier.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Expression simplification API
19
20use arrow::{
21    array::{Array, AsArray, new_null_array},
22    datatypes::{DataType, Field, Schema},
23    record_batch::RecordBatch,
24};
25use std::borrow::Cow;
26use std::collections::HashSet;
27use std::ops::Not;
28use std::sync::Arc;
29use std::sync::LazyLock;
30
31use datafusion_common::config::ConfigOptions;
32use datafusion_common::nested_struct::has_one_of_more_common_fields;
33use datafusion_common::{
34    DFSchema, DataFusionError, Result, ScalarValue, exec_datafusion_err, internal_err,
35};
36use datafusion_common::{
37    HashMap,
38    cast::{as_large_list_array, as_list_array},
39    metadata::FieldMetadata,
40    tree_node::{Transformed, TransformedResult, TreeNode, TreeNodeRewriter},
41};
42use datafusion_expr::expr::HigherOrderFunction;
43use datafusion_expr::physical_planning_context::PhysicalPlanningContext;
44use datafusion_expr::{
45    BinaryExpr, Case, ColumnarValue, Expr, ExprSchemable, Like, Operator, Volatility,
46    and, binary::BinaryTypeCoercer, lit, or, preimage::PreimageResult,
47};
48use datafusion_expr::{Cast, TryCast, simplify::ExprSimplifyResult};
49use datafusion_expr::{expr::ScalarFunction, interval_arithmetic::NullableInterval};
50use datafusion_expr::{
51    expr::{InList, InSubquery},
52    utils::{iter_conjunction, iter_conjunction_owned},
53};
54use datafusion_physical_expr::{create_physical_expr, execution_props::ExecutionProps};
55
56use super::inlist_simplifier::ShortenInListSimplifier;
57use super::utils::*;
58use crate::simplify_expressions::SimplifyContext;
59use crate::simplify_expressions::regex::simplify_regex_expr;
60use crate::simplify_expressions::unwrap_cast::{
61    is_cast_expr_and_support_unwrap_cast_in_comparison_for_binary,
62    is_cast_expr_and_support_unwrap_cast_in_comparison_for_inlist,
63    unwrap_cast_in_comparison_for_binary,
64};
65use crate::{
66    analyzer::type_coercion::TypeCoercionRewriter,
67    simplify_expressions::udf_preimage::rewrite_with_preimage,
68};
69use datafusion_expr::expr_rewriter::rewrite_with_guarantees_map;
70use datafusion_expr_common::casts::try_cast_literal_to_type;
71use indexmap::IndexSet;
72use regex::Regex;
73
74/// This structure handles API for expression simplification
75///
76/// Provides simplification information based on DFSchema and
77/// [`ExecutionProps`]. This is the default implementation used by DataFusion
78///
79/// For example:
80/// ```
81/// use arrow::datatypes::{DataType, Field, Schema};
82/// use datafusion_common::{DataFusionError, ToDFSchema};
83/// use datafusion_expr::simplify::SimplifyContext;
84/// use datafusion_expr::{col, lit};
85/// use datafusion_optimizer::simplify_expressions::ExprSimplifier;
86///
87/// // Create the schema
88/// let schema = Schema::new(vec![Field::new("i", DataType::Int64, false)])
89///     .to_dfschema_ref()
90///     .unwrap();
91///
92/// // Create the simplifier
93/// let context = SimplifyContext::builder().with_schema(schema).build();
94/// let simplifier = ExprSimplifier::new(context);
95///
96/// // Use the simplifier
97///
98/// // b < 2 or (1 > 3)
99/// let expr = col("b").lt(lit(2)).or(lit(1).gt(lit(3)));
100///
101/// // b < 2
102/// let simplified = simplifier.simplify(expr).unwrap();
103/// assert_eq!(simplified, col("b").lt(lit(2)));
104/// ```
105pub struct ExprSimplifier {
106    info: SimplifyContext,
107    /// Guarantees about the values of columns. This is provided by the user
108    /// in [ExprSimplifier::with_guarantees()].
109    guarantees: Vec<(Expr, NullableInterval)>,
110    /// Should expressions be canonicalized before simplification? Defaults to
111    /// true
112    canonicalize: bool,
113    /// Maximum number of simplifier cycles
114    max_simplifier_cycles: u32,
115}
116
117pub const THRESHOLD_INLINE_INLIST: usize = 3;
118pub const DEFAULT_MAX_SIMPLIFIER_CYCLES: u32 = 3;
119
120impl ExprSimplifier {
121    /// Create a new `ExprSimplifier` with the given [`SimplifyContext`].
122    /// See [`simplify`](Self::simplify) for an example.
123    ///
124    /// [`SimplifyContext`]: datafusion_expr::simplify::SimplifyContext
125    pub fn new(info: SimplifyContext) -> Self {
126        Self {
127            info,
128            guarantees: vec![],
129            canonicalize: true,
130            max_simplifier_cycles: DEFAULT_MAX_SIMPLIFIER_CYCLES,
131        }
132    }
133
134    /// Simplifies this [`Expr`] as much as possible, evaluating
135    /// constants and applying algebraic simplifications.
136    ///
137    /// The types of the expression must match what operators expect,
138    /// or else an error may occur trying to evaluate. See
139    /// [`coerce`](Self::coerce) for a function to help.
140    ///
141    /// # Example:
142    ///
143    /// `b > 2 AND b > 2`
144    ///
145    /// can be written to
146    ///
147    /// `b > 2`
148    ///
149    /// ```
150    /// use arrow::datatypes::{DataType, Field, Schema};
151    /// use datafusion_common::{DFSchema, ToDFSchema};
152    /// use datafusion_common::Result;
153    /// use datafusion_expr::simplify::SimplifyContext;
154    /// use datafusion_expr::{col, lit, Expr};
155    /// use datafusion_optimizer::simplify_expressions::ExprSimplifier;
156    /// use std::sync::Arc;
157    ///
158    /// // Create a schema and SimplifyContext
159    /// let schema = Schema::new(vec![Field::new("b", DataType::Int32, true)])
160    ///     .to_dfschema_ref()
161    ///     .unwrap();
162    /// // Create the simplifier
163    /// let context = SimplifyContext::builder().with_schema(schema).build();
164    /// let simplifier = ExprSimplifier::new(context);
165    ///
166    /// // b < 2
167    /// let b_lt_2 = col("b").gt(lit(2));
168    ///
169    /// // (b < 2) OR (b < 2)
170    /// let expr = b_lt_2.clone().or(b_lt_2.clone());
171    ///
172    /// // (b < 2) OR (b < 2) --> (b < 2)
173    /// let expr = simplifier.simplify(expr).unwrap();
174    /// assert_eq!(expr, b_lt_2);
175    /// ```
176    pub fn simplify(&self, expr: Expr) -> Result<Expr> {
177        Ok(self.simplify_with_cycle_count_transformed(expr)?.0.data)
178    }
179
180    /// Like [Self::simplify], simplifies this [`Expr`] as much as possible, evaluating
181    /// constants and applying algebraic simplifications. Additionally returns a `u32`
182    /// representing the number of simplification cycles performed, which can be useful for testing
183    /// optimizations.
184    ///
185    /// See [Self::simplify] for details and usage examples.
186    #[deprecated(
187        since = "48.0.0",
188        note = "Use `simplify_with_cycle_count_transformed` instead"
189    )]
190    #[expect(unused_mut)]
191    pub fn simplify_with_cycle_count(&self, mut expr: Expr) -> Result<(Expr, u32)> {
192        let (transformed, cycle_count) =
193            self.simplify_with_cycle_count_transformed(expr)?;
194        Ok((transformed.data, cycle_count))
195    }
196
197    /// Like [Self::simplify], simplifies this [`Expr`] as much as possible, evaluating
198    /// constants and applying algebraic simplifications. Additionally returns a `u32`
199    /// representing the number of simplification cycles performed, which can be useful for testing
200    /// optimizations.
201    ///
202    /// # Returns
203    ///
204    /// A tuple containing:
205    /// - The simplified expression wrapped in a `Transformed<Expr>` indicating if changes were made
206    /// - The number of simplification cycles that were performed
207    ///
208    /// See [Self::simplify] for details and usage examples.
209    pub fn simplify_with_cycle_count_transformed(
210        &self,
211        mut expr: Expr,
212    ) -> Result<(Transformed<Expr>, u32)> {
213        let mut simplifier = Simplifier::new(&self.info);
214        let config_options = Some(Arc::clone(self.info.config_options()));
215        let mut const_evaluator = ConstEvaluator::try_new(config_options)?;
216        let mut shorten_in_list_simplifier = ShortenInListSimplifier::new();
217        let guarantees_map: HashMap<&Expr, &NullableInterval> =
218            self.guarantees.iter().map(|(k, v)| (k, v)).collect();
219
220        if self.canonicalize {
221            expr = expr.rewrite(&mut Canonicalizer::new()).data()?
222        }
223
224        // Evaluating constants can enable new simplifications and
225        // simplifications can enable new constant evaluation
226        // see `Self::with_max_cycles`
227        let mut num_cycles = 0;
228        let mut has_transformed = false;
229        loop {
230            let Transformed {
231                data, transformed, ..
232            } = expr
233                .rewrite(&mut const_evaluator)?
234                .transform_data(|expr| expr.rewrite(&mut simplifier))?
235                .transform_data(|expr| {
236                    rewrite_with_guarantees_map(expr, &guarantees_map)
237                })?;
238            expr = data;
239            num_cycles += 1;
240            // Track if any transformation occurred
241            has_transformed = has_transformed || transformed;
242            if !transformed || num_cycles >= self.max_simplifier_cycles {
243                break;
244            }
245        }
246        // shorten inlist should be started after other inlist rules are applied
247        expr = expr.rewrite(&mut shorten_in_list_simplifier).data()?;
248        Ok((
249            Transformed::new_transformed(expr, has_transformed),
250            num_cycles,
251        ))
252    }
253
254    /// Apply type coercion to an [`Expr`] so that it can be
255    /// evaluated as a [`PhysicalExpr`](datafusion_physical_expr::PhysicalExpr).
256    ///
257    /// See the [type coercion module](datafusion_expr::type_coercion)
258    /// documentation for more details on type coercion
259    pub fn coerce(&self, expr: Expr, schema: &DFSchema) -> Result<Expr> {
260        let mut expr_rewrite = TypeCoercionRewriter { schema };
261        expr.rewrite(&mut expr_rewrite).data()
262    }
263
264    /// Input guarantees about the values of columns.
265    ///
266    /// The guarantees can simplify expressions. For example, if a column `x` is
267    /// guaranteed to be `3`, then the expression `x > 1` can be replaced by the
268    /// literal `true`.
269    ///
270    /// The guarantees are provided as a `Vec<(Expr, NullableInterval)>`,
271    /// where the [Expr] is a column reference and the [NullableInterval]
272    /// is an interval representing the known possible values of that column.
273    ///
274    /// ```rust
275    /// use arrow::datatypes::{DataType, Field, Schema};
276    /// use datafusion_common::{Result, ScalarValue, ToDFSchema};
277    /// use datafusion_expr::interval_arithmetic::{Interval, NullableInterval};
278    /// use datafusion_expr::simplify::SimplifyContext;
279    /// use datafusion_expr::{col, lit, Expr};
280    /// use datafusion_optimizer::simplify_expressions::ExprSimplifier;
281    ///
282    /// let schema = Schema::new(vec![
283    ///     Field::new("x", DataType::Int64, false),
284    ///     Field::new("y", DataType::UInt32, false),
285    ///     Field::new("z", DataType::Int64, false),
286    /// ])
287    /// .to_dfschema_ref()
288    /// .unwrap();
289    ///
290    /// // Create the simplifier
291    /// let context = SimplifyContext::builder().with_schema(schema).build();
292    ///
293    /// // Expression: (x >= 3) AND (y + 2 < 10) AND (z > 5)
294    /// let expr_x = col("x").gt_eq(lit(3_i64));
295    /// let expr_y = (col("y") + lit(2_u32)).lt(lit(10_u32));
296    /// let expr_z = col("z").gt(lit(5_i64));
297    /// let expr = expr_x.and(expr_y).and(expr_z.clone());
298    ///
299    /// let guarantees = vec![
300    ///     // x ∈ [3, 5]
301    ///     (
302    ///         col("x"),
303    ///         NullableInterval::NotNull {
304    ///             values: Interval::make(Some(3_i64), Some(5_i64)).unwrap(),
305    ///         },
306    ///     ),
307    ///     // y = 3
308    ///     (
309    ///         col("y"),
310    ///         NullableInterval::from(ScalarValue::UInt32(Some(3))),
311    ///     ),
312    /// ];
313    /// let simplifier = ExprSimplifier::new(context).with_guarantees(guarantees);
314    /// let output = simplifier.simplify(expr).unwrap();
315    /// // Expression becomes: true AND true AND (z > 5), which simplifies to
316    /// // z > 5.
317    /// assert_eq!(output, expr_z);
318    /// ```
319    pub fn with_guarantees(mut self, guarantees: Vec<(Expr, NullableInterval)>) -> Self {
320        self.guarantees = guarantees;
321        self
322    }
323
324    /// Should `Canonicalizer` be applied before simplification?
325    ///
326    /// If true (the default), the expression will be rewritten to canonical
327    /// form before simplification. This is useful to ensure that the simplifier
328    /// can apply all possible simplifications.
329    ///
330    /// Some expressions, such as those in some Joins, can not be canonicalized
331    /// without changing their meaning. In these cases, canonicalization should
332    /// be disabled.
333    ///
334    /// ```rust
335    /// use arrow::datatypes::{DataType, Field, Schema};
336    /// use datafusion_common::{Result, ScalarValue, ToDFSchema};
337    /// use datafusion_expr::interval_arithmetic::{Interval, NullableInterval};
338    /// use datafusion_expr::simplify::SimplifyContext;
339    /// use datafusion_expr::{col, lit, Expr};
340    /// use datafusion_optimizer::simplify_expressions::ExprSimplifier;
341    ///
342    /// let schema = Schema::new(vec![
343    ///     Field::new("a", DataType::Int64, false),
344    ///     Field::new("b", DataType::Int64, false),
345    ///     Field::new("c", DataType::Int64, false),
346    /// ])
347    /// .to_dfschema_ref()
348    /// .unwrap();
349    ///
350    /// // Create the simplifier
351    /// let context = SimplifyContext::builder().with_schema(schema).build();
352    /// let simplifier = ExprSimplifier::new(context);
353    ///
354    /// // Expression: a = c AND 1 = b
355    /// let expr = col("a").eq(col("c")).and(lit(1).eq(col("b")));
356    ///
357    /// // With canonicalization, the expression is rewritten to canonical form
358    /// // (though it is no simpler in this case):
359    /// let canonical = simplifier.simplify(expr.clone()).unwrap();
360    /// // Expression has been rewritten to: (c = a AND b = 1)
361    /// assert_eq!(canonical, col("c").eq(col("a")).and(col("b").eq(lit(1))));
362    ///
363    /// // If canonicalization is disabled, the expression is not changed
364    /// let non_canonicalized = simplifier
365    ///     .with_canonicalize(false)
366    ///     .simplify(expr.clone())
367    ///     .unwrap();
368    ///
369    /// assert_eq!(non_canonicalized, expr);
370    /// ```
371    pub fn with_canonicalize(mut self, canonicalize: bool) -> Self {
372        self.canonicalize = canonicalize;
373        self
374    }
375
376    /// Specifies the maximum number of simplification cycles to run.
377    ///
378    /// The simplifier can perform multiple passes of simplification. This is
379    /// because the output of one simplification step can allow more optimizations
380    /// in another simplification step. For example, constant evaluation can allow more
381    /// expression simplifications, and expression simplifications can allow more constant
382    /// evaluations.
383    ///
384    /// This method specifies the maximum number of allowed iteration cycles before the simplifier
385    /// returns an [Expr] output. However, it does not always perform the maximum number of cycles.
386    /// The simplifier will attempt to detect when an [Expr] is unchanged by all the simplification
387    /// passes, and return early. This avoids wasting time on unnecessary [Expr] tree traversals.
388    ///
389    /// If no maximum is specified, the value of [DEFAULT_MAX_SIMPLIFIER_CYCLES] is used
390    /// instead.
391    ///
392    /// ```rust
393    /// use arrow::datatypes::{DataType, Field, Schema};
394    /// use datafusion_expr::{col, lit, Expr};
395    /// use datafusion_common::{Result, ScalarValue, ToDFSchema};
396    /// use datafusion_expr::simplify::SimplifyContext;
397    /// use datafusion_optimizer::simplify_expressions::ExprSimplifier;
398    ///
399    /// let schema = Schema::new(vec![
400    ///   Field::new("a", DataType::Int64, false),
401    ///   ])
402    ///   .to_dfschema_ref().unwrap();
403    ///
404    /// // Create the simplifier
405    /// let context = SimplifyContext::builder().with_schema(schema).build();
406    /// let simplifier = ExprSimplifier::new(context);
407    ///
408    /// // Expression: a IS NOT NULL
409    /// let expr = col("a").is_not_null();
410    ///
411    /// // When using default maximum cycles, 2 cycles will be performed.
412    /// let (simplified_expr, count) = simplifier.simplify_with_cycle_count_transformed(expr.clone()).unwrap();
413    /// assert_eq!(simplified_expr.data, lit(true));
414    /// // 2 cycles were executed, but only 1 was needed
415    /// assert_eq!(count, 2);
416    ///
417    /// // Only 1 simplification pass is necessary here, so we can set the maximum cycles to 1.
418    /// let (simplified_expr, count) = simplifier.with_max_cycles(1).simplify_with_cycle_count_transformed(expr.clone()).unwrap();
419    /// // Expression has been rewritten to: (c = a AND b = 1)
420    /// assert_eq!(simplified_expr.data, lit(true));
421    /// // Only 1 cycle was executed
422    /// assert_eq!(count, 1);
423    /// ```
424    pub fn with_max_cycles(mut self, max_simplifier_cycles: u32) -> Self {
425        self.max_simplifier_cycles = max_simplifier_cycles;
426        self
427    }
428}
429
430/// Canonicalize any BinaryExprs that are not in canonical form
431///
432/// `<literal> <op> <col>` is rewritten to `<col> <op> <literal>`
433///
434/// `<col1> <op> <col2>` is rewritten so that the name of `col1` sorts higher
435/// than `col2` (`a > b` would be canonicalized to `b < a`)
436struct Canonicalizer {}
437
438impl Canonicalizer {
439    fn new() -> Self {
440        Self {}
441    }
442}
443
444impl TreeNodeRewriter for Canonicalizer {
445    type Node = Expr;
446
447    fn f_up(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
448        let Expr::BinaryExpr(BinaryExpr { left, op, right }) = expr else {
449            return Ok(Transformed::no(expr));
450        };
451        match (left.as_ref(), right.as_ref(), op.swap()) {
452            // <col1> <op> <col2>
453            (Expr::Column(left_col), Expr::Column(right_col), Some(swapped_op))
454                if right_col > left_col =>
455            {
456                Ok(Transformed::yes(Expr::BinaryExpr(BinaryExpr {
457                    left: right,
458                    op: swapped_op,
459                    right: left,
460                })))
461            }
462            // <literal> <op> <col>
463            (Expr::Literal(_a, _), Expr::Column(_b), Some(swapped_op)) => {
464                Ok(Transformed::yes(Expr::BinaryExpr(BinaryExpr {
465                    left: right,
466                    op: swapped_op,
467                    right: left,
468                })))
469            }
470            _ => Ok(Transformed::no(Expr::BinaryExpr(BinaryExpr {
471                left,
472                op,
473                right,
474            }))),
475        }
476    }
477}
478
479/// Partially evaluate `Expr`s so constant subtrees are evaluated at plan time.
480///
481/// Note it does not handle algebraic rewrites such as `(a or false)`
482/// --> `a`, which is handled by [`Simplifier`]
483struct ConstEvaluator {
484    /// `can_evaluate` is used during the depth-first-search of the
485    /// `Expr` tree to track if any siblings (or their descendants) were
486    /// non evaluatable (e.g. had a column reference or volatile
487    /// function)
488    ///
489    /// Specifically, `can_evaluate[N]` represents the state of
490    /// traversal when we are N levels deep in the tree, one entry for
491    /// this Expr and each of its parents.
492    ///
493    /// After visiting all siblings if `can_evaluate.top()` is true, that
494    /// means there were no non evaluatable siblings (or their
495    /// descendants) so this `Expr` can be evaluated
496    can_evaluate: Vec<bool>,
497    /// Execution properties needed to call [`create_physical_expr`].
498    /// `ConstEvaluator` only evaluates expressions without column references
499    /// (i.e. constant expressions) and doesn't use the variable binding features
500    /// of `ExecutionProps` (we explicitly filter out [`Expr::ScalarVariable`]).
501    /// The `config_options` are passed from the session to allow scalar functions
502    /// to access configuration like timezone.
503    execution_props: ExecutionProps,
504}
505
506/// The simplify result of ConstEvaluator
507enum ConstSimplifyResult {
508    // Expr was simplified and contains the new expression
509    Simplified(ScalarValue, Option<FieldMetadata>),
510    // Expr was not simplified and original value is returned
511    NotSimplified(ScalarValue, Option<FieldMetadata>),
512    // Evaluation encountered an error, contains the original expression
513    SimplifyRuntimeError(DataFusionError, Expr),
514}
515
516impl TreeNodeRewriter for ConstEvaluator {
517    type Node = Expr;
518
519    fn f_down(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
520        // Default to being able to evaluate this node
521        self.can_evaluate.push(true);
522
523        // if this expr is not ok to evaluate, mark entire parent
524        // stack as not ok (as all parents have at least one child or
525        // descendant that can not be evaluated
526
527        if !Self::can_evaluate(&expr) {
528            // walk back up stack, marking first parent that is not mutable
529            let parent_iter = self.can_evaluate.iter_mut().rev();
530            for p in parent_iter {
531                if !*p {
532                    // optimization: if we find an element on the
533                    // stack already marked, know all elements above are also marked
534                    break;
535                }
536                *p = false;
537            }
538        }
539
540        // NB: do not short circuit recursion even if we find a non
541        // evaluatable node (so we can fold other children, args to
542        // functions, etc.)
543        Ok(Transformed::no(expr))
544    }
545
546    fn f_up(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
547        match self.can_evaluate.pop() {
548            // Certain expressions such as `CASE` and `COALESCE` are short-circuiting
549            // and may not evaluate all their sub expressions. Thus, if
550            // any error is countered during simplification, return the original
551            // so that normal evaluation can occur
552            Some(true) => match self.evaluate_to_scalar(expr) {
553                ConstSimplifyResult::Simplified(s, m) => {
554                    Ok(Transformed::yes(Expr::Literal(s, m)))
555                }
556                ConstSimplifyResult::NotSimplified(s, m) => {
557                    Ok(Transformed::no(Expr::Literal(s, m)))
558                }
559                ConstSimplifyResult::SimplifyRuntimeError(err, expr) => {
560                    // For CAST expressions with literal inputs, propagate the error at plan time rather than deferring to execution time.
561                    // This provides clearer error messages and fails fast.
562                    if let Expr::Cast(Cast { ref expr, .. })
563                    | Expr::TryCast(TryCast { ref expr, .. }) = expr
564                        && matches!(expr.as_ref(), Expr::Literal(_, _))
565                    {
566                        return Err(err);
567                    }
568                    // For other expressions (like CASE, COALESCE), preserve the original
569                    // to allow short-circuit evaluation at execution time
570                    Ok(Transformed::yes(expr))
571                }
572            },
573            Some(false) => Ok(Transformed::no(expr)),
574            _ => internal_err!("Failed to pop can_evaluate"),
575        }
576    }
577}
578
579static DUMMY_SCHEMA: LazyLock<Arc<Schema>> =
580    LazyLock::new(|| Arc::new(Schema::new(vec![Field::new(".", DataType::Null, true)])));
581
582static DUMMY_DF_SCHEMA: LazyLock<DFSchema> =
583    LazyLock::new(|| DFSchema::try_from(Arc::clone(&*DUMMY_SCHEMA)).unwrap());
584
585static DUMMY_BATCH: LazyLock<RecordBatch> = LazyLock::new(|| {
586    // Need a single "input" row to produce a single output row
587    let col = new_null_array(&DataType::Null, 1);
588    RecordBatch::try_new(DUMMY_SCHEMA.clone(), vec![col]).unwrap()
589});
590
591impl ConstEvaluator {
592    /// Create a new `ConstantEvaluator`.
593    ///
594    /// Note: `ConstEvaluator` filters out expressions with scalar variables
595    /// (like `$var`) and volatile functions, so it creates its own default
596    /// `ExecutionProps` internally. The filtered expressions will be evaluated
597    /// at runtime where proper variable bindings are available.
598    ///
599    /// The `config_options` parameter is used to pass session configuration
600    /// (like timezone) to scalar functions during constant evaluation.
601    pub fn try_new(config_options: Option<Arc<ConfigOptions>>) -> Result<Self> {
602        // The dummy column name is unused and doesn't matter as only
603        // expressions without column references can be evaluated
604
605        let mut execution_props = ExecutionProps::new();
606        execution_props.config_options = config_options;
607
608        Ok(Self {
609            can_evaluate: vec![],
610            execution_props,
611        })
612    }
613
614    /// Can a function of the specified volatility be evaluated?
615    fn volatility_ok(volatility: Volatility) -> bool {
616        match volatility {
617            Volatility::Immutable => true,
618            // Values for functions such as now() are taken from ExecutionProps
619            Volatility::Stable => true,
620            Volatility::Volatile => false,
621        }
622    }
623
624    /// Can the expression be evaluated at plan time, (assuming all of
625    /// its children can also be evaluated)?
626    fn can_evaluate(expr: &Expr) -> bool {
627        // check for reasons we can't evaluate this node
628        //
629        // NOTE all expr types are listed here so when new ones are
630        // added they can be checked for their ability to be evaluated
631        // at plan time
632        match expr {
633            // TODO: remove the next line after `Expr::Wildcard` is removed
634            #[expect(deprecated)]
635            Expr::AggregateFunction { .. }
636            | Expr::ScalarVariable(_, _)
637            | Expr::Column(_)
638            | Expr::OuterReferenceColumn(_, _)
639            | Expr::Exists { .. }
640            | Expr::InSubquery(_)
641            | Expr::SetComparison(_)
642            | Expr::ScalarSubquery(_)
643            | Expr::WindowFunction { .. }
644            | Expr::GroupingSet(_)
645            | Expr::Wildcard { .. }
646            | Expr::Placeholder(_) => false,
647            Expr::ScalarFunction(ScalarFunction { func, .. }) => {
648                Self::volatility_ok(func.signature().volatility)
649            }
650            Expr::HigherOrderFunction(HigherOrderFunction { func, .. }) => {
651                Self::volatility_ok(func.signature().volatility)
652            }
653            Expr::Cast(Cast { expr, field }) | Expr::TryCast(TryCast { expr, field }) => {
654                if let (
655                    Ok(DataType::Struct(source_fields)),
656                    DataType::Struct(target_fields),
657                ) = (expr.get_type(&DFSchema::empty()), field.data_type())
658                {
659                    // Don't const-fold struct casts with different field counts
660                    if source_fields.len() != target_fields.len() {
661                        return false;
662                    }
663
664                    // Skip const-folding when there is no field name overlap
665                    if !has_one_of_more_common_fields(&source_fields, target_fields) {
666                        return false;
667                    }
668
669                    // Don't const-fold struct casts with empty (0-row) literals
670                    // The simplifier uses a 1-row input batch, which causes dimension mismatches
671                    // when evaluating 0-row struct literals
672                    if let Expr::Literal(ScalarValue::Struct(struct_array), _) =
673                        expr.as_ref()
674                        && struct_array.len() == 0
675                    {
676                        return false;
677                    }
678                }
679                true
680            }
681            Expr::Literal(_, _)
682            | Expr::Alias(..)
683            | Expr::Unnest(_)
684            | Expr::BinaryExpr { .. }
685            | Expr::Not(_)
686            | Expr::IsNotNull(_)
687            | Expr::IsNull(_)
688            | Expr::IsTrue(_)
689            | Expr::IsFalse(_)
690            | Expr::IsUnknown(_)
691            | Expr::IsNotTrue(_)
692            | Expr::IsNotFalse(_)
693            | Expr::IsNotUnknown(_)
694            | Expr::Negative(_)
695            | Expr::Between { .. }
696            | Expr::Like { .. }
697            | Expr::SimilarTo { .. }
698            | Expr::Case(_)
699            | Expr::InList { .. }
700            | Expr::Lambda(_)
701            | Expr::LambdaVariable(_) => true,
702        }
703    }
704
705    /// Internal helper to evaluates an Expr
706    pub(crate) fn evaluate_to_scalar(&mut self, expr: Expr) -> ConstSimplifyResult {
707        if let Expr::Literal(s, m) = expr {
708            return ConstSimplifyResult::NotSimplified(s, m);
709        }
710
711        let phys_expr = match create_physical_expr(
712            &expr,
713            &DUMMY_DF_SCHEMA,
714            &self.execution_props,
715            &PhysicalPlanningContext::default(),
716        ) {
717            Ok(e) => e,
718            Err(err) => return ConstSimplifyResult::SimplifyRuntimeError(err, expr),
719        };
720        let metadata = phys_expr
721            .return_field(DUMMY_BATCH.schema_ref())
722            .ok()
723            .and_then(|f| {
724                let m = f.metadata();
725                match m.is_empty() {
726                    true => None,
727                    false => Some(FieldMetadata::from(m)),
728                }
729            });
730        let col_val = match phys_expr.evaluate(&DUMMY_BATCH) {
731            Ok(v) => v,
732            Err(err) => return ConstSimplifyResult::SimplifyRuntimeError(err, expr),
733        };
734        match col_val {
735            ColumnarValue::Array(a) => {
736                if a.len() != 1 {
737                    ConstSimplifyResult::SimplifyRuntimeError(
738                        exec_datafusion_err!(
739                            "Could not evaluate the expression, found a result of length {}",
740                            a.len()
741                        ),
742                        expr,
743                    )
744                } else if as_list_array(&a).is_ok() {
745                    ConstSimplifyResult::Simplified(
746                        ScalarValue::List(a.as_list::<i32>().to_owned().into()),
747                        metadata,
748                    )
749                } else if as_large_list_array(&a).is_ok() {
750                    ConstSimplifyResult::Simplified(
751                        ScalarValue::LargeList(a.as_list::<i64>().to_owned().into()),
752                        metadata,
753                    )
754                } else {
755                    // Non-ListArray
756                    match ScalarValue::try_from_array(&a, 0) {
757                        Ok(s) => ConstSimplifyResult::Simplified(s, metadata),
758                        Err(err) => ConstSimplifyResult::SimplifyRuntimeError(err, expr),
759                    }
760                }
761            }
762            ColumnarValue::Scalar(s) => ConstSimplifyResult::Simplified(s, metadata),
763        }
764    }
765}
766
767/// Simplifies [`Expr`]s by applying algebraic transformation rules
768///
769/// Example transformations that are applied:
770/// * `expr = true` and `expr != false` to `expr` when `expr` is of boolean type
771/// * `expr = false` and `expr != true` to `!expr` when `expr` is of boolean type
772/// * `true = true` and `false = false` to `true`
773/// * `false = true` and `true = false` to `false`
774/// * `!!expr` to `expr`
775/// * `expr = null` and `expr != null` to `null`
776struct Simplifier<'a> {
777    info: &'a SimplifyContext,
778}
779
780impl<'a> Simplifier<'a> {
781    pub fn new(info: &'a SimplifyContext) -> Self {
782        Self { info }
783    }
784}
785
786impl TreeNodeRewriter for Simplifier<'_> {
787    type Node = Expr;
788
789    /// rewrite the expression simplifying any constant expressions
790    fn f_up(&mut self, expr: Expr) -> Result<Transformed<Expr>> {
791        use datafusion_expr::Operator::{
792            And, BitwiseAnd, BitwiseOr, BitwiseShiftLeft, BitwiseShiftRight, BitwiseXor,
793            Divide, Eq, Modulo, Multiply, NotEq, Or, RegexIMatch, RegexMatch,
794            RegexNotIMatch, RegexNotMatch,
795        };
796
797        let info = self.info;
798        Ok(match expr {
799            // `value op NULL` -> `NULL`
800            // `NULL op value` -> `NULL`
801            // except for few operators that can return non-null value even when one of the operands is NULL
802            ref expr @ Expr::BinaryExpr(BinaryExpr {
803                ref left,
804                ref op,
805                ref right,
806            }) if op.returns_null_on_null()
807                && (is_null(left.as_ref()) || is_null(right.as_ref())) =>
808            {
809                Transformed::yes(Expr::Literal(
810                    ScalarValue::try_new_null(&info.get_data_type(expr)?)?,
811                    None,
812                ))
813            }
814
815            // `NULL {AND, OR} NULL` -> `NULL`
816            Expr::BinaryExpr(BinaryExpr {
817                left,
818                op: And | Or,
819                right,
820            }) if is_null(&left) && is_null(&right) => Transformed::yes(lit_bool_null()),
821
822            //
823            // Rules for Eq
824            //
825
826            // true = A  --> A
827            // false = A --> !A
828            // null = A --> null
829            Expr::BinaryExpr(BinaryExpr {
830                left,
831                op: Eq,
832                right,
833            }) if is_bool_lit(&left) && info.is_boolean_type(&right)? => {
834                Transformed::yes(match as_bool_lit(&left)? {
835                    Some(true) => *right,
836                    Some(false) => Expr::Not(right),
837                    None => lit_bool_null(),
838                })
839            }
840            // A = true  --> A
841            // A = false --> !A
842            // A = null --> null
843            Expr::BinaryExpr(BinaryExpr {
844                left,
845                op: Eq,
846                right,
847            }) if is_bool_lit(&right) && info.is_boolean_type(&left)? => {
848                Transformed::yes(match as_bool_lit(&right)? {
849                    Some(true) => *left,
850                    Some(false) => Expr::Not(left),
851                    None => lit_bool_null(),
852                })
853            }
854            // According to SQL's null semantics, NULL = NULL evaluates to NULL
855            // Both sides are the same expression (A = A) and A is non-volatile expression
856            // A = A --> A IS NOT NULL OR NULL
857            // A = A --> true (if A not nullable)
858            Expr::BinaryExpr(BinaryExpr {
859                left,
860                op: Eq,
861                right,
862            }) if (left == right) & !left.is_volatile() => {
863                Transformed::yes(match !info.nullable(&left)? {
864                    true => lit(true),
865                    false => Expr::BinaryExpr(BinaryExpr {
866                        left: Box::new(Expr::IsNotNull(left)),
867                        op: Or,
868                        right: Box::new(lit_bool_null()),
869                    }),
870                })
871            }
872
873            // Rules for NotEq
874            //
875
876            // true != A  --> !A
877            // false != A --> A
878            // null != A --> null
879            Expr::BinaryExpr(BinaryExpr {
880                left,
881                op: NotEq,
882                right,
883            }) if is_bool_lit(&left) && info.is_boolean_type(&right)? => {
884                Transformed::yes(match as_bool_lit(&left)? {
885                    Some(true) => Expr::Not(right),
886                    Some(false) => *right,
887                    None => lit_bool_null(),
888                })
889            }
890            // A != true  --> !A
891            // A != false --> A
892            // A != null --> null,
893            Expr::BinaryExpr(BinaryExpr {
894                left,
895                op: NotEq,
896                right,
897            }) if is_bool_lit(&right) && info.is_boolean_type(&left)? => {
898                Transformed::yes(match as_bool_lit(&right)? {
899                    Some(true) => Expr::Not(left),
900                    Some(false) => *left,
901                    None => lit_bool_null(),
902                })
903            }
904
905            //
906            // Rules for OR
907            //
908
909            // true OR A --> true (even if A is null)
910            Expr::BinaryExpr(BinaryExpr {
911                left,
912                op: Or,
913                right: _,
914            }) if is_true(&left) => Transformed::yes(*left),
915            // false OR A --> A
916            Expr::BinaryExpr(BinaryExpr {
917                left,
918                op: Or,
919                right,
920            }) if is_false(&left) => Transformed::yes(*right),
921            // A OR true --> true (even if A is null)
922            Expr::BinaryExpr(BinaryExpr {
923                left: _,
924                op: Or,
925                right,
926            }) if is_true(&right) => Transformed::yes(*right),
927            // A OR false --> A
928            Expr::BinaryExpr(BinaryExpr {
929                left,
930                op: Or,
931                right,
932            }) if is_false(&right) => Transformed::yes(*left),
933            // A OR !A ---> true (if A not nullable)
934            Expr::BinaryExpr(BinaryExpr {
935                left,
936                op: Or,
937                right,
938            }) if is_not_of(&right, &left) && !info.nullable(&left)? => {
939                Transformed::yes(lit(true))
940            }
941            // !A OR A ---> true (if A not nullable)
942            Expr::BinaryExpr(BinaryExpr {
943                left,
944                op: Or,
945                right,
946            }) if is_not_of(&left, &right) && !info.nullable(&right)? => {
947                Transformed::yes(lit(true))
948            }
949            // (..A..) OR A --> (..A..)
950            Expr::BinaryExpr(BinaryExpr {
951                left,
952                op: Or,
953                right,
954            }) if expr_contains(&left, &right, Or) => Transformed::yes(*left),
955            // A OR (..A..) --> (..A..)
956            Expr::BinaryExpr(BinaryExpr {
957                left,
958                op: Or,
959                right,
960            }) if expr_contains(&right, &left, Or) => Transformed::yes(*right),
961            // A OR (A AND B) --> A
962            Expr::BinaryExpr(BinaryExpr {
963                left,
964                op: Or,
965                right,
966            }) if is_op_with(And, &right, &left) => Transformed::yes(*left),
967            // (A AND B) OR A --> A
968            Expr::BinaryExpr(BinaryExpr {
969                left,
970                op: Or,
971                right,
972            }) if is_op_with(And, &left, &right) => Transformed::yes(*right),
973            // Eliminate common factors in conjunctions e.g
974            // (A AND B) OR (A AND C) -> A AND (B OR C)
975            Expr::BinaryExpr(BinaryExpr {
976                left,
977                op: Or,
978                right,
979            }) if has_common_conjunction(&left, &right) => {
980                let lhs: IndexSet<Expr> = iter_conjunction_owned(*left).collect();
981                let (common, rhs): (Vec<_>, Vec<_>) = iter_conjunction_owned(*right)
982                    .partition(|e| lhs.contains(e) && !e.is_volatile());
983
984                let new_rhs = rhs.into_iter().reduce(and);
985                let new_lhs = lhs.into_iter().filter(|e| !common.contains(e)).reduce(and);
986                let common_conjunction = common.into_iter().reduce(and).unwrap();
987
988                let new_expr = match (new_lhs, new_rhs) {
989                    (Some(lhs), Some(rhs)) => and(common_conjunction, or(lhs, rhs)),
990                    (_, _) => common_conjunction,
991                };
992                Transformed::yes(new_expr)
993            }
994
995            //
996            // Rules for AND
997            //
998
999            // true AND A --> A
1000            Expr::BinaryExpr(BinaryExpr {
1001                left,
1002                op: And,
1003                right,
1004            }) if is_true(&left) => Transformed::yes(*right),
1005            // false AND A --> false (even if A is null)
1006            Expr::BinaryExpr(BinaryExpr {
1007                left,
1008                op: And,
1009                right: _,
1010            }) if is_false(&left) => Transformed::yes(*left),
1011            // A AND true --> A
1012            Expr::BinaryExpr(BinaryExpr {
1013                left,
1014                op: And,
1015                right,
1016            }) if is_true(&right) => Transformed::yes(*left),
1017            // A AND false --> false (even if A is null)
1018            Expr::BinaryExpr(BinaryExpr {
1019                left: _,
1020                op: And,
1021                right,
1022            }) if is_false(&right) => Transformed::yes(*right),
1023            // A AND !A ---> false (if A not nullable)
1024            Expr::BinaryExpr(BinaryExpr {
1025                left,
1026                op: And,
1027                right,
1028            }) if is_not_of(&right, &left) && !info.nullable(&left)? => {
1029                Transformed::yes(lit(false))
1030            }
1031            // !A AND A ---> false (if A not nullable)
1032            Expr::BinaryExpr(BinaryExpr {
1033                left,
1034                op: And,
1035                right,
1036            }) if is_not_of(&left, &right) && !info.nullable(&right)? => {
1037                Transformed::yes(lit(false))
1038            }
1039            // (..A..) AND A --> (..A..)
1040            Expr::BinaryExpr(BinaryExpr {
1041                left,
1042                op: And,
1043                right,
1044            }) if expr_contains(&left, &right, And) => Transformed::yes(*left),
1045            // A AND (..A..) --> (..A..)
1046            Expr::BinaryExpr(BinaryExpr {
1047                left,
1048                op: And,
1049                right,
1050            }) if expr_contains(&right, &left, And) => Transformed::yes(*right),
1051            // A AND (A OR B) --> A
1052            Expr::BinaryExpr(BinaryExpr {
1053                left,
1054                op: And,
1055                right,
1056            }) if is_op_with(Or, &right, &left) => Transformed::yes(*left),
1057            // (A OR B) AND A --> A
1058            Expr::BinaryExpr(BinaryExpr {
1059                left,
1060                op: And,
1061                right,
1062            }) if is_op_with(Or, &left, &right) => Transformed::yes(*right),
1063            // A >= constant AND constant <= A --> A = constant
1064            Expr::BinaryExpr(BinaryExpr {
1065                left,
1066                op: And,
1067                right,
1068            }) if can_reduce_to_equal_statement(&left, &right) => {
1069                if let Expr::BinaryExpr(BinaryExpr {
1070                    left: left_left,
1071                    right: left_right,
1072                    ..
1073                }) = *left
1074                {
1075                    Transformed::yes(Expr::BinaryExpr(BinaryExpr {
1076                        left: left_left,
1077                        op: Eq,
1078                        right: left_right,
1079                    }))
1080                } else {
1081                    return internal_err!(
1082                        "can_reduce_to_equal_statement should only be called with a BinaryExpr"
1083                    );
1084                }
1085            }
1086            // A = L1 AND A != L2 --> A = L1 (when L1 != L2)
1087            Expr::BinaryExpr(BinaryExpr {
1088                left,
1089                op: And,
1090                right,
1091            }) if is_eq_and_ne_with_different_literal(&left, &right) => {
1092                Transformed::yes(*left)
1093            }
1094            // A != L2 AND A = L1 --> A = L1 (when L1 != L2)
1095            Expr::BinaryExpr(BinaryExpr {
1096                left,
1097                op: And,
1098                right,
1099            }) if is_eq_and_ne_with_different_literal(&right, &left) => {
1100                Transformed::yes(*right)
1101            }
1102
1103            //
1104            // Rules for Multiply
1105            //
1106
1107            // A * 1 --> A (with type coercion if needed)
1108            Expr::BinaryExpr(BinaryExpr {
1109                left,
1110                op: Multiply,
1111                right,
1112            }) if is_one(&right) => {
1113                simplify_right_is_one_case(info, left, &Multiply, &right)?
1114            }
1115            // 1 * A --> A
1116            Expr::BinaryExpr(BinaryExpr {
1117                left,
1118                op: Multiply,
1119                right,
1120            }) if is_one(&left) => {
1121                // 1 * A is equivalent to A * 1
1122                simplify_right_is_one_case(info, right, &Multiply, &left)?
1123            }
1124
1125            // A * 0 --> 0 (if A is not null and not floating, since NAN * 0 -> NAN)
1126            Expr::BinaryExpr(BinaryExpr {
1127                left,
1128                op: Multiply,
1129                right,
1130            }) if !info.nullable(&left)?
1131                && !info.get_data_type(&left)?.is_floating()
1132                && is_zero(&right) =>
1133            {
1134                Transformed::yes(*right)
1135            }
1136            // 0 * A --> 0 (if A is not null and not floating, since 0 * NAN -> NAN)
1137            Expr::BinaryExpr(BinaryExpr {
1138                left,
1139                op: Multiply,
1140                right,
1141            }) if !info.nullable(&right)?
1142                && !info.get_data_type(&right)?.is_floating()
1143                && is_zero(&left) =>
1144            {
1145                Transformed::yes(*left)
1146            }
1147
1148            //
1149            // Rules for Divide
1150            //
1151
1152            // A / 1 --> A
1153            Expr::BinaryExpr(BinaryExpr {
1154                left,
1155                op: Divide,
1156                right,
1157            }) if is_one(&right) => {
1158                simplify_right_is_one_case(info, left, &Divide, &right)?
1159            }
1160
1161            //
1162            // Rules for Modulo
1163            //
1164
1165            // A % 1 --> 0 (if A is not nullable and not floating, since NAN % 1 --> NAN)
1166            Expr::BinaryExpr(BinaryExpr {
1167                left,
1168                op: Modulo,
1169                right,
1170            }) if !info.nullable(&left)?
1171                && !info.get_data_type(&left)?.is_floating()
1172                && is_one(&right) =>
1173            {
1174                Transformed::yes(Expr::Literal(
1175                    ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1176                    None,
1177                ))
1178            }
1179
1180            //
1181            // Rules for BitwiseAnd
1182            //
1183
1184            // A & 0 -> 0 (if A not nullable)
1185            Expr::BinaryExpr(BinaryExpr {
1186                left,
1187                op: BitwiseAnd,
1188                right,
1189            }) if !info.nullable(&left)? && is_zero(&right) => Transformed::yes(*right),
1190
1191            // 0 & A -> 0 (if A not nullable)
1192            Expr::BinaryExpr(BinaryExpr {
1193                left,
1194                op: BitwiseAnd,
1195                right,
1196            }) if !info.nullable(&right)? && is_zero(&left) => Transformed::yes(*left),
1197
1198            // !A & A -> 0 (if A not nullable)
1199            Expr::BinaryExpr(BinaryExpr {
1200                left,
1201                op: BitwiseAnd,
1202                right,
1203            }) if is_negative_of(&left, &right) && !info.nullable(&right)? => {
1204                Transformed::yes(Expr::Literal(
1205                    ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1206                    None,
1207                ))
1208            }
1209
1210            // A & !A -> 0 (if A not nullable)
1211            Expr::BinaryExpr(BinaryExpr {
1212                left,
1213                op: BitwiseAnd,
1214                right,
1215            }) if is_negative_of(&right, &left) && !info.nullable(&left)? => {
1216                Transformed::yes(Expr::Literal(
1217                    ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1218                    None,
1219                ))
1220            }
1221
1222            // (..A..) & A --> (..A..)
1223            Expr::BinaryExpr(BinaryExpr {
1224                left,
1225                op: BitwiseAnd,
1226                right,
1227            }) if expr_contains(&left, &right, BitwiseAnd) => Transformed::yes(*left),
1228
1229            // A & (..A..) --> (..A..)
1230            Expr::BinaryExpr(BinaryExpr {
1231                left,
1232                op: BitwiseAnd,
1233                right,
1234            }) if expr_contains(&right, &left, BitwiseAnd) => Transformed::yes(*right),
1235
1236            // A & (A | B) --> A (if B not null)
1237            Expr::BinaryExpr(BinaryExpr {
1238                left,
1239                op: BitwiseAnd,
1240                right,
1241            }) if !info.nullable(&right)? && is_op_with(BitwiseOr, &right, &left) => {
1242                Transformed::yes(*left)
1243            }
1244
1245            // (A | B) & A --> A (if B not null)
1246            Expr::BinaryExpr(BinaryExpr {
1247                left,
1248                op: BitwiseAnd,
1249                right,
1250            }) if !info.nullable(&left)? && is_op_with(BitwiseOr, &left, &right) => {
1251                Transformed::yes(*right)
1252            }
1253
1254            //
1255            // Rules for BitwiseOr
1256            //
1257
1258            // A | 0 -> A (even if A is null)
1259            Expr::BinaryExpr(BinaryExpr {
1260                left,
1261                op: BitwiseOr,
1262                right,
1263            }) if is_zero(&right) => Transformed::yes(*left),
1264
1265            // 0 | A -> A (even if A is null)
1266            Expr::BinaryExpr(BinaryExpr {
1267                left,
1268                op: BitwiseOr,
1269                right,
1270            }) if is_zero(&left) => Transformed::yes(*right),
1271
1272            // !A | A -> -1 (if A not nullable)
1273            Expr::BinaryExpr(BinaryExpr {
1274                left,
1275                op: BitwiseOr,
1276                right,
1277            }) if is_negative_of(&left, &right) && !info.nullable(&right)? => {
1278                Transformed::yes(Expr::Literal(
1279                    ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1280                    None,
1281                ))
1282            }
1283
1284            // A | !A -> -1 (if A not nullable)
1285            Expr::BinaryExpr(BinaryExpr {
1286                left,
1287                op: BitwiseOr,
1288                right,
1289            }) if is_negative_of(&right, &left) && !info.nullable(&left)? => {
1290                Transformed::yes(Expr::Literal(
1291                    ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1292                    None,
1293                ))
1294            }
1295
1296            // (..A..) | A --> (..A..)
1297            Expr::BinaryExpr(BinaryExpr {
1298                left,
1299                op: BitwiseOr,
1300                right,
1301            }) if expr_contains(&left, &right, BitwiseOr) => Transformed::yes(*left),
1302
1303            // A | (..A..) --> (..A..)
1304            Expr::BinaryExpr(BinaryExpr {
1305                left,
1306                op: BitwiseOr,
1307                right,
1308            }) if expr_contains(&right, &left, BitwiseOr) => Transformed::yes(*right),
1309
1310            // A | (A & B) --> A (if B not null)
1311            Expr::BinaryExpr(BinaryExpr {
1312                left,
1313                op: BitwiseOr,
1314                right,
1315            }) if !info.nullable(&right)? && is_op_with(BitwiseAnd, &right, &left) => {
1316                Transformed::yes(*left)
1317            }
1318
1319            // (A & B) | A --> A (if B not null)
1320            Expr::BinaryExpr(BinaryExpr {
1321                left,
1322                op: BitwiseOr,
1323                right,
1324            }) if !info.nullable(&left)? && is_op_with(BitwiseAnd, &left, &right) => {
1325                Transformed::yes(*right)
1326            }
1327
1328            //
1329            // Rules for BitwiseXor
1330            //
1331
1332            // A ^ 0 -> A (if A not nullable)
1333            Expr::BinaryExpr(BinaryExpr {
1334                left,
1335                op: BitwiseXor,
1336                right,
1337            }) if !info.nullable(&left)? && is_zero(&right) => Transformed::yes(*left),
1338
1339            // 0 ^ A -> A (if A not nullable)
1340            Expr::BinaryExpr(BinaryExpr {
1341                left,
1342                op: BitwiseXor,
1343                right,
1344            }) if !info.nullable(&right)? && is_zero(&left) => Transformed::yes(*right),
1345
1346            // !A ^ A -> -1 (if A not nullable)
1347            Expr::BinaryExpr(BinaryExpr {
1348                left,
1349                op: BitwiseXor,
1350                right,
1351            }) if is_negative_of(&left, &right) && !info.nullable(&right)? => {
1352                Transformed::yes(Expr::Literal(
1353                    ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1354                    None,
1355                ))
1356            }
1357
1358            // A ^ !A -> -1 (if A not nullable)
1359            Expr::BinaryExpr(BinaryExpr {
1360                left,
1361                op: BitwiseXor,
1362                right,
1363            }) if is_negative_of(&right, &left) && !info.nullable(&left)? => {
1364                Transformed::yes(Expr::Literal(
1365                    ScalarValue::new_negative_one(&info.get_data_type(&left)?)?,
1366                    None,
1367                ))
1368            }
1369
1370            // (..A..) ^ A --> (the expression without A, if number of A is odd, otherwise one A)
1371            Expr::BinaryExpr(BinaryExpr {
1372                left,
1373                op: BitwiseXor,
1374                right,
1375            }) if expr_contains(&left, &right, BitwiseXor) => {
1376                let expr = delete_xor_in_complex_expr(&left, &right, false);
1377                Transformed::yes(if expr == *right {
1378                    Expr::Literal(
1379                        ScalarValue::new_zero(&info.get_data_type(&right)?)?,
1380                        None,
1381                    )
1382                } else {
1383                    expr
1384                })
1385            }
1386
1387            // A ^ (..A..) --> (the expression without A, if number of A is odd, otherwise one A)
1388            Expr::BinaryExpr(BinaryExpr {
1389                left,
1390                op: BitwiseXor,
1391                right,
1392            }) if expr_contains(&right, &left, BitwiseXor) => {
1393                let expr = delete_xor_in_complex_expr(&right, &left, true);
1394                Transformed::yes(if expr == *left {
1395                    Expr::Literal(
1396                        ScalarValue::new_zero(&info.get_data_type(&left)?)?,
1397                        None,
1398                    )
1399                } else {
1400                    expr
1401                })
1402            }
1403
1404            //
1405            // Rules for BitwiseShiftRight
1406            //
1407
1408            // A >> 0 -> A (even if A is null)
1409            Expr::BinaryExpr(BinaryExpr {
1410                left,
1411                op: BitwiseShiftRight,
1412                right,
1413            }) if is_zero(&right) => Transformed::yes(*left),
1414
1415            //
1416            // Rules for BitwiseShiftRight
1417            //
1418
1419            // A << 0 -> A (even if A is null)
1420            Expr::BinaryExpr(BinaryExpr {
1421                left,
1422                op: BitwiseShiftLeft,
1423                right,
1424            }) if is_zero(&right) => Transformed::yes(*left),
1425
1426            //
1427            // Rules for Not
1428            //
1429            Expr::Not(inner) => Transformed::yes(negate_clause(*inner)),
1430
1431            //
1432            // Rules for Negative
1433            //
1434            Expr::Negative(inner) => Transformed::yes(distribute_negation(*inner)),
1435
1436            //
1437            // Rules for Case
1438            //
1439
1440            // Inline a comparison to a literal with the case statement into the `THEN` clauses.
1441            // which can enable further simplifications
1442            // CASE WHEN X THEN "a" WHEN Y THEN "b" ... END = "a" --> CASE WHEN X THEN "a" = "a" WHEN Y THEN "b" = "a" END
1443            Expr::BinaryExpr(BinaryExpr {
1444                left,
1445                op: op @ (Eq | NotEq),
1446                right,
1447            }) if is_case_with_literal_outputs(&left) && is_lit(&right) => {
1448                let case = into_case(*left)?;
1449                Transformed::yes(Expr::Case(Case {
1450                    expr: None,
1451                    when_then_expr: case
1452                        .when_then_expr
1453                        .into_iter()
1454                        .map(|(when, then)| {
1455                            (
1456                                when,
1457                                Box::new(Expr::BinaryExpr(BinaryExpr {
1458                                    left: then,
1459                                    op,
1460                                    right: right.clone(),
1461                                })),
1462                            )
1463                        })
1464                        .collect(),
1465                    else_expr: case.else_expr.map(|els| {
1466                        Box::new(Expr::BinaryExpr(BinaryExpr {
1467                            left: els,
1468                            op,
1469                            right,
1470                        }))
1471                    }),
1472                }))
1473            }
1474
1475            // CASE WHEN true THEN A ... END --> A
1476            // CASE WHEN X THEN A WHEN TRUE THEN B ... END --> CASE WHEN X THEN A ELSE B END
1477            // CASE WHEN false THEN A END --> NULL
1478            // CASE WHEN false THEN A ELSE B END --> B
1479            // CASE WHEN X THEN A WHEN false THEN B END --> CASE WHEN X THEN A ELSE B END
1480            Expr::Case(Case {
1481                expr: None,
1482                when_then_expr,
1483                mut else_expr,
1484            }) if when_then_expr
1485                .iter()
1486                .any(|(when, _)| is_true(when.as_ref()) || is_false(when.as_ref())) =>
1487            {
1488                let out_type = info.get_data_type(&when_then_expr[0].1)?;
1489                let mut new_when_then_expr = Vec::with_capacity(when_then_expr.len());
1490
1491                for (when, then) in when_then_expr.into_iter() {
1492                    if is_true(when.as_ref()) {
1493                        // Skip adding the rest of the when-then expressions after WHEN true
1494                        // CASE WHEN X THEN A WHEN TRUE THEN B ... END --> CASE WHEN X THEN A ELSE B END
1495                        else_expr = Some(then);
1496                        break;
1497                    } else if !is_false(when.as_ref()) {
1498                        new_when_then_expr.push((when, then));
1499                    }
1500                    // else: skip WHEN false cases
1501                }
1502
1503                // Exclude CASE statement altogether if there are no when-then expressions left
1504                if new_when_then_expr.is_empty() {
1505                    // CASE WHEN false THEN A ELSE B END --> B
1506                    if let Some(else_expr) = else_expr {
1507                        return Ok(Transformed::yes(*else_expr));
1508                    // CASE WHEN false THEN A END --> NULL
1509                    } else {
1510                        let null =
1511                            Expr::Literal(ScalarValue::try_new_null(&out_type)?, None);
1512                        return Ok(Transformed::yes(null));
1513                    }
1514                }
1515
1516                Transformed::yes(Expr::Case(Case {
1517                    expr: None,
1518                    when_then_expr: new_when_then_expr,
1519                    else_expr,
1520                }))
1521            }
1522
1523            // CASE
1524            //   WHEN X THEN A
1525            //   WHEN Y THEN B
1526            //   ...
1527            //   ELSE Q
1528            // END
1529            //
1530            // ---> (X AND A) OR (Y AND B AND NOT X) OR ... (NOT (X OR Y) AND Q)
1531            //
1532            // Note: the rationale for this rewrite is that the expr can then be further
1533            // simplified using the existing rules for AND/OR
1534            Expr::Case(Case {
1535                expr: None,
1536                when_then_expr,
1537                else_expr,
1538            }) if !when_then_expr.is_empty()
1539                // The rewrite is O(n²) in general so limit to small number of when-thens that can be true
1540                && (when_then_expr.len() < 3 // small number of input whens
1541                    // or all thens are literal bools and a small number of them are true
1542                    || (when_then_expr.iter().all(|(_, then)| is_bool_lit(then))
1543                        && when_then_expr.iter().filter(|(_, then)| is_true(then)).count() < 3))
1544                && info.is_boolean_type(&when_then_expr[0].1)? =>
1545            {
1546                // String disjunction of all the when predicates encountered so far. Not nullable.
1547                let mut filter_expr = lit(false);
1548                // The disjunction of all the cases
1549                let mut out_expr = lit(false);
1550
1551                for (when, then) in when_then_expr {
1552                    let when = is_exactly_true(*when, info)?;
1553                    let case_expr =
1554                        when.clone().and(filter_expr.clone().not()).and(*then);
1555
1556                    out_expr = out_expr.or(case_expr);
1557                    filter_expr = filter_expr.or(when);
1558                }
1559
1560                let else_expr = else_expr.map(|b| *b).unwrap_or_else(lit_bool_null);
1561                let case_expr = filter_expr.not().and(else_expr);
1562                out_expr = out_expr.or(case_expr);
1563
1564                // Do a first pass at simplification
1565                out_expr.rewrite(self)?
1566            }
1567            // CASE
1568            //   WHEN X THEN true
1569            //   WHEN Y THEN true
1570            //   WHEN Z THEN false
1571            //   ...
1572            //   ELSE true
1573            // END
1574            //
1575            // --->
1576            //
1577            // NOT(CASE
1578            //   WHEN X THEN false
1579            //   WHEN Y THEN false
1580            //   WHEN Z THEN true
1581            //   ...
1582            //   ELSE false
1583            // END)
1584            //
1585            // Note: the rationale for this rewrite is that the case can then be further
1586            // simplified into a small number of ANDs and ORs
1587            Expr::Case(Case {
1588                expr: None,
1589                when_then_expr,
1590                else_expr,
1591            }) if !when_then_expr.is_empty()
1592                && when_then_expr
1593                    .iter()
1594                    .all(|(_, then)| is_bool_lit(then)) // all thens are literal bools
1595                // This simplification is only helpful if we end up with a small number of true thens
1596                && when_then_expr
1597                    .iter()
1598                    .filter(|(_, then)| is_false(then))
1599                    .count()
1600                    < 3
1601                && else_expr.as_deref().is_none_or(is_bool_lit) =>
1602            {
1603                Transformed::yes(
1604                    Expr::Case(Case {
1605                        expr: None,
1606                        when_then_expr: when_then_expr
1607                            .into_iter()
1608                            .map(|(when, then)| (when, Box::new(Expr::Not(then))))
1609                            .collect(),
1610                        else_expr: else_expr
1611                            .map(|else_expr| Box::new(Expr::Not(else_expr))),
1612                    })
1613                    .not(),
1614                )
1615            }
1616            Expr::ScalarFunction(ScalarFunction { func: udf, args }) => {
1617                match udf.simplify(args, info)? {
1618                    ExprSimplifyResult::Original(args) => {
1619                        Transformed::no(Expr::ScalarFunction(ScalarFunction {
1620                            func: udf,
1621                            args,
1622                        }))
1623                    }
1624                    ExprSimplifyResult::Simplified(expr) => Transformed::yes(expr),
1625                }
1626            }
1627
1628            Expr::AggregateFunction(datafusion_expr::expr::AggregateFunction {
1629                ref func,
1630                ..
1631            }) => match (func.simplify(), expr) {
1632                (Some(simplify_function), Expr::AggregateFunction(af)) => {
1633                    Transformed::yes(simplify_function(af, info)?)
1634                }
1635                (_, expr) => Transformed::no(expr),
1636            },
1637
1638            Expr::WindowFunction(ref window_fun) => match (window_fun.simplify(), expr) {
1639                (Some(simplify_function), Expr::WindowFunction(wf)) => {
1640                    Transformed::yes(simplify_function(*wf, info)?)
1641                }
1642                (_, expr) => Transformed::no(expr),
1643            },
1644
1645            //
1646            // Rules for Between
1647            //
1648
1649            // a between 3 and 5  -->  a >= 3 AND a <=5
1650            // a not between 3 and 5  -->  a < 3 OR a > 5
1651            Expr::Between(between) => Transformed::yes(if between.negated {
1652                let l = *between.expr.clone();
1653                let r = *between.expr;
1654                or(l.lt(*between.low), r.gt(*between.high))
1655            } else {
1656                and(
1657                    between.expr.clone().gt_eq(*between.low),
1658                    between.expr.lt_eq(*between.high),
1659                )
1660            }),
1661
1662            //
1663            // Rules for regexes
1664            //
1665            Expr::BinaryExpr(BinaryExpr {
1666                left,
1667                op: op @ (RegexMatch | RegexNotMatch | RegexIMatch | RegexNotIMatch),
1668                right,
1669            }) => simplify_regex_expr(left, op, right)?,
1670
1671            // Rules for Like
1672            Expr::Like(like) => {
1673                // `\` is implicit escape, see https://github.com/apache/datafusion/issues/13291
1674                let escape_char = like.escape_char.unwrap_or('\\');
1675
1676                match StringScalar::try_from_expr(&like.pattern) {
1677                    Some(string_scalar) => {
1678                        let pattern_str = string_scalar.as_str();
1679                        match pattern_str {
1680                            None => return Ok(Transformed::yes(lit_bool_null())),
1681                            Some("%") => {
1682                                // exp LIKE '%' is
1683                                //   - when exp is not NULL, it's true
1684                                //   - when exp is NULL, it's NULL
1685                                // exp NOT LIKE '%' is
1686                                //   - when exp is not NULL, it's false
1687                                //   - when exp is NULL, it's NULL
1688                                let result_for_non_null = lit(!like.negated);
1689                                Transformed::yes(if !info.nullable(&like.expr)? {
1690                                    result_for_non_null
1691                                } else {
1692                                    Expr::Case(Case {
1693                                        expr: Some(Box::new(Expr::IsNotNull(like.expr))),
1694                                        when_then_expr: vec![(
1695                                            Box::new(lit(true)),
1696                                            Box::new(result_for_non_null),
1697                                        )],
1698                                        else_expr: None,
1699                                    })
1700                                })
1701                            }
1702                            Some(pattern_str)
1703                                if pattern_str.contains("%%")
1704                                    && !pattern_str.contains(escape_char) =>
1705                            {
1706                                // Repeated occurrences of wildcard are redundant so remove them
1707                                // exp LIKE '%%'  --> exp LIKE '%'
1708
1709                                static LIKE_REGEX: LazyLock<Regex> =
1710                                    LazyLock::new(|| Regex::new("%%+").unwrap());
1711                                let simplified_pattern =
1712                                    LIKE_REGEX.replace_all(pattern_str, "%").to_string();
1713                                Transformed::yes(Expr::Like(Like {
1714                                    pattern: Box::new(
1715                                        string_scalar.to_expr(&simplified_pattern),
1716                                    ),
1717                                    ..like
1718                                }))
1719                            }
1720                            Some(pattern_str)
1721                                if !like.case_insensitive
1722                                    && !pattern_str
1723                                        .contains(['%', '_', escape_char].as_ref()) =>
1724                            {
1725                                // If the pattern does not contain any wildcards, we can simplify the like expression to an equality expression
1726                                // TODO: handle escape characters
1727                                Transformed::yes(Expr::BinaryExpr(BinaryExpr {
1728                                    left: like.expr.clone(),
1729                                    op: if like.negated { NotEq } else { Eq },
1730                                    right: like.pattern.clone(),
1731                                }))
1732                            }
1733
1734                            Some(_pattern_str) => Transformed::no(Expr::Like(like)),
1735                        }
1736                    }
1737                    None => Transformed::no(Expr::Like(like)),
1738                }
1739            }
1740
1741            // a is not null/unknown --> true (if a is not nullable)
1742            Expr::IsNotNull(expr) | Expr::IsNotUnknown(expr)
1743                if !info.nullable(&expr)? =>
1744            {
1745                Transformed::yes(lit(true))
1746            }
1747
1748            // a is null/unknown --> false (if a is not nullable)
1749            Expr::IsNull(expr) | Expr::IsUnknown(expr) if !info.nullable(&expr)? => {
1750                Transformed::yes(lit(false))
1751            }
1752
1753            // expr IN () --> false
1754            // expr NOT IN () --> true
1755            Expr::InList(InList {
1756                expr: _,
1757                list,
1758                negated,
1759            }) if list.is_empty() => Transformed::yes(lit(negated)),
1760
1761            // null in (x, y, z) --> null
1762            // null not in (x, y, z) --> null
1763            Expr::InList(InList {
1764                expr,
1765                list,
1766                negated: _,
1767            }) if is_null(expr.as_ref()) && !list.is_empty() => {
1768                Transformed::yes(lit_bool_null())
1769            }
1770
1771            // expr IN ((subquery)) -> expr IN (subquery), see ##5529
1772            Expr::InList(InList {
1773                expr,
1774                mut list,
1775                negated,
1776            }) if list.len() == 1
1777                && matches!(list.first(), Some(Expr::ScalarSubquery { .. })) =>
1778            {
1779                let Expr::ScalarSubquery(subquery) = list.remove(0) else {
1780                    unreachable!()
1781                };
1782
1783                Transformed::yes(Expr::InSubquery(InSubquery::new(
1784                    expr, subquery, negated,
1785                )))
1786            }
1787
1788            // Combine multiple OR expressions into a single IN list expression if possible
1789            //
1790            // i.e. `a = 1 OR a = 2 OR a = 3` -> `a IN (1, 2, 3)`
1791            Expr::BinaryExpr(BinaryExpr {
1792                left,
1793                op: Or,
1794                right,
1795            }) if are_inlist_and_eq(left.as_ref(), right.as_ref()) => {
1796                let lhs = to_inlist(*left).unwrap();
1797                let rhs = to_inlist(*right).unwrap();
1798                #[allow(clippy::allow_attributes, clippy::mutable_key_type)]
1799                // Expr contains Arc with interior mutability but is intentionally used as hash key
1800                let mut seen: HashSet<Expr> = HashSet::new();
1801                let list = lhs
1802                    .list
1803                    .into_iter()
1804                    .chain(rhs.list)
1805                    .filter(|e| seen.insert(e.to_owned()))
1806                    .collect::<Vec<_>>();
1807
1808                let merged_inlist = InList {
1809                    expr: lhs.expr,
1810                    list,
1811                    negated: false,
1812                };
1813
1814                Transformed::yes(Expr::InList(merged_inlist))
1815            }
1816
1817            // Simplify expressions that is guaranteed to be true or false to a literal boolean expression
1818            //
1819            // Rules:
1820            // If both expressions are `IN` or `NOT IN`, then we can apply intersection or union on both lists
1821            //   Intersection:
1822            //     1. `a in (1,2,3) AND a in (4,5) -> a in (), which is false`
1823            //     2. `a in (1,2,3) AND a in (2,3,4) -> a in (2,3)`
1824            //     3. `a not in (1,2,3) OR a not in (3,4,5,6) -> a not in (3)`
1825            //   Union:
1826            //     4. `a not int (1,2,3) AND a not in (4,5,6) -> a not in (1,2,3,4,5,6)`
1827            //     # This rule is handled by `or_in_list_simplifier.rs`
1828            //     5. `a in (1,2,3) OR a in (4,5,6) -> a in (1,2,3,4,5,6)`
1829            // If one of the expressions is `IN` and another one is `NOT IN`, then we apply exception on `In` expression
1830            //     6. `a in (1,2,3,4) AND a not in (1,2,3,4,5) -> a in (), which is false`
1831            //     7. `a not in (1,2,3,4) AND a in (1,2,3,4,5) -> a = 5`
1832            //     8. `a in (1,2,3,4) AND a not in (5,6,7,8) -> a in (1,2,3,4)`
1833            Expr::BinaryExpr(BinaryExpr {
1834                left,
1835                op: And,
1836                right,
1837            }) if are_inlist_and_eq_and_match_neg(
1838                left.as_ref(),
1839                right.as_ref(),
1840                false,
1841                false,
1842            ) =>
1843            {
1844                match (*left, *right) {
1845                    (Expr::InList(l1), Expr::InList(l2)) => {
1846                        return inlist_intersection(l1, &l2, false).map(Transformed::yes);
1847                    }
1848                    // Matched previously once
1849                    _ => unreachable!(),
1850                }
1851            }
1852
1853            Expr::BinaryExpr(BinaryExpr {
1854                left,
1855                op: And,
1856                right,
1857            }) if are_inlist_and_eq_and_match_neg(
1858                left.as_ref(),
1859                right.as_ref(),
1860                true,
1861                true,
1862            ) =>
1863            {
1864                match (*left, *right) {
1865                    (Expr::InList(l1), Expr::InList(l2)) => {
1866                        return inlist_union(l1, l2, true).map(Transformed::yes);
1867                    }
1868                    // Matched previously once
1869                    _ => unreachable!(),
1870                }
1871            }
1872
1873            Expr::BinaryExpr(BinaryExpr {
1874                left,
1875                op: And,
1876                right,
1877            }) if are_inlist_and_eq_and_match_neg(
1878                left.as_ref(),
1879                right.as_ref(),
1880                false,
1881                true,
1882            ) =>
1883            {
1884                match (*left, *right) {
1885                    (Expr::InList(l1), Expr::InList(l2)) => {
1886                        return inlist_except(l1, &l2).map(Transformed::yes);
1887                    }
1888                    // Matched previously once
1889                    _ => unreachable!(),
1890                }
1891            }
1892
1893            Expr::BinaryExpr(BinaryExpr {
1894                left,
1895                op: And,
1896                right,
1897            }) if are_inlist_and_eq_and_match_neg(
1898                left.as_ref(),
1899                right.as_ref(),
1900                true,
1901                false,
1902            ) =>
1903            {
1904                match (*left, *right) {
1905                    (Expr::InList(l1), Expr::InList(l2)) => {
1906                        return inlist_except(l2, &l1).map(Transformed::yes);
1907                    }
1908                    // Matched previously once
1909                    _ => unreachable!(),
1910                }
1911            }
1912
1913            Expr::BinaryExpr(BinaryExpr {
1914                left,
1915                op: Or,
1916                right,
1917            }) if are_inlist_and_eq_and_match_neg(
1918                left.as_ref(),
1919                right.as_ref(),
1920                true,
1921                true,
1922            ) =>
1923            {
1924                match (*left, *right) {
1925                    (Expr::InList(l1), Expr::InList(l2)) => {
1926                        return inlist_intersection(l1, &l2, true).map(Transformed::yes);
1927                    }
1928                    // Matched previously once
1929                    _ => unreachable!(),
1930                }
1931            }
1932
1933            // =======================================
1934            // unwrap_cast_in_comparison
1935            // =======================================
1936            //
1937            // For case:
1938            // try_cast/cast(expr as data_type) op literal
1939            Expr::BinaryExpr(BinaryExpr { left, op, right })
1940                if is_cast_expr_and_support_unwrap_cast_in_comparison_for_binary(
1941                    info, &left, op, &right,
1942                ) && op.supports_propagation() =>
1943            {
1944                unwrap_cast_in_comparison_for_binary(info, *left, *right, op)?
1945            }
1946            // literal op try_cast/cast(expr as data_type)
1947            // -->
1948            // try_cast/cast(expr as data_type) op_swap literal
1949            Expr::BinaryExpr(BinaryExpr { left, op, right })
1950                if is_cast_expr_and_support_unwrap_cast_in_comparison_for_binary(
1951                    info, &right, op, &left,
1952                ) && op.supports_propagation()
1953                    && op.swap().is_some() =>
1954            {
1955                unwrap_cast_in_comparison_for_binary(
1956                    info,
1957                    *right,
1958                    *left,
1959                    op.swap().unwrap(),
1960                )?
1961            }
1962            // For case:
1963            // try_cast/cast(expr as left_type) in (expr1,expr2,expr3)
1964            Expr::InList(InList {
1965                expr: mut left,
1966                list,
1967                negated,
1968            }) if is_cast_expr_and_support_unwrap_cast_in_comparison_for_inlist(
1969                info, &left, &list,
1970            ) =>
1971            {
1972                let (Expr::TryCast(TryCast {
1973                    expr: left_expr, ..
1974                })
1975                | Expr::Cast(Cast {
1976                    expr: left_expr, ..
1977                })) = left.as_mut()
1978                else {
1979                    return internal_err!("Expect cast expr, but got {:?}", left)?;
1980                };
1981
1982                let expr_type = info.get_data_type(left_expr)?;
1983                let right_exprs = list
1984                    .into_iter()
1985                    .map(|right| {
1986                        match right {
1987                            Expr::Literal(right_lit_value, _) => {
1988                                // if the right_lit_value can be casted to the type of internal_left_expr
1989                                // we need to unwrap the cast for cast/try_cast expr, and add cast to the literal
1990                                let Some(value) = try_cast_literal_to_type(&right_lit_value, &expr_type) else {
1991                                    internal_err!(
1992                                        "Can't cast the list expr {:?} to type {}",
1993                                        right_lit_value, &expr_type
1994                                    )?
1995                                };
1996                                Ok(lit(value))
1997                            }
1998                            other_expr => internal_err!(
1999                                "Only support literal expr to optimize, but the expr is {:?}",
2000                                &other_expr
2001                            ),
2002                        }
2003                    })
2004                    .collect::<Result<Vec<_>>>()?;
2005
2006                Transformed::yes(Expr::InList(InList {
2007                    expr: std::mem::take(left_expr),
2008                    list: right_exprs,
2009                    negated,
2010                }))
2011            }
2012
2013            // =======================================
2014            // preimage_in_comparison
2015            // =======================================
2016            //
2017            // For case:
2018            // date_part('YEAR', expr) op literal
2019            //
2020            // For details see datafusion_expr::ScalarUDFImpl::preimage
2021            Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2022                use datafusion_expr::Operator::*;
2023                let is_preimage_op = matches!(
2024                    op,
2025                    Eq | NotEq
2026                        | Lt
2027                        | LtEq
2028                        | Gt
2029                        | GtEq
2030                        | IsDistinctFrom
2031                        | IsNotDistinctFrom
2032                );
2033                if !is_preimage_op || is_null(&right) {
2034                    return Ok(Transformed::no(Expr::BinaryExpr(BinaryExpr {
2035                        left,
2036                        op,
2037                        right,
2038                    })));
2039                }
2040
2041                if let PreimageResult::Range { interval, expr } =
2042                    get_preimage(left.as_ref(), right.as_ref(), info)?
2043                {
2044                    rewrite_with_preimage(*interval, op, expr)?
2045                } else if let Some(swapped) = op.swap() {
2046                    if let PreimageResult::Range { interval, expr } =
2047                        get_preimage(right.as_ref(), left.as_ref(), info)?
2048                    {
2049                        rewrite_with_preimage(*interval, swapped, expr)?
2050                    } else {
2051                        Transformed::no(Expr::BinaryExpr(BinaryExpr { left, op, right }))
2052                    }
2053                } else {
2054                    Transformed::no(Expr::BinaryExpr(BinaryExpr { left, op, right }))
2055                }
2056            }
2057            // For case:
2058            // date_part('YEAR', expr) IN (literal1, literal2, ...)
2059            Expr::InList(InList {
2060                expr,
2061                list,
2062                negated,
2063            }) => {
2064                if list.len() > THRESHOLD_INLINE_INLIST || list.iter().any(is_null) {
2065                    return Ok(Transformed::no(Expr::InList(InList {
2066                        expr,
2067                        list,
2068                        negated,
2069                    })));
2070                }
2071
2072                let (op, combiner): (Operator, fn(Expr, Expr) -> Expr) =
2073                    if negated { (NotEq, and) } else { (Eq, or) };
2074
2075                let mut rewritten: Option<Expr> = None;
2076                for item in &list {
2077                    let PreimageResult::Range { interval, expr } =
2078                        get_preimage(expr.as_ref(), item, info)?
2079                    else {
2080                        return Ok(Transformed::no(Expr::InList(InList {
2081                            expr,
2082                            list,
2083                            negated,
2084                        })));
2085                    };
2086
2087                    let range_expr = rewrite_with_preimage(*interval, op, expr)?.data;
2088                    rewritten = Some(match rewritten {
2089                        None => range_expr,
2090                        Some(acc) => combiner(acc, range_expr),
2091                    });
2092                }
2093
2094                if let Some(rewritten) = rewritten {
2095                    Transformed::yes(rewritten)
2096                } else {
2097                    Transformed::no(Expr::InList(InList {
2098                        expr,
2099                        list,
2100                        negated,
2101                    }))
2102                }
2103            }
2104
2105            // no additional rewrites possible
2106            expr => Transformed::no(expr),
2107        })
2108    }
2109}
2110
2111fn get_preimage(
2112    left_expr: &Expr,
2113    right_expr: &Expr,
2114    info: &SimplifyContext,
2115) -> Result<PreimageResult> {
2116    let Expr::ScalarFunction(ScalarFunction { func, args }) = left_expr else {
2117        return Ok(PreimageResult::None);
2118    };
2119    if !is_literal_or_literal_cast(right_expr) {
2120        return Ok(PreimageResult::None);
2121    }
2122    if func.signature().volatility != Volatility::Immutable {
2123        return Ok(PreimageResult::None);
2124    }
2125    func.preimage(args, right_expr, info)
2126}
2127
2128fn is_literal_or_literal_cast(expr: &Expr) -> bool {
2129    match expr {
2130        Expr::Literal(_, _) => true,
2131        Expr::Cast(Cast { expr, .. }) => matches!(expr.as_ref(), Expr::Literal(_, _)),
2132        Expr::TryCast(TryCast { expr, .. }) => {
2133            matches!(expr.as_ref(), Expr::Literal(_, _))
2134        }
2135        _ => false,
2136    }
2137}
2138
2139/// Helper for working with string scalar values (Utf8, LargeUtf8, Utf8View)
2140pub(crate) enum StringScalar<'a> {
2141    Utf8(&'a ScalarValue),
2142    LargeUtf8(&'a ScalarValue),
2143    Utf8View(&'a ScalarValue),
2144}
2145
2146impl<'a> StringScalar<'a> {
2147    /// Create a `StringScalar` view from an `Expr` if it is a supported string literal.
2148    /// Returns `None` if the expression is not a string literal.
2149    pub(crate) fn try_from_expr(expr: &'a Expr) -> Option<Self> {
2150        match expr {
2151            Expr::Literal(scalar, _) => Self::try_from_scalar(scalar),
2152            _ => None,
2153        }
2154    }
2155
2156    /// Create a `StringScalar` view from a `ScalarValue` if it is a supported string type.
2157    /// Returns `None` if the scalar value is not a supported string type.
2158    fn try_from_scalar(scalar: &'a ScalarValue) -> Option<Self> {
2159        match scalar {
2160            ScalarValue::Utf8(_) => Some(Self::Utf8(scalar)),
2161            ScalarValue::LargeUtf8(_) => Some(Self::LargeUtf8(scalar)),
2162            ScalarValue::Utf8View(_) => Some(Self::Utf8View(scalar)),
2163            _ => None,
2164        }
2165    }
2166
2167    /// Returns the underlying string slice.
2168    pub(crate) fn as_str(&self) -> Option<&'a str> {
2169        match self {
2170            Self::Utf8(scalar) | Self::LargeUtf8(scalar) | Self::Utf8View(scalar) => {
2171                scalar.try_as_str().flatten()
2172            }
2173        }
2174    }
2175
2176    /// Build a new `Expr` of the same string type with the given value.
2177    pub(crate) fn to_expr(&self, val: &str) -> Expr {
2178        match self {
2179            Self::Utf8(_) => Expr::Literal(ScalarValue::Utf8(Some(val.to_owned())), None),
2180            Self::LargeUtf8(_) => {
2181                Expr::Literal(ScalarValue::LargeUtf8(Some(val.to_owned())), None)
2182            }
2183            Self::Utf8View(_) => {
2184                Expr::Literal(ScalarValue::Utf8View(Some(val.to_owned())), None)
2185            }
2186        }
2187    }
2188}
2189
2190#[allow(clippy::allow_attributes, clippy::mutable_key_type)] // Expr contains Arc with interior mutability but is intentionally used as hash key
2191fn has_common_conjunction(lhs: &Expr, rhs: &Expr) -> bool {
2192    let lhs_set: HashSet<&Expr> = iter_conjunction(lhs).collect();
2193    iter_conjunction(rhs).any(|e| lhs_set.contains(&e) && !e.is_volatile())
2194}
2195
2196// TODO: We might not need this after defer pattern for Box is stabilized. https://github.com/rust-lang/rust/issues/87121
2197fn are_inlist_and_eq_and_match_neg(
2198    left: &Expr,
2199    right: &Expr,
2200    is_left_neg: bool,
2201    is_right_neg: bool,
2202) -> bool {
2203    match (left, right) {
2204        (Expr::InList(l), Expr::InList(r)) => {
2205            l.expr == r.expr && l.negated == is_left_neg && r.negated == is_right_neg
2206        }
2207        _ => false,
2208    }
2209}
2210
2211// TODO: We might not need this after defer pattern for Box is stabilized. https://github.com/rust-lang/rust/issues/87121
2212fn are_inlist_and_eq(left: &Expr, right: &Expr) -> bool {
2213    let left = as_inlist(left);
2214    let right = as_inlist(right);
2215    if let (Some(lhs), Some(rhs)) = (left, right) {
2216        matches!(lhs.expr.as_ref(), Expr::Column(_))
2217            && matches!(rhs.expr.as_ref(), Expr::Column(_))
2218            && lhs.expr == rhs.expr
2219            && !lhs.negated
2220            && !rhs.negated
2221    } else {
2222        false
2223    }
2224}
2225
2226/// Try to convert an expression to an in-list expression
2227fn as_inlist(expr: &'_ Expr) -> Option<Cow<'_, InList>> {
2228    match expr {
2229        Expr::InList(inlist) => Some(Cow::Borrowed(inlist)),
2230        Expr::BinaryExpr(BinaryExpr { left, op, right }) if *op == Operator::Eq => {
2231            match (left.as_ref(), right.as_ref()) {
2232                (Expr::Column(_), Expr::Literal(_, _)) => Some(Cow::Owned(InList {
2233                    expr: left.clone(),
2234                    list: vec![*right.clone()],
2235                    negated: false,
2236                })),
2237                (Expr::Literal(_, _), Expr::Column(_)) => Some(Cow::Owned(InList {
2238                    expr: right.clone(),
2239                    list: vec![*left.clone()],
2240                    negated: false,
2241                })),
2242                _ => None,
2243            }
2244        }
2245        _ => None,
2246    }
2247}
2248
2249fn to_inlist(expr: Expr) -> Option<InList> {
2250    match expr {
2251        Expr::InList(inlist) => Some(inlist),
2252        Expr::BinaryExpr(BinaryExpr {
2253            left,
2254            op: Operator::Eq,
2255            right,
2256        }) => match (left.as_ref(), right.as_ref()) {
2257            (Expr::Column(_), Expr::Literal(_, _)) => Some(InList {
2258                expr: left,
2259                list: vec![*right],
2260                negated: false,
2261            }),
2262            (Expr::Literal(_, _), Expr::Column(_)) => Some(InList {
2263                expr: right,
2264                list: vec![*left],
2265                negated: false,
2266            }),
2267            _ => None,
2268        },
2269        _ => None,
2270    }
2271}
2272
2273/// Return the union of two inlist expressions
2274/// maintaining the order of the elements in the two lists
2275#[allow(clippy::allow_attributes, clippy::mutable_key_type)] // Expr contains Arc with interior mutability but is intentionally used as hash key
2276fn inlist_union(mut l1: InList, l2: InList, negated: bool) -> Result<Expr> {
2277    // extend the list in l1 with the elements in l2 that are not already in l1
2278    let l1_items: HashSet<_> = l1.list.iter().collect();
2279
2280    // keep all l2 items that do not also appear in l1
2281    let keep_l2: Vec<_> = l2
2282        .list
2283        .into_iter()
2284        .filter_map(|e| if l1_items.contains(&e) { None } else { Some(e) })
2285        .collect();
2286
2287    l1.list.extend(keep_l2);
2288    l1.negated = negated;
2289    Ok(Expr::InList(l1))
2290}
2291
2292/// Return the intersection of two inlist expressions
2293/// maintaining the order of the elements in the two lists
2294#[allow(clippy::allow_attributes, clippy::mutable_key_type)] // Expr contains Arc with interior mutability but is intentionally used as hash key
2295fn inlist_intersection(mut l1: InList, l2: &InList, negated: bool) -> Result<Expr> {
2296    let l2_items = l2.list.iter().collect::<HashSet<_>>();
2297
2298    // remove all items from l1 that are not in l2
2299    l1.list.retain(|e| l2_items.contains(e));
2300
2301    // e in () is always false
2302    // e not in () is always true
2303    if l1.list.is_empty() {
2304        return Ok(lit(negated));
2305    }
2306    Ok(Expr::InList(l1))
2307}
2308
2309/// Return the all items in l1 that are not in l2
2310/// maintaining the order of the elements in the two lists
2311#[allow(clippy::allow_attributes, clippy::mutable_key_type)] // Expr contains Arc with interior mutability but is intentionally used as hash key
2312fn inlist_except(mut l1: InList, l2: &InList) -> Result<Expr> {
2313    let l2_items = l2.list.iter().collect::<HashSet<_>>();
2314
2315    // keep only items from l1 that are not in l2
2316    l1.list.retain(|e| !l2_items.contains(e));
2317
2318    if l1.list.is_empty() {
2319        return Ok(lit(false));
2320    }
2321    Ok(Expr::InList(l1))
2322}
2323
2324/// Returns expression testing a boolean `expr` for being exactly `true` (not `false` or NULL).
2325fn is_exactly_true(expr: Expr, info: &SimplifyContext) -> Result<Expr> {
2326    if !info.nullable(&expr)? {
2327        Ok(expr)
2328    } else {
2329        Ok(Expr::BinaryExpr(BinaryExpr {
2330            left: Box::new(expr),
2331            op: Operator::IsNotDistinctFrom,
2332            right: Box::new(lit(true)),
2333        }))
2334    }
2335}
2336
2337// A * 1 -> A
2338// A / 1 -> A
2339//
2340// Move this function body out of the large match branch avoid stack overflow
2341fn simplify_right_is_one_case(
2342    info: &SimplifyContext,
2343    left: Box<Expr>,
2344    op: &Operator,
2345    right: &Expr,
2346) -> Result<Transformed<Expr>> {
2347    // Check if resulting type would be different due to coercion
2348    let left_type = info.get_data_type(&left)?;
2349    let right_type = info.get_data_type(right)?;
2350    match BinaryTypeCoercer::new(&left_type, op, &right_type).get_result_type() {
2351        Ok(result_type) => {
2352            // Only cast if the types differ
2353            if left_type != result_type {
2354                Ok(Transformed::yes(Expr::Cast(Cast::new(left, result_type))))
2355            } else {
2356                Ok(Transformed::yes(*left))
2357            }
2358        }
2359        Err(_) => Ok(Transformed::yes(*left)),
2360    }
2361}
2362
2363#[cfg(test)]
2364mod tests {
2365    use super::*;
2366    use crate::test::test_table_scan_with_name;
2367    use arrow::{
2368        array::{Int32Array, StructArray},
2369        datatypes::{FieldRef, Fields},
2370    };
2371    use datafusion_common::{DFSchemaRef, ToDFSchema, assert_contains};
2372    use datafusion_expr::{
2373        expr::WindowFunction,
2374        function::{
2375            AccumulatorArgs, AggregateFunctionSimplification,
2376            WindowFunctionSimplification,
2377        },
2378        interval_arithmetic::Interval,
2379        *,
2380    };
2381    use datafusion_functions_window_common::field::WindowUDFFieldArgs;
2382    use datafusion_functions_window_common::partition::PartitionEvaluatorArgs;
2383    use datafusion_physical_expr::PhysicalExpr;
2384    use std::hash::Hash;
2385    use std::sync::LazyLock;
2386    use std::{
2387        collections::HashMap,
2388        ops::{BitAnd, BitOr, BitXor},
2389        sync::Arc,
2390    };
2391
2392    // ------------------------------
2393    // --- ExprSimplifier tests -----
2394    // ------------------------------
2395    #[test]
2396    fn api_basic() {
2397        let simplifier = ExprSimplifier::new(
2398            SimplifyContext::builder()
2399                .with_schema(test_schema())
2400                .build(),
2401        );
2402
2403        let expr = lit(1) + lit(2);
2404        let expected = lit(3);
2405        assert_eq!(expected, simplifier.simplify(expr).unwrap());
2406    }
2407
2408    #[test]
2409    fn basic_coercion() {
2410        let schema = test_schema();
2411        let simplifier = ExprSimplifier::new(
2412            SimplifyContext::builder()
2413                .with_schema(Arc::clone(&schema))
2414                .build(),
2415        );
2416
2417        // Note expr type is int32 (not int64)
2418        // (1i64 + 2i32) < i
2419        let expr = (lit(1i64) + lit(2i32)).lt(col("i"));
2420        // should fully simplify to 3 < i (though i has been coerced to i64)
2421        let expected = lit(3i64).lt(col("i"));
2422
2423        let expr = simplifier.coerce(expr, &schema).unwrap();
2424
2425        assert_eq!(expected, simplifier.simplify(expr).unwrap());
2426    }
2427
2428    fn test_schema() -> DFSchemaRef {
2429        static TEST_SCHEMA: LazyLock<DFSchemaRef> = LazyLock::new(|| {
2430            Schema::new(vec![
2431                Field::new("i", DataType::Int64, false),
2432                Field::new("b", DataType::Boolean, true),
2433            ])
2434            .to_dfschema_ref()
2435            .unwrap()
2436        });
2437        Arc::clone(&TEST_SCHEMA)
2438    }
2439
2440    #[test]
2441    fn simplify_and_constant_prop() {
2442        let simplifier = ExprSimplifier::new(
2443            SimplifyContext::builder()
2444                .with_schema(test_schema())
2445                .build(),
2446        );
2447
2448        // should be able to simplify to false
2449        // (i * (1 - 2)) > 0
2450        let expr = (col("i") * (lit(1) - lit(1))).gt(lit(0));
2451        let expected = lit(false);
2452        assert_eq!(expected, simplifier.simplify(expr).unwrap());
2453    }
2454
2455    #[test]
2456    fn simplify_and_constant_prop_with_case() {
2457        let simplifier = ExprSimplifier::new(
2458            SimplifyContext::builder()
2459                .with_schema(test_schema())
2460                .build(),
2461        );
2462
2463        //   CASE
2464        //     WHEN i>5 AND false THEN i > 5
2465        //     WHEN i<5 AND true THEN i < 5
2466        //     ELSE false
2467        //   END
2468        //
2469        // Can be simplified to `i < 5`
2470        let expr = when(col("i").gt(lit(5)).and(lit(false)), col("i").gt(lit(5)))
2471            .when(col("i").lt(lit(5)).and(lit(true)), col("i").lt(lit(5)))
2472            .otherwise(lit(false))
2473            .unwrap();
2474        let expected = col("i").lt(lit(5));
2475        assert_eq!(expected, simplifier.simplify(expr).unwrap());
2476    }
2477
2478    // ------------------------------
2479    // --- Simplifier tests -----
2480    // ------------------------------
2481
2482    #[test]
2483    fn test_simplify_canonicalize() {
2484        {
2485            let expr = lit(1).lt(col("c2")).and(col("c2").gt(lit(1)));
2486            let expected = col("c2").gt(lit(1));
2487            assert_eq!(simplify(expr), expected);
2488        }
2489        {
2490            let expr = col("c1").lt(col("c2")).and(col("c2").gt(col("c1")));
2491            let expected = col("c2").gt(col("c1"));
2492            assert_eq!(simplify(expr), expected);
2493        }
2494        {
2495            let expr = col("c1")
2496                .eq(lit(1))
2497                .and(lit(1).eq(col("c1")))
2498                .and(col("c1").eq(lit(3)));
2499            let expected = col("c1").eq(lit(1)).and(col("c1").eq(lit(3)));
2500            assert_eq!(simplify(expr), expected);
2501        }
2502        {
2503            let expr = col("c1")
2504                .eq(col("c2"))
2505                .and(col("c1").gt(lit(5)))
2506                .and(col("c2").eq(col("c1")));
2507            let expected = col("c2").eq(col("c1")).and(col("c1").gt(lit(5)));
2508            assert_eq!(simplify(expr), expected);
2509        }
2510        {
2511            let expr = col("c1")
2512                .eq(lit(1))
2513                .and(col("c2").gt(lit(3)).or(lit(3).lt(col("c2"))));
2514            let expected = col("c1").eq(lit(1)).and(col("c2").gt(lit(3)));
2515            assert_eq!(simplify(expr), expected);
2516        }
2517        {
2518            let expr = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2519            let expected = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2520            assert_eq!(simplify(expr), expected);
2521        }
2522        {
2523            let expr = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2524            let expected = col("c1").lt(lit(5)).and(col("c1").gt_eq(lit(5)));
2525            assert_eq!(simplify(expr), expected);
2526        }
2527        {
2528            let expr = col("c1").gt(col("c2")).and(col("c1").gt(col("c2")));
2529            let expected = col("c2").lt(col("c1"));
2530            assert_eq!(simplify(expr), expected);
2531        }
2532    }
2533
2534    #[test]
2535    fn test_simplify_eq_not_self() {
2536        // `expr_a`: column `c2` is nullable, so `c2 = c2` simplifies to `c2 IS NOT NULL OR NULL`
2537        // This ensures the expression is only true when `c2` is not NULL, accounting for SQL's NULL semantics.
2538        let expr_a = col("c2").eq(col("c2"));
2539        let expected_a = col("c2").is_not_null().or(lit_bool_null());
2540
2541        // `expr_b`: column `c2_non_null` is explicitly non-nullable, so `c2_non_null = c2_non_null` is always true
2542        let expr_b = col("c2_non_null").eq(col("c2_non_null"));
2543        let expected_b = lit(true);
2544
2545        assert_eq!(simplify(expr_a), expected_a);
2546        assert_eq!(simplify(expr_b), expected_b);
2547    }
2548
2549    /// `c3_non_null IN (SELECT a FROM t)`, where `a` has the given nullability.
2550    fn in_subquery_expr(a_nullable: bool) -> Expr {
2551        let schema = Schema::new(vec![Field::new("a", DataType::Int64, a_nullable)]);
2552        let source = Arc::new(LogicalTableSource::new(Arc::new(schema)));
2553        let subquery = LogicalPlanBuilder::scan("t", source, None)
2554            .unwrap()
2555            .project(vec![col("a")])
2556            .unwrap()
2557            .build()
2558            .unwrap();
2559
2560        in_subquery(col("c3_non_null"), Arc::new(subquery))
2561    }
2562
2563    #[test]
2564    fn test_simplify_eq_not_self_in_subquery() {
2565        // `expr_a`: even though `c3_non_null` is non-nullable, the `IN` evaluates to NULL
2566        // when `c3_non_null` matches no row and the subquery's `a` contains a NULL. So the
2567        // expression is nullable and `A = A` must not fold to `true`.
2568        let expr_a = in_subquery_expr(true);
2569        let expected_a = expr_a.clone().is_not_null().or(lit_bool_null());
2570
2571        // `expr_b`: neither side can be NULL, so the `IN` is non-nullable and `A = A` is true.
2572        let expr_b = in_subquery_expr(false);
2573        let expected_b = lit(true);
2574
2575        assert_eq!(simplify(expr_a.clone().eq(expr_a)), expected_a);
2576        assert_eq!(simplify(expr_b.clone().eq(expr_b)), expected_b);
2577    }
2578
2579    #[test]
2580    fn test_simplify_or_true() {
2581        let expr_a = col("c2").or(lit(true));
2582        let expr_b = lit(true).or(col("c2"));
2583        let expected = lit(true);
2584
2585        assert_eq!(simplify(expr_a), expected);
2586        assert_eq!(simplify(expr_b), expected);
2587    }
2588
2589    #[test]
2590    fn test_simplify_or_false() {
2591        let expr_a = lit(false).or(col("c2"));
2592        let expr_b = col("c2").or(lit(false));
2593        let expected = col("c2");
2594
2595        assert_eq!(simplify(expr_a), expected);
2596        assert_eq!(simplify(expr_b), expected);
2597    }
2598
2599    #[test]
2600    fn test_simplify_or_same() {
2601        let expr = col("c2").or(col("c2"));
2602        let expected = col("c2");
2603
2604        assert_eq!(simplify(expr), expected);
2605    }
2606
2607    #[test]
2608    fn test_simplify_or_not_self() {
2609        // A OR !A if A is not nullable --> true
2610        // !A OR A if A is not nullable --> true
2611        let expr_a = col("c2_non_null").or(col("c2_non_null").not());
2612        let expr_b = col("c2_non_null").not().or(col("c2_non_null"));
2613        let expected = lit(true);
2614
2615        assert_eq!(simplify(expr_a), expected);
2616        assert_eq!(simplify(expr_b), expected);
2617    }
2618
2619    #[test]
2620    fn test_simplify_and_false() {
2621        let expr_a = lit(false).and(col("c2"));
2622        let expr_b = col("c2").and(lit(false));
2623        let expected = lit(false);
2624
2625        assert_eq!(simplify(expr_a), expected);
2626        assert_eq!(simplify(expr_b), expected);
2627    }
2628
2629    #[test]
2630    fn test_simplify_and_same() {
2631        let expr = col("c2").and(col("c2"));
2632        let expected = col("c2");
2633
2634        assert_eq!(simplify(expr), expected);
2635    }
2636
2637    #[test]
2638    fn test_simplify_and_true() {
2639        let expr_a = lit(true).and(col("c2"));
2640        let expr_b = col("c2").and(lit(true));
2641        let expected = col("c2");
2642
2643        assert_eq!(simplify(expr_a), expected);
2644        assert_eq!(simplify(expr_b), expected);
2645    }
2646
2647    #[test]
2648    fn test_simplify_and_not_self() {
2649        // A AND !A if A is not nullable --> false
2650        // !A AND A if A is not nullable --> false
2651        let expr_a = col("c2_non_null").and(col("c2_non_null").not());
2652        let expr_b = col("c2_non_null").not().and(col("c2_non_null"));
2653        let expected = lit(false);
2654
2655        assert_eq!(simplify(expr_a), expected);
2656        assert_eq!(simplify(expr_b), expected);
2657    }
2658
2659    #[test]
2660    fn test_simplify_eq_and_neq_with_different_literals() {
2661        // A = 1 AND A != 0 --> A = 1 (when 1 != 0)
2662        let expr = col("c2").eq(lit(1)).and(col("c2").not_eq(lit(0)));
2663        let expected = col("c2").eq(lit(1));
2664        assert_eq!(simplify(expr), expected);
2665
2666        // A != 0 AND A = 1 --> A = 1 (when 1 != 0)
2667        let expr = col("c2").not_eq(lit(0)).and(col("c2").eq(lit(1)));
2668        let expected = col("c2").eq(lit(1));
2669        assert_eq!(simplify(expr), expected);
2670
2671        // Should NOT simplify when literals are the same (A = 1 AND A != 1)
2672        // This is a contradiction but handled by other rules
2673        let expr = col("c2").eq(lit(1)).and(col("c2").not_eq(lit(1)));
2674        // Should not be simplified by this rule (left unchanged or handled elsewhere)
2675        let result = simplify(expr.clone());
2676        // The expression should not have been simplified
2677        assert_eq!(result, expr);
2678    }
2679
2680    #[test]
2681    fn test_simplify_multiply_by_one() {
2682        let expr_a = col("c2") * lit(1);
2683        let expr_b = lit(1) * col("c2");
2684        let expected = col("c2");
2685
2686        assert_eq!(simplify(expr_a), expected);
2687        assert_eq!(simplify(expr_b), expected);
2688
2689        let expr = col("c2") * lit(ScalarValue::Decimal128(Some(10000000000), 38, 10));
2690        assert_eq!(simplify(expr), expected);
2691
2692        let expr = lit(ScalarValue::Decimal128(Some(10000000000), 31, 10)) * col("c2");
2693        assert_eq!(simplify(expr), expected);
2694    }
2695
2696    #[test]
2697    fn test_simplify_multiply_by_null() {
2698        let null = lit(ScalarValue::Int64(None));
2699        // A * null --> null
2700        {
2701            let expr = col("c3") * null.clone();
2702            assert_eq!(simplify(expr), null);
2703        }
2704        // null * A --> null
2705        {
2706            let expr = null.clone() * col("c3");
2707            assert_eq!(simplify(expr), null);
2708        }
2709    }
2710
2711    #[test]
2712    fn test_simplify_multiply_by_zero() {
2713        // cannot optimize A * null (null * A) if A is nullable
2714        {
2715            let expr_a = col("c2") * lit(0);
2716            let expr_b = lit(0) * col("c2");
2717
2718            assert_eq!(simplify(expr_a.clone()), expr_a);
2719            assert_eq!(simplify(expr_b.clone()), expr_b);
2720        }
2721        // 0 * A --> 0 if A is not nullable
2722        {
2723            let expr = lit(0) * col("c2_non_null");
2724            assert_eq!(simplify(expr), lit(0));
2725        }
2726        // A * 0 --> 0 if A is not nullable
2727        {
2728            let expr = col("c2_non_null") * lit(0);
2729            assert_eq!(simplify(expr), lit(0));
2730        }
2731        // A * Decimal128(0) --> 0 if A is not nullable
2732        {
2733            let expr = col("c2_non_null") * lit(ScalarValue::Decimal128(Some(0), 31, 10));
2734            assert_eq!(
2735                simplify(expr),
2736                lit(ScalarValue::Decimal128(Some(0), 31, 10))
2737            );
2738            let expr = binary_expr(
2739                lit(ScalarValue::Decimal128(Some(0), 31, 10)),
2740                Operator::Multiply,
2741                col("c2_non_null"),
2742            );
2743            assert_eq!(
2744                simplify(expr),
2745                lit(ScalarValue::Decimal128(Some(0), 31, 10))
2746            );
2747        }
2748    }
2749
2750    #[test]
2751    fn test_simplify_divide_by_one() {
2752        let expr = binary_expr(col("c2"), Operator::Divide, lit(1));
2753        let expected = col("c2");
2754        assert_eq!(simplify(expr), expected);
2755        let expr = col("c2") / lit(ScalarValue::Decimal128(Some(10000000000), 31, 10));
2756        assert_eq!(simplify(expr), expected);
2757    }
2758
2759    #[test]
2760    fn test_simplify_divide_null() {
2761        // A / null --> null
2762        let null = lit(ScalarValue::Int64(None));
2763        {
2764            let expr = col("c3") / null.clone();
2765            assert_eq!(simplify(expr), null);
2766        }
2767        // null / A --> null
2768        {
2769            let expr = null.clone() / col("c3");
2770            assert_eq!(simplify(expr), null);
2771        }
2772    }
2773
2774    #[test]
2775    fn test_simplify_divide_by_same() {
2776        let expr = col("c2") / col("c2");
2777        // if c2 is null, c2 / c2 = null, so can't simplify
2778        let expected = expr.clone();
2779
2780        assert_eq!(simplify(expr), expected);
2781    }
2782
2783    #[test]
2784    fn test_simplify_modulo_by_null() {
2785        let null = lit(ScalarValue::Int64(None));
2786        // A % null --> null
2787        {
2788            let expr = col("c3") % null.clone();
2789            assert_eq!(simplify(expr), null);
2790        }
2791        // null % A --> null
2792        {
2793            let expr = null.clone() % col("c3");
2794            assert_eq!(simplify(expr), null);
2795        }
2796    }
2797
2798    #[test]
2799    fn test_simplify_modulo_by_one() {
2800        let expr = col("c2") % lit(1);
2801        // if c2 is null, c2 % 1 = null, so can't simplify
2802        let expected = expr.clone();
2803
2804        assert_eq!(simplify(expr), expected);
2805    }
2806
2807    #[test]
2808    fn test_simplify_divide_zero_by_zero() {
2809        // because divide by 0 maybe occur in short-circuit expression
2810        // so we should not simplify this, and throw error in runtime
2811        let expr = lit(0) / lit(0);
2812        let expected = expr.clone();
2813
2814        assert_eq!(simplify(expr), expected);
2815    }
2816
2817    #[test]
2818    fn test_simplify_divide_by_zero() {
2819        // because divide by 0 maybe occur in short-circuit expression
2820        // so we should not simplify this, and throw error in runtime
2821        let expr = col("c2_non_null") / lit(0);
2822        let expected = expr.clone();
2823
2824        assert_eq!(simplify(expr), expected);
2825    }
2826
2827    #[test]
2828    fn test_simplify_modulo_by_one_non_null() {
2829        let expr = col("c3_non_null") % lit(1);
2830        let expected = lit(0_i64);
2831        assert_eq!(simplify(expr), expected);
2832        let expr =
2833            col("c3_non_null") % lit(ScalarValue::Decimal128(Some(10000000000), 31, 10));
2834        assert_eq!(simplify(expr), expected);
2835    }
2836
2837    #[test]
2838    fn test_simplify_bitwise_xor_by_null() {
2839        let null = lit(ScalarValue::Int64(None));
2840        // A ^ null --> null
2841        {
2842            let expr = col("c3") ^ null.clone();
2843            assert_eq!(simplify(expr), null);
2844        }
2845        // null ^ A --> null
2846        {
2847            let expr = null.clone() ^ col("c3");
2848            assert_eq!(simplify(expr), null);
2849        }
2850    }
2851
2852    #[test]
2853    fn test_simplify_bitwise_shift_right_by_null() {
2854        let null = lit(ScalarValue::Int64(None));
2855        // A >> null --> null
2856        {
2857            let expr = col("c3") >> null.clone();
2858            assert_eq!(simplify(expr), null);
2859        }
2860        // null >> A --> null
2861        {
2862            let expr = null.clone() >> col("c3");
2863            assert_eq!(simplify(expr), null);
2864        }
2865    }
2866
2867    #[test]
2868    fn test_simplify_bitwise_shift_left_by_null() {
2869        let null = lit(ScalarValue::Int64(None));
2870        // A << null --> null
2871        {
2872            let expr = col("c3") << null.clone();
2873            assert_eq!(simplify(expr), null);
2874        }
2875        // null << A --> null
2876        {
2877            let expr = null.clone() << col("c3");
2878            assert_eq!(simplify(expr), null);
2879        }
2880    }
2881
2882    #[test]
2883    fn test_simplify_bitwise_and_by_zero() {
2884        // A & 0 --> 0
2885        {
2886            let expr = col("c2_non_null") & lit(0);
2887            assert_eq!(simplify(expr), lit(0));
2888        }
2889        // 0 & A --> 0
2890        {
2891            let expr = lit(0) & col("c2_non_null");
2892            assert_eq!(simplify(expr), lit(0));
2893        }
2894    }
2895
2896    #[test]
2897    fn test_simplify_bitwise_or_by_zero() {
2898        // A | 0 --> A
2899        {
2900            let expr = col("c2_non_null") | lit(0);
2901            assert_eq!(simplify(expr), col("c2_non_null"));
2902        }
2903        // 0 | A --> A
2904        {
2905            let expr = lit(0) | col("c2_non_null");
2906            assert_eq!(simplify(expr), col("c2_non_null"));
2907        }
2908    }
2909
2910    #[test]
2911    fn test_simplify_bitwise_xor_by_zero() {
2912        // A ^ 0 --> A
2913        {
2914            let expr = col("c2_non_null") ^ lit(0);
2915            assert_eq!(simplify(expr), col("c2_non_null"));
2916        }
2917        // 0 ^ A --> A
2918        {
2919            let expr = lit(0) ^ col("c2_non_null");
2920            assert_eq!(simplify(expr), col("c2_non_null"));
2921        }
2922    }
2923
2924    #[test]
2925    fn test_simplify_bitwise_bitwise_shift_right_by_zero() {
2926        // A >> 0 --> A
2927        {
2928            let expr = col("c2_non_null") >> lit(0);
2929            assert_eq!(simplify(expr), col("c2_non_null"));
2930        }
2931    }
2932
2933    #[test]
2934    fn test_simplify_bitwise_bitwise_shift_left_by_zero() {
2935        // A << 0 --> A
2936        {
2937            let expr = col("c2_non_null") << lit(0);
2938            assert_eq!(simplify(expr), col("c2_non_null"));
2939        }
2940    }
2941
2942    #[test]
2943    fn test_simplify_bitwise_and_by_null() {
2944        let null = Expr::Literal(ScalarValue::Int64(None), None);
2945        // A & null --> null
2946        {
2947            let expr = col("c3") & null.clone();
2948            assert_eq!(simplify(expr), null);
2949        }
2950        // null & A --> null
2951        {
2952            let expr = null.clone() & col("c3");
2953            assert_eq!(simplify(expr), null);
2954        }
2955    }
2956
2957    #[test]
2958    fn test_simplify_concat_by_null() {
2959        let null = Expr::Literal(ScalarValue::Utf8(None), None);
2960        // A || null --> null
2961        {
2962            let expr = binary_expr(col("c1"), Operator::StringConcat, null.clone());
2963            assert_eq!(simplify(expr), null);
2964        }
2965        // null || A --> null
2966        {
2967            let expr = binary_expr(null.clone(), Operator::StringConcat, col("c1"));
2968            assert_eq!(simplify(expr), null);
2969        }
2970    }
2971
2972    #[test]
2973    fn test_simplify_composed_bitwise_and() {
2974        // ((c2 > 5) & (c1 < 6)) & (c2 > 5) --> (c2 > 5) & (c1 < 6)
2975
2976        let expr = bitwise_and(
2977            bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
2978            col("c2").gt(lit(5)),
2979        );
2980        let expected = bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
2981
2982        assert_eq!(simplify(expr), expected);
2983
2984        // (c2 > 5) & ((c2 > 5) & (c1 < 6)) --> (c2 > 5) & (c1 < 6)
2985
2986        let expr = bitwise_and(
2987            col("c2").gt(lit(5)),
2988            bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
2989        );
2990        let expected = bitwise_and(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
2991        assert_eq!(simplify(expr), expected);
2992    }
2993
2994    #[test]
2995    fn test_simplify_composed_bitwise_or() {
2996        // ((c2 > 5) | (c1 < 6)) | (c2 > 5) --> (c2 > 5) | (c1 < 6)
2997
2998        let expr = bitwise_or(
2999            bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
3000            col("c2").gt(lit(5)),
3001        );
3002        let expected = bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
3003
3004        assert_eq!(simplify(expr), expected);
3005
3006        // (c2 > 5) | ((c2 > 5) | (c1 < 6)) --> (c2 > 5) | (c1 < 6)
3007
3008        let expr = bitwise_or(
3009            col("c2").gt(lit(5)),
3010            bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
3011        );
3012        let expected = bitwise_or(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
3013
3014        assert_eq!(simplify(expr), expected);
3015    }
3016
3017    #[test]
3018    fn test_simplify_composed_bitwise_xor() {
3019        // with an even number of the column "c2"
3020        // c2 ^ ((c2 ^ (c2 | c1)) ^ (c1 & c2)) --> (c2 | c1) ^ (c1 & c2)
3021
3022        let expr = bitwise_xor(
3023            col("c2"),
3024            bitwise_xor(
3025                bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3026                bitwise_and(col("c1"), col("c2")),
3027            ),
3028        );
3029
3030        let expected = bitwise_xor(
3031            bitwise_or(col("c2"), col("c1")),
3032            bitwise_and(col("c1"), col("c2")),
3033        );
3034
3035        assert_eq!(simplify(expr), expected);
3036
3037        // with an odd number of the column "c2"
3038        // c2 ^ (c2 ^ (c2 | c1)) ^ ((c1 & c2) ^ c2) --> c2 ^ ((c2 | c1) ^ (c1 & c2))
3039
3040        let expr = bitwise_xor(
3041            col("c2"),
3042            bitwise_xor(
3043                bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3044                bitwise_xor(bitwise_and(col("c1"), col("c2")), col("c2")),
3045            ),
3046        );
3047
3048        let expected = bitwise_xor(
3049            col("c2"),
3050            bitwise_xor(
3051                bitwise_or(col("c2"), col("c1")),
3052                bitwise_and(col("c1"), col("c2")),
3053            ),
3054        );
3055
3056        assert_eq!(simplify(expr), expected);
3057
3058        // with an even number of the column "c2"
3059        // ((c2 ^ (c2 | c1)) ^ (c1 & c2)) ^ c2 --> (c2 | c1) ^ (c1 & c2)
3060
3061        let expr = bitwise_xor(
3062            bitwise_xor(
3063                bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3064                bitwise_and(col("c1"), col("c2")),
3065            ),
3066            col("c2"),
3067        );
3068
3069        let expected = bitwise_xor(
3070            bitwise_or(col("c2"), col("c1")),
3071            bitwise_and(col("c1"), col("c2")),
3072        );
3073
3074        assert_eq!(simplify(expr), expected);
3075
3076        // with an odd number of the column "c2"
3077        // (c2 ^ (c2 | c1)) ^ ((c1 & c2) ^ c2) ^ c2 --> ((c2 | c1) ^ (c1 & c2)) ^ c2
3078
3079        let expr = bitwise_xor(
3080            bitwise_xor(
3081                bitwise_xor(col("c2"), bitwise_or(col("c2"), col("c1"))),
3082                bitwise_xor(bitwise_and(col("c1"), col("c2")), col("c2")),
3083            ),
3084            col("c2"),
3085        );
3086
3087        let expected = bitwise_xor(
3088            bitwise_xor(
3089                bitwise_or(col("c2"), col("c1")),
3090                bitwise_and(col("c1"), col("c2")),
3091            ),
3092            col("c2"),
3093        );
3094
3095        assert_eq!(simplify(expr), expected);
3096    }
3097
3098    #[test]
3099    fn test_simplify_negated_bitwise_and() {
3100        // !c3 & c3 --> 0
3101        let expr = (-col("c3_non_null")) & col("c3_non_null");
3102        let expected = lit(0i64);
3103
3104        assert_eq!(simplify(expr), expected);
3105        // c3 & !c3 --> 0
3106        let expr = col("c3_non_null") & (-col("c3_non_null"));
3107        let expected = lit(0i64);
3108
3109        assert_eq!(simplify(expr), expected);
3110    }
3111
3112    #[test]
3113    fn test_simplify_negated_bitwise_or() {
3114        // !c3 | c3 --> -1
3115        let expr = (-col("c3_non_null")) | col("c3_non_null");
3116        let expected = lit(-1i64);
3117
3118        assert_eq!(simplify(expr), expected);
3119
3120        // c3 | !c3 --> -1
3121        let expr = col("c3_non_null") | (-col("c3_non_null"));
3122        let expected = lit(-1i64);
3123
3124        assert_eq!(simplify(expr), expected);
3125    }
3126
3127    #[test]
3128    fn test_simplify_negated_bitwise_xor() {
3129        // !c3 ^ c3 --> -1
3130        let expr = (-col("c3_non_null")) ^ col("c3_non_null");
3131        let expected = lit(-1i64);
3132
3133        assert_eq!(simplify(expr), expected);
3134
3135        // c3 ^ !c3 --> -1
3136        let expr = col("c3_non_null") ^ (-col("c3_non_null"));
3137        let expected = lit(-1i64);
3138
3139        assert_eq!(simplify(expr), expected);
3140    }
3141
3142    #[test]
3143    fn test_simplify_bitwise_and_or() {
3144        // (c2 < 3) & ((c2 < 3) | c1) -> (c2 < 3)
3145        let expr = bitwise_and(
3146            col("c2_non_null").lt(lit(3)),
3147            bitwise_or(col("c2_non_null").lt(lit(3)), col("c1_non_null")),
3148        );
3149        let expected = col("c2_non_null").lt(lit(3));
3150
3151        assert_eq!(simplify(expr), expected);
3152    }
3153
3154    #[test]
3155    fn test_simplify_bitwise_or_and() {
3156        // (c2 < 3) | ((c2 < 3) & c1) -> (c2 < 3)
3157        let expr = bitwise_or(
3158            col("c2_non_null").lt(lit(3)),
3159            bitwise_and(col("c2_non_null").lt(lit(3)), col("c1_non_null")),
3160        );
3161        let expected = col("c2_non_null").lt(lit(3));
3162
3163        assert_eq!(simplify(expr), expected);
3164    }
3165
3166    #[test]
3167    fn test_simplify_simple_bitwise_and() {
3168        // (c2 > 5) & (c2 > 5) -> (c2 > 5)
3169        let expr = (col("c2").gt(lit(5))).bitand(col("c2").gt(lit(5)));
3170        let expected = col("c2").gt(lit(5));
3171
3172        assert_eq!(simplify(expr), expected);
3173    }
3174
3175    #[test]
3176    fn test_simplify_simple_bitwise_or() {
3177        // (c2 > 5) | (c2 > 5) -> (c2 > 5)
3178        let expr = (col("c2").gt(lit(5))).bitor(col("c2").gt(lit(5)));
3179        let expected = col("c2").gt(lit(5));
3180
3181        assert_eq!(simplify(expr), expected);
3182    }
3183
3184    #[test]
3185    fn test_simplify_simple_bitwise_xor() {
3186        // c4 ^ c4 -> 0
3187        let expr = (col("c4")).bitxor(col("c4"));
3188        let expected = lit(0u32);
3189
3190        assert_eq!(simplify(expr), expected);
3191
3192        // c3 ^ c3 -> 0
3193        let expr = col("c3").bitxor(col("c3"));
3194        let expected = lit(0i64);
3195
3196        assert_eq!(simplify(expr), expected);
3197    }
3198
3199    #[test]
3200    fn test_simplify_modulo_by_zero_non_null() {
3201        // because modulo by 0 maybe occur in short-circuit expression
3202        // so we should not simplify this, and throw error in runtime.
3203        let expr = col("c2_non_null") % lit(0);
3204        let expected = expr.clone();
3205
3206        assert_eq!(simplify(expr), expected);
3207    }
3208
3209    #[test]
3210    fn test_simplify_simple_and() {
3211        // (c2 > 5) AND (c2 > 5) -> (c2 > 5)
3212        let expr = (col("c2").gt(lit(5))).and(col("c2").gt(lit(5)));
3213        let expected = col("c2").gt(lit(5));
3214
3215        assert_eq!(simplify(expr), expected);
3216    }
3217
3218    #[test]
3219    fn test_simplify_composed_and() {
3220        // ((c2 > 5) AND (c1 < 6)) AND (c2 > 5)
3221        let expr = and(
3222            and(col("c2").gt(lit(5)), col("c1").lt(lit(6))),
3223            col("c2").gt(lit(5)),
3224        );
3225        let expected = and(col("c2").gt(lit(5)), col("c1").lt(lit(6)));
3226
3227        assert_eq!(simplify(expr), expected);
3228    }
3229
3230    #[test]
3231    fn test_simplify_negated_and() {
3232        // (c2 > 5) AND !(c2 > 5) --> (c2 > 5) AND (c2 <= 5)
3233        let expr = and(col("c2").gt(lit(5)), Expr::not(col("c2").gt(lit(5))));
3234        let expected = col("c2").gt(lit(5)).and(col("c2").lt_eq(lit(5)));
3235
3236        assert_eq!(simplify(expr), expected);
3237    }
3238
3239    #[test]
3240    fn test_simplify_or_and() {
3241        let l = col("c2").gt(lit(5));
3242        let r = and(col("c1").lt(lit(6)), col("c2").gt(lit(5)));
3243
3244        // (c2 > 5) OR ((c1 < 6) AND (c2 > 5))
3245        let expr = or(l.clone(), r.clone());
3246
3247        let expected = l.clone();
3248        assert_eq!(simplify(expr), expected);
3249
3250        // ((c1 < 6) AND (c2 > 5)) OR (c2 > 5)
3251        let expr = or(r, l);
3252        assert_eq!(simplify(expr), expected);
3253    }
3254
3255    #[test]
3256    fn test_simplify_or_and_non_null() {
3257        let l = col("c2_non_null").gt(lit(5));
3258        let r = and(col("c1_non_null").lt(lit(6)), col("c2_non_null").gt(lit(5)));
3259
3260        // (c2 > 5) OR ((c1 < 6) AND (c2 > 5)) --> c2 > 5
3261        let expr = or(l.clone(), r.clone());
3262
3263        // This is only true if `c1 < 6` is not nullable / can not be null.
3264        let expected = col("c2_non_null").gt(lit(5));
3265
3266        assert_eq!(simplify(expr), expected);
3267
3268        // ((c1 < 6) AND (c2 > 5)) OR (c2 > 5) --> c2 > 5
3269        let expr = or(l, r);
3270
3271        assert_eq!(simplify(expr), expected);
3272    }
3273
3274    #[test]
3275    fn test_simplify_and_or() {
3276        let l = col("c2").gt(lit(5));
3277        let r = or(col("c1").lt(lit(6)), col("c2").gt(lit(5)));
3278
3279        // (c2 > 5) AND ((c1 < 6) OR (c2 > 5)) --> c2 > 5
3280        let expr = and(l.clone(), r.clone());
3281
3282        let expected = l.clone();
3283        assert_eq!(simplify(expr), expected);
3284
3285        // ((c1 < 6) OR (c2 > 5)) AND (c2 > 5) --> c2 > 5
3286        let expr = and(r, l);
3287        assert_eq!(simplify(expr), expected);
3288    }
3289
3290    #[test]
3291    fn test_simplify_and_or_non_null() {
3292        let l = col("c2_non_null").gt(lit(5));
3293        let r = or(col("c1_non_null").lt(lit(6)), col("c2_non_null").gt(lit(5)));
3294
3295        // (c2 > 5) AND ((c1 < 6) OR (c2 > 5)) --> c2 > 5
3296        let expr = and(l.clone(), r.clone());
3297
3298        // This is only true if `c1 < 6` is not nullable / can not be null.
3299        let expected = col("c2_non_null").gt(lit(5));
3300
3301        assert_eq!(simplify(expr), expected);
3302
3303        // ((c1 < 6) OR (c2 > 5)) AND (c2 > 5) --> c2 > 5
3304        let expr = and(l, r);
3305
3306        assert_eq!(simplify(expr), expected);
3307    }
3308
3309    #[test]
3310    fn test_simplify_by_de_morgan_laws() {
3311        // Laws with logical operations
3312        // !(c3 AND c4) --> !c3 OR !c4
3313        let expr = and(col("c3"), col("c4")).not();
3314        let expected = or(col("c3").not(), col("c4").not());
3315        assert_eq!(simplify(expr), expected);
3316        // !(c3 OR c4) --> !c3 AND !c4
3317        let expr = or(col("c3"), col("c4")).not();
3318        let expected = and(col("c3").not(), col("c4").not());
3319        assert_eq!(simplify(expr), expected);
3320        // !(!c3) --> c3
3321        let expr = col("c3").not().not();
3322        let expected = col("c3");
3323        assert_eq!(simplify(expr), expected);
3324
3325        // Laws with bitwise operations
3326        // !(c3 & c4) --> !c3 | !c4
3327        let expr = -bitwise_and(col("c3"), col("c4"));
3328        let expected = bitwise_or(-col("c3"), -col("c4"));
3329        assert_eq!(simplify(expr), expected);
3330        // !(c3 | c4) --> !c3 & !c4
3331        let expr = -bitwise_or(col("c3"), col("c4"));
3332        let expected = bitwise_and(-col("c3"), -col("c4"));
3333        assert_eq!(simplify(expr), expected);
3334        // !(!c3) --> c3
3335        let expr = -(-col("c3"));
3336        let expected = col("c3");
3337        assert_eq!(simplify(expr), expected);
3338    }
3339
3340    #[test]
3341    fn test_simplify_null_and_false() {
3342        let expr = and(lit_bool_null(), lit(false));
3343        let expr_eq = lit(false);
3344
3345        assert_eq!(simplify(expr), expr_eq);
3346    }
3347
3348    #[test]
3349    fn test_simplify_divide_null_by_null() {
3350        let null = lit(ScalarValue::Int32(None));
3351        let expr_plus = null.clone() / null.clone();
3352        let expr_eq = null;
3353
3354        assert_eq!(simplify(expr_plus), expr_eq);
3355    }
3356
3357    #[test]
3358    fn test_simplify_simplify_arithmetic_expr() {
3359        let expr_plus = lit(1) + lit(1);
3360
3361        assert_eq!(simplify(expr_plus), lit(2));
3362    }
3363
3364    #[test]
3365    fn test_simplify_simplify_eq_expr() {
3366        let expr_eq = binary_expr(lit(1), Operator::Eq, lit(1));
3367
3368        assert_eq!(simplify(expr_eq), lit(true));
3369    }
3370
3371    #[test]
3372    fn test_simplify_regex() {
3373        // malformed regex
3374        assert_contains!(
3375            try_simplify(regex_match(col("c1"), lit("foo{")))
3376                .unwrap_err()
3377                .to_string(),
3378            "regex parse error"
3379        );
3380
3381        // unsupported cases
3382        assert_no_change(regex_match(col("c1"), lit("foo.*")));
3383        assert_no_change(regex_match(col("c1"), lit("(foo)")));
3384        assert_no_change(regex_match(col("c1"), lit("%")));
3385        assert_no_change(regex_match(col("c1"), lit("_")));
3386        assert_no_change(regex_match(col("c1"), lit("f%o")));
3387        assert_no_change(regex_match(col("c1"), lit("^f%o")));
3388        assert_no_change(regex_match(col("c1"), lit("f_o")));
3389
3390        // empty cases
3391        assert_change(
3392            regex_match(col("c1"), lit("")),
3393            if_not_null(col("c1"), true),
3394        );
3395        assert_change(
3396            regex_not_match(col("c1"), lit("")),
3397            if_not_null(col("c1"), false),
3398        );
3399        assert_change(
3400            regex_imatch(col("c1"), lit("")),
3401            if_not_null(col("c1"), true),
3402        );
3403        assert_change(
3404            regex_not_imatch(col("c1"), lit("")),
3405            if_not_null(col("c1"), false),
3406        );
3407
3408        // single character
3409        assert_change(regex_match(col("c1"), lit("x")), col("c1").like(lit("%x%")));
3410
3411        // single word
3412        assert_change(
3413            regex_match(col("c1"), lit("foo")),
3414            col("c1").like(lit("%foo%")),
3415        );
3416
3417        // regular expressions that match an exact literal
3418        assert_change(regex_match(col("c1"), lit("^$")), col("c1").eq(lit("")));
3419        assert_change(
3420            regex_not_match(col("c1"), lit("^$")),
3421            col("c1").not_eq(lit("")),
3422        );
3423        assert_change(
3424            regex_match(col("c1"), lit("^foo$")),
3425            col("c1").eq(lit("foo")),
3426        );
3427        assert_change(
3428            regex_not_match(col("c1"), lit("^foo$")),
3429            col("c1").not_eq(lit("foo")),
3430        );
3431
3432        // regular expressions that match exact captured literals
3433        assert_change(
3434            regex_match(col("c1"), lit("^(foo|bar)$")),
3435            col("c1").eq(lit("foo")).or(col("c1").eq(lit("bar"))),
3436        );
3437        assert_change(
3438            regex_not_match(col("c1"), lit("^(foo|bar)$")),
3439            col("c1")
3440                .not_eq(lit("foo"))
3441                .and(col("c1").not_eq(lit("bar"))),
3442        );
3443        assert_change(
3444            regex_match(col("c1"), lit("^(foo)$")),
3445            col("c1").eq(lit("foo")),
3446        );
3447        assert_change(
3448            regex_match(col("c1"), lit("^(foo|bar|baz)$")),
3449            ((col("c1").eq(lit("foo"))).or(col("c1").eq(lit("bar"))))
3450                .or(col("c1").eq(lit("baz"))),
3451        );
3452        assert_change(
3453            regex_match(col("c1"), lit("^(foo|bar|baz|qux)$")),
3454            col("c1")
3455                .in_list(vec![lit("foo"), lit("bar"), lit("baz"), lit("qux")], false),
3456        );
3457        assert_change(
3458            regex_match(col("c1"), lit("^(fo_o)$")),
3459            col("c1").eq(lit("fo_o")),
3460        );
3461        assert_change(
3462            regex_match(col("c1"), lit("^(fo_o)$")),
3463            col("c1").eq(lit("fo_o")),
3464        );
3465        assert_change(
3466            regex_match(col("c1"), lit("^(fo_o|ba_r)$")),
3467            col("c1").eq(lit("fo_o")).or(col("c1").eq(lit("ba_r"))),
3468        );
3469        assert_change(
3470            regex_not_match(col("c1"), lit("^(fo_o|ba_r)$")),
3471            col("c1")
3472                .not_eq(lit("fo_o"))
3473                .and(col("c1").not_eq(lit("ba_r"))),
3474        );
3475        assert_change(
3476            regex_match(col("c1"), lit("^(fo_o|ba_r|ba_z)$")),
3477            ((col("c1").eq(lit("fo_o"))).or(col("c1").eq(lit("ba_r"))))
3478                .or(col("c1").eq(lit("ba_z"))),
3479        );
3480        assert_change(
3481            regex_match(col("c1"), lit("^(fo_o|ba_r|baz|qu_x)$")),
3482            col("c1").in_list(
3483                vec![lit("fo_o"), lit("ba_r"), lit("baz"), lit("qu_x")],
3484                false,
3485            ),
3486        );
3487
3488        // regular expressions that mismatch captured literals
3489        assert_no_change(regex_match(col("c1"), lit("(foo|bar)")));
3490        assert_no_change(regex_match(col("c1"), lit("(foo|bar)*")));
3491        assert_no_change(regex_match(col("c1"), lit("(fo_o|b_ar)")));
3492        assert_no_change(regex_match(col("c1"), lit("(foo|ba_r)*")));
3493        assert_no_change(regex_match(col("c1"), lit("(fo_o|ba_r)*")));
3494        assert_no_change(regex_match(col("c1"), lit("^(foo|bar)*")));
3495        assert_no_change(regex_match(col("c1"), lit("^(foo)(bar)$")));
3496        assert_no_change(regex_match(col("c1"), lit("^")));
3497        assert_no_change(regex_match(col("c1"), lit("$")));
3498        assert_no_change(regex_match(col("c1"), lit("$^")));
3499        assert_no_change(regex_match(col("c1"), lit("$foo^")));
3500
3501        // regular expressions that match a partial literal
3502        assert_change(
3503            regex_match(col("c1"), lit("^foo")),
3504            col("c1").like(lit("foo%")),
3505        );
3506        assert_change(
3507            regex_match(col("c1"), lit("foo$")),
3508            col("c1").like(lit("%foo")),
3509        );
3510        assert_change(
3511            regex_match(col("c1"), lit("^foo|bar$")),
3512            col("c1").like(lit("foo%")).or(col("c1").like(lit("%bar"))),
3513        );
3514
3515        // OR-chain
3516        assert_change(
3517            regex_match(col("c1"), lit("foo|bar|baz")),
3518            col("c1")
3519                .like(lit("%foo%"))
3520                .or(col("c1").like(lit("%bar%")))
3521                .or(col("c1").like(lit("%baz%"))),
3522        );
3523        assert_change(
3524            regex_match(col("c1"), lit("foo|x|baz")),
3525            col("c1")
3526                .like(lit("%foo%"))
3527                .or(col("c1").like(lit("%x%")))
3528                .or(col("c1").like(lit("%baz%"))),
3529        );
3530        assert_change(
3531            regex_not_match(col("c1"), lit("foo|bar|baz")),
3532            col("c1")
3533                .not_like(lit("%foo%"))
3534                .and(col("c1").not_like(lit("%bar%")))
3535                .and(col("c1").not_like(lit("%baz%"))),
3536        );
3537        // both anchored expressions (translated to equality) and unanchored
3538        assert_change(
3539            regex_match(col("c1"), lit("foo|^x$|baz")),
3540            col("c1")
3541                .like(lit("%foo%"))
3542                .or(col("c1").eq(lit("x")))
3543                .or(col("c1").like(lit("%baz%"))),
3544        );
3545        assert_change(
3546            regex_not_match(col("c1"), lit("foo|^bar$|baz")),
3547            col("c1")
3548                .not_like(lit("%foo%"))
3549                .and(col("c1").not_eq(lit("bar")))
3550                .and(col("c1").not_like(lit("%baz%"))),
3551        );
3552        // Too many patterns (MAX_REGEX_ALTERNATIONS_EXPANSION)
3553        assert_no_change(regex_match(col("c1"), lit("foo|bar|baz|blarg|bozo|etc")));
3554    }
3555
3556    #[test]
3557    fn test_simplify_not_regex_match() {
3558        let pattern = || lit("foo.*");
3559
3560        // NOT (c1 ~ pattern)  --> c1 !~ pattern
3561        assert_eq!(
3562            simplify(regex_match(col("c1"), pattern()).not()),
3563            regex_not_match(col("c1"), pattern()),
3564        );
3565        // NOT (c1 !~ pattern) --> c1 ~ pattern
3566        assert_eq!(
3567            simplify(regex_not_match(col("c1"), pattern()).not()),
3568            regex_match(col("c1"), pattern()),
3569        );
3570        // NOT (c1 ~* pattern)  --> c1 !~* pattern
3571        assert_eq!(
3572            simplify(regex_imatch(col("c1"), pattern()).not()),
3573            regex_not_imatch(col("c1"), pattern()),
3574        );
3575        // NOT (c1 !~* pattern) --> c1 ~* pattern
3576        assert_eq!(
3577            simplify(regex_not_imatch(col("c1"), pattern()).not()),
3578            regex_imatch(col("c1"), pattern()),
3579        );
3580    }
3581
3582    #[track_caller]
3583    fn assert_no_change(expr: Expr) {
3584        let optimized = simplify(expr.clone());
3585        assert_eq!(expr, optimized);
3586    }
3587
3588    #[track_caller]
3589    fn assert_change(expr: Expr, expected: Expr) {
3590        let optimized = simplify(expr);
3591        assert_eq!(optimized, expected);
3592    }
3593
3594    fn regex_match(left: Expr, right: Expr) -> Expr {
3595        Expr::BinaryExpr(BinaryExpr {
3596            left: Box::new(left),
3597            op: Operator::RegexMatch,
3598            right: Box::new(right),
3599        })
3600    }
3601
3602    fn regex_not_match(left: Expr, right: Expr) -> Expr {
3603        Expr::BinaryExpr(BinaryExpr {
3604            left: Box::new(left),
3605            op: Operator::RegexNotMatch,
3606            right: Box::new(right),
3607        })
3608    }
3609
3610    fn regex_imatch(left: Expr, right: Expr) -> Expr {
3611        Expr::BinaryExpr(BinaryExpr {
3612            left: Box::new(left),
3613            op: Operator::RegexIMatch,
3614            right: Box::new(right),
3615        })
3616    }
3617
3618    fn regex_not_imatch(left: Expr, right: Expr) -> Expr {
3619        Expr::BinaryExpr(BinaryExpr {
3620            left: Box::new(left),
3621            op: Operator::RegexNotIMatch,
3622            right: Box::new(right),
3623        })
3624    }
3625
3626    // ------------------------------
3627    // ----- Simplifier tests -------
3628    // ------------------------------
3629
3630    fn try_simplify(expr: Expr) -> Result<Expr> {
3631        let schema = expr_test_schema();
3632        let simplifier =
3633            ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
3634        simplifier.simplify(expr)
3635    }
3636
3637    fn coerce(expr: Expr) -> Expr {
3638        let schema = expr_test_schema();
3639        let simplifier = ExprSimplifier::new(
3640            SimplifyContext::builder()
3641                .with_schema(Arc::clone(&schema))
3642                .build(),
3643        );
3644        simplifier.coerce(expr, schema.as_ref()).unwrap()
3645    }
3646
3647    fn simplify(expr: Expr) -> Expr {
3648        try_simplify(expr).unwrap()
3649    }
3650
3651    fn try_simplify_with_cycle_count(expr: Expr) -> Result<(Expr, u32)> {
3652        let schema = expr_test_schema();
3653        let simplifier =
3654            ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
3655        let (expr, count) = simplifier.simplify_with_cycle_count_transformed(expr)?;
3656        Ok((expr.data, count))
3657    }
3658
3659    fn simplify_with_cycle_count(expr: Expr) -> (Expr, u32) {
3660        try_simplify_with_cycle_count(expr).unwrap()
3661    }
3662
3663    fn simplify_with_guarantee(
3664        expr: Expr,
3665        guarantees: Vec<(Expr, NullableInterval)>,
3666    ) -> Expr {
3667        let schema = expr_test_schema();
3668        let simplifier =
3669            ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build())
3670                .with_guarantees(guarantees);
3671        simplifier.simplify(expr).unwrap()
3672    }
3673
3674    fn expr_test_schema() -> DFSchemaRef {
3675        static EXPR_TEST_SCHEMA: LazyLock<DFSchemaRef> = LazyLock::new(|| {
3676            Arc::new(
3677                DFSchema::from_unqualified_fields(
3678                    vec![
3679                        Field::new("c1", DataType::Utf8, true),
3680                        Field::new("c2", DataType::Boolean, true),
3681                        Field::new("c3", DataType::Int64, true),
3682                        Field::new("c4", DataType::UInt32, true),
3683                        Field::new("c1_non_null", DataType::Utf8, false),
3684                        Field::new("c2_non_null", DataType::Boolean, false),
3685                        Field::new("c3_non_null", DataType::Int64, false),
3686                        Field::new("c4_non_null", DataType::UInt32, false),
3687                        Field::new("c5", DataType::FixedSizeBinary(3), true),
3688                    ]
3689                    .into(),
3690                    HashMap::new(),
3691                )
3692                .unwrap(),
3693            )
3694        });
3695        Arc::clone(&EXPR_TEST_SCHEMA)
3696    }
3697
3698    #[test]
3699    fn simplify_expr_null_comparison() {
3700        // x = null is always null
3701        assert_eq!(
3702            simplify(lit(true).eq(lit(ScalarValue::Boolean(None)))),
3703            lit(ScalarValue::Boolean(None)),
3704        );
3705
3706        // null != null is always null
3707        assert_eq!(
3708            simplify(
3709                lit(ScalarValue::Boolean(None)).not_eq(lit(ScalarValue::Boolean(None)))
3710            ),
3711            lit(ScalarValue::Boolean(None)),
3712        );
3713
3714        // x != null is always null
3715        assert_eq!(
3716            simplify(col("c2").not_eq(lit(ScalarValue::Boolean(None)))),
3717            lit(ScalarValue::Boolean(None)),
3718        );
3719
3720        // null = x is always null
3721        assert_eq!(
3722            simplify(lit(ScalarValue::Boolean(None)).eq(col("c2"))),
3723            lit(ScalarValue::Boolean(None)),
3724        );
3725    }
3726
3727    #[test]
3728    fn simplify_expr_is_not_null() {
3729        assert_eq!(
3730            simplify(Expr::IsNotNull(Box::new(col("c1")))),
3731            Expr::IsNotNull(Box::new(col("c1")))
3732        );
3733
3734        // 'c1_non_null IS NOT NULL' is always true
3735        assert_eq!(
3736            simplify(Expr::IsNotNull(Box::new(col("c1_non_null")))),
3737            lit(true)
3738        );
3739    }
3740
3741    #[test]
3742    fn simplify_expr_is_null() {
3743        assert_eq!(
3744            simplify(Expr::IsNull(Box::new(col("c1")))),
3745            Expr::IsNull(Box::new(col("c1")))
3746        );
3747
3748        // 'c1_non_null IS NULL' is always false
3749        assert_eq!(
3750            simplify(Expr::IsNull(Box::new(col("c1_non_null")))),
3751            lit(false)
3752        );
3753    }
3754
3755    #[test]
3756    fn simplify_expr_is_unknown() {
3757        assert_eq!(simplify(col("c2").is_unknown()), col("c2").is_unknown(),);
3758
3759        // 'c2_non_null is unknown' is always false
3760        assert_eq!(simplify(col("c2_non_null").is_unknown()), lit(false));
3761    }
3762
3763    #[test]
3764    fn simplify_expr_is_not_known() {
3765        assert_eq!(
3766            simplify(col("c2").is_not_unknown()),
3767            col("c2").is_not_unknown()
3768        );
3769
3770        // 'c2_non_null is not unknown' is always true
3771        assert_eq!(simplify(col("c2_non_null").is_not_unknown()), lit(true));
3772    }
3773
3774    #[test]
3775    fn simplify_expr_eq() {
3776        let schema = expr_test_schema();
3777        assert_eq!(col("c2").get_type(&schema).unwrap(), DataType::Boolean);
3778
3779        // true = true -> true
3780        assert_eq!(simplify(lit(true).eq(lit(true))), lit(true));
3781
3782        // true = false -> false
3783        assert_eq!(simplify(lit(true).eq(lit(false))), lit(false),);
3784
3785        // c2 = true -> c2
3786        assert_eq!(simplify(col("c2").eq(lit(true))), col("c2"));
3787
3788        // c2 = false => !c2
3789        assert_eq!(simplify(col("c2").eq(lit(false))), col("c2").not(),);
3790    }
3791
3792    #[test]
3793    fn simplify_expr_eq_skip_nonboolean_type() {
3794        let schema = expr_test_schema();
3795
3796        // When one of the operand is not of boolean type, folding the
3797        // other boolean constant will change return type of
3798        // expression to non-boolean.
3799        //
3800        // Make sure c1 column to be used in tests is not boolean type
3801        assert_eq!(col("c1").get_type(&schema).unwrap(), DataType::Utf8);
3802
3803        // don't fold c1 = foo
3804        assert_eq!(simplify(col("c1").eq(lit("foo"))), col("c1").eq(lit("foo")),);
3805    }
3806
3807    #[test]
3808    fn simplify_expr_not_eq() {
3809        let schema = expr_test_schema();
3810
3811        assert_eq!(col("c2").get_type(&schema).unwrap(), DataType::Boolean);
3812
3813        // c2 != true -> !c2
3814        assert_eq!(simplify(col("c2").not_eq(lit(true))), col("c2").not(),);
3815
3816        // c2 != false -> c2
3817        assert_eq!(simplify(col("c2").not_eq(lit(false))), col("c2"),);
3818
3819        // test constant
3820        assert_eq!(simplify(lit(true).not_eq(lit(true))), lit(false),);
3821
3822        assert_eq!(simplify(lit(true).not_eq(lit(false))), lit(true),);
3823    }
3824
3825    #[test]
3826    fn simplify_expr_not_eq_skip_nonboolean_type() {
3827        let schema = expr_test_schema();
3828
3829        // when one of the operand is not of boolean type, folding the
3830        // other boolean constant will change return type of
3831        // expression to non-boolean.
3832        assert_eq!(col("c1").get_type(&schema).unwrap(), DataType::Utf8);
3833
3834        assert_eq!(
3835            simplify(col("c1").not_eq(lit("foo"))),
3836            col("c1").not_eq(lit("foo")),
3837        );
3838    }
3839
3840    #[test]
3841    fn simplify_literal_case_equality() {
3842        // CASE WHEN c2 != false THEN "ok" ELSE "not_ok"
3843        let simple_case = Expr::Case(Case::new(
3844            None,
3845            vec![(
3846                Box::new(col("c2_non_null").not_eq(lit(false))),
3847                Box::new(lit("ok")),
3848            )],
3849            Some(Box::new(lit("not_ok"))),
3850        ));
3851
3852        // CASE WHEN c2 != false THEN "ok" ELSE "not_ok" == "ok"
3853        // -->
3854        // CASE WHEN c2 != false THEN "ok" == "ok" ELSE "not_ok" == "ok"
3855        // -->
3856        // CASE WHEN c2 != false THEN true ELSE false
3857        // -->
3858        // c2
3859        assert_eq!(
3860            simplify(binary_expr(simple_case.clone(), Operator::Eq, lit("ok"),)),
3861            col("c2_non_null"),
3862        );
3863
3864        // CASE WHEN c2 != false THEN "ok" ELSE "not_ok" != "ok"
3865        // -->
3866        // NOT(CASE WHEN c2 != false THEN "ok" == "ok" ELSE "not_ok" == "ok")
3867        // -->
3868        // NOT(CASE WHEN c2 != false THEN true ELSE false)
3869        // -->
3870        // NOT(c2)
3871        assert_eq!(
3872            simplify(binary_expr(simple_case, Operator::NotEq, lit("ok"),)),
3873            not(col("c2_non_null")),
3874        );
3875
3876        let complex_case = Expr::Case(Case::new(
3877            None,
3878            vec![
3879                (
3880                    Box::new(col("c1").eq(lit("inboxed"))),
3881                    Box::new(lit("pending")),
3882                ),
3883                (
3884                    Box::new(col("c1").eq(lit("scheduled"))),
3885                    Box::new(lit("pending")),
3886                ),
3887                (
3888                    Box::new(col("c1").eq(lit("completed"))),
3889                    Box::new(lit("completed")),
3890                ),
3891                (
3892                    Box::new(col("c1").eq(lit("paused"))),
3893                    Box::new(lit("paused")),
3894                ),
3895                (Box::new(col("c2")), Box::new(lit("running"))),
3896                (
3897                    Box::new(col("c1").eq(lit("invoked")).and(col("c3").gt(lit(0)))),
3898                    Box::new(lit("backing-off")),
3899                ),
3900            ],
3901            Some(Box::new(lit("ready"))),
3902        ));
3903
3904        assert_eq!(
3905            simplify(binary_expr(
3906                complex_case.clone(),
3907                Operator::Eq,
3908                lit("completed"),
3909            )),
3910            not_distinct_from(col("c1").eq(lit("completed")), lit(true)).and(
3911                distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3912                    .and(distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3913            )
3914        );
3915
3916        assert_eq!(
3917            simplify(binary_expr(
3918                complex_case.clone(),
3919                Operator::NotEq,
3920                lit("completed"),
3921            )),
3922            distinct_from(col("c1").eq(lit("completed")), lit(true))
3923                .or(not_distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3924                    .or(not_distinct_from(col("c1").eq(lit("scheduled")), lit(true))))
3925        );
3926
3927        assert_eq!(
3928            simplify(binary_expr(
3929                complex_case.clone(),
3930                Operator::Eq,
3931                lit("running"),
3932            )),
3933            not_distinct_from(col("c2"), lit(true)).and(
3934                distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3935                    .and(distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3936                    .and(distinct_from(col("c1").eq(lit("completed")), lit(true)))
3937                    .and(distinct_from(col("c1").eq(lit("paused")), lit(true)))
3938            )
3939        );
3940
3941        assert_eq!(
3942            simplify(binary_expr(
3943                complex_case.clone(),
3944                Operator::Eq,
3945                lit("ready"),
3946            )),
3947            distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3948                .and(distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3949                .and(distinct_from(col("c1").eq(lit("completed")), lit(true)))
3950                .and(distinct_from(col("c1").eq(lit("paused")), lit(true)))
3951                .and(distinct_from(col("c2"), lit(true)))
3952                .and(distinct_from(
3953                    col("c1").eq(lit("invoked")).and(col("c3").gt(lit(0))),
3954                    lit(true)
3955                ))
3956        );
3957
3958        assert_eq!(
3959            simplify(binary_expr(
3960                complex_case.clone(),
3961                Operator::NotEq,
3962                lit("ready"),
3963            )),
3964            not_distinct_from(col("c1").eq(lit("inboxed")), lit(true))
3965                .or(not_distinct_from(col("c1").eq(lit("scheduled")), lit(true)))
3966                .or(not_distinct_from(col("c1").eq(lit("completed")), lit(true)))
3967                .or(not_distinct_from(col("c1").eq(lit("paused")), lit(true)))
3968                .or(not_distinct_from(col("c2"), lit(true)))
3969                .or(not_distinct_from(
3970                    col("c1").eq(lit("invoked")).and(col("c3").gt(lit(0))),
3971                    lit(true)
3972                ))
3973        );
3974    }
3975
3976    #[test]
3977    fn simplify_expr_case_when_then_else() {
3978        // CASE WHEN c2 != false THEN "ok" == "not_ok" ELSE c2 == true
3979        // -->
3980        // CASE WHEN c2 THEN false ELSE c2
3981        // -->
3982        // false
3983        assert_eq!(
3984            simplify(Expr::Case(Case::new(
3985                None,
3986                vec![(
3987                    Box::new(col("c2_non_null").not_eq(lit(false))),
3988                    Box::new(lit("ok").eq(lit("not_ok"))),
3989                )],
3990                Some(Box::new(col("c2_non_null").eq(lit(true)))),
3991            ))),
3992            lit(false) // #1716
3993        );
3994
3995        // CASE WHEN c2 != false THEN "ok" == "ok" ELSE c2
3996        // -->
3997        // CASE WHEN c2 THEN true ELSE c2
3998        // -->
3999        // c2
4000        //
4001        // Need to call simplify 2x due to
4002        // https://github.com/apache/datafusion/issues/1160
4003        assert_eq!(
4004            simplify(simplify(Expr::Case(Case::new(
4005                None,
4006                vec![(
4007                    Box::new(col("c2_non_null").not_eq(lit(false))),
4008                    Box::new(lit("ok").eq(lit("ok"))),
4009                )],
4010                Some(Box::new(col("c2_non_null").eq(lit(true)))),
4011            )))),
4012            col("c2_non_null")
4013        );
4014
4015        // CASE WHEN ISNULL(c2) THEN true ELSE c2
4016        // -->
4017        // ISNULL(c2) OR c2
4018        //
4019        // Need to call simplify 2x due to
4020        // https://github.com/apache/datafusion/issues/1160
4021        assert_eq!(
4022            simplify(simplify(Expr::Case(Case::new(
4023                None,
4024                vec![(Box::new(col("c2").is_null()), Box::new(lit(true)),)],
4025                Some(Box::new(col("c2"))),
4026            )))),
4027            col("c2")
4028                .is_null()
4029                .or(col("c2").is_not_null().and(col("c2")))
4030        );
4031
4032        // CASE WHEN c1 then true WHEN c2 then false ELSE true
4033        // --> c1 OR (NOT(c1) AND c2 AND FALSE) OR (NOT(c1 OR c2) AND TRUE)
4034        // --> c1 OR (NOT(c1) AND NOT(c2))
4035        // --> c1 OR NOT(c2)
4036        //
4037        // Need to call simplify 2x due to
4038        // https://github.com/apache/datafusion/issues/1160
4039        assert_eq!(
4040            simplify(simplify(Expr::Case(Case::new(
4041                None,
4042                vec![
4043                    (Box::new(col("c1_non_null")), Box::new(lit(true)),),
4044                    (Box::new(col("c2_non_null")), Box::new(lit(false)),),
4045                ],
4046                Some(Box::new(lit(true))),
4047            )))),
4048            col("c1_non_null").or(col("c1_non_null").not().and(col("c2_non_null").not()))
4049        );
4050
4051        // CASE WHEN c1 then true WHEN c2 then true ELSE false
4052        // --> c1 OR (NOT(c1) AND c2 AND TRUE) OR (NOT(c1 OR c2) AND FALSE)
4053        // --> c1 OR (NOT(c1) AND c2)
4054        // --> c1 OR c2
4055        //
4056        // Need to call simplify 2x due to
4057        // https://github.com/apache/datafusion/issues/1160
4058        assert_eq!(
4059            simplify(simplify(Expr::Case(Case::new(
4060                None,
4061                vec![
4062                    (Box::new(col("c1_non_null")), Box::new(lit(true)),),
4063                    (Box::new(col("c2_non_null")), Box::new(lit(false)),),
4064                ],
4065                Some(Box::new(lit(true))),
4066            )))),
4067            col("c1_non_null").or(col("c1_non_null").not().and(col("c2_non_null").not()))
4068        );
4069
4070        // CASE WHEN c > 0 THEN true END AS c1
4071        assert_eq!(
4072            simplify(simplify(Expr::Case(Case::new(
4073                None,
4074                vec![(Box::new(col("c3").gt(lit(0_i64))), Box::new(lit(true)))],
4075                None,
4076            )))),
4077            not_distinct_from(col("c3").gt(lit(0_i64)), lit(true)).or(distinct_from(
4078                col("c3").gt(lit(0_i64)),
4079                lit(true)
4080            )
4081            .and(lit_bool_null()))
4082        );
4083
4084        // CASE WHEN c > 0 THEN true ELSE false END AS c1
4085        assert_eq!(
4086            simplify(simplify(Expr::Case(Case::new(
4087                None,
4088                vec![(Box::new(col("c3").gt(lit(0_i64))), Box::new(lit(true)))],
4089                Some(Box::new(lit(false))),
4090            )))),
4091            not_distinct_from(col("c3").gt(lit(0_i64)), lit(true))
4092        );
4093    }
4094
4095    #[test]
4096    fn simplify_expr_case_when_first_true() {
4097        // CASE WHEN true THEN 1 ELSE c1 END --> 1
4098        assert_eq!(
4099            simplify(Expr::Case(Case::new(
4100                None,
4101                vec![(Box::new(lit(true)), Box::new(lit(1)),)],
4102                Some(Box::new(col("c1"))),
4103            ))),
4104            lit(1)
4105        );
4106
4107        // CASE WHEN true THEN col('a') ELSE col('b') END --> col('a')
4108        assert_eq!(
4109            simplify(Expr::Case(Case::new(
4110                None,
4111                vec![(Box::new(lit(true)), Box::new(lit("a")),)],
4112                Some(Box::new(lit("b"))),
4113            ))),
4114            lit("a")
4115        );
4116
4117        // CASE WHEN true THEN col('a') WHEN col('x') > 5 THEN col('b') ELSE col('c') END --> col('a')
4118        assert_eq!(
4119            simplify(Expr::Case(Case::new(
4120                None,
4121                vec![
4122                    (Box::new(lit(true)), Box::new(lit("a"))),
4123                    (Box::new(lit("x").gt(lit(5))), Box::new(lit("b"))),
4124                ],
4125                Some(Box::new(lit("c"))),
4126            ))),
4127            lit("a")
4128        );
4129
4130        // CASE WHEN true THEN col('a') END --> col('a') (no else clause)
4131        assert_eq!(
4132            simplify(Expr::Case(Case::new(
4133                None,
4134                vec![(Box::new(lit(true)), Box::new(lit("a")),)],
4135                None,
4136            ))),
4137            lit("a")
4138        );
4139
4140        // Negative test: CASE WHEN c2 THEN 1 ELSE 2 END should not be simplified
4141        let expr = Expr::Case(Case::new(
4142            None,
4143            vec![(Box::new(col("c2")), Box::new(lit(1)))],
4144            Some(Box::new(lit(2))),
4145        ));
4146        assert_eq!(simplify(expr.clone()), expr);
4147
4148        // Negative test: CASE WHEN false THEN 1 ELSE 2 END should not use this rule
4149        let expr = Expr::Case(Case::new(
4150            None,
4151            vec![(Box::new(lit(false)), Box::new(lit(1)))],
4152            Some(Box::new(lit(2))),
4153        ));
4154        assert_ne!(simplify(expr), lit(1));
4155
4156        // Negative test: CASE WHEN col('c1') > 5 THEN 1 ELSE 2 END should not be simplified
4157        let expr = Expr::Case(Case::new(
4158            None,
4159            vec![(Box::new(col("c1").gt(lit(5))), Box::new(lit(1)))],
4160            Some(Box::new(lit(2))),
4161        ));
4162        assert_eq!(simplify(expr.clone()), expr);
4163    }
4164
4165    #[test]
4166    fn simplify_expr_case_when_any_true() {
4167        // CASE WHEN c3 > 0 THEN 'a' WHEN true THEN 'b' ELSE 'c' END --> CASE WHEN c3 > 0 THEN 'a' ELSE 'b' END
4168        assert_eq!(
4169            simplify(Expr::Case(Case::new(
4170                None,
4171                vec![
4172                    (Box::new(col("c3").gt(lit(0))), Box::new(lit("a"))),
4173                    (Box::new(lit(true)), Box::new(lit("b"))),
4174                ],
4175                Some(Box::new(lit("c"))),
4176            ))),
4177            Expr::Case(Case::new(
4178                None,
4179                vec![(Box::new(col("c3").gt(lit(0))), Box::new(lit("a")))],
4180                Some(Box::new(lit("b"))),
4181            ))
4182        );
4183
4184        // CASE WHEN c3 > 0 THEN 'a' WHEN c4 < 0 THEN 'b' WHEN true THEN 'c' WHEN c3 = 0 THEN 'd' ELSE 'e' END
4185        // --> CASE WHEN c3 > 0 THEN 'a' WHEN c4 < 0 THEN 'b' ELSE 'c' END
4186        assert_eq!(
4187            simplify(Expr::Case(Case::new(
4188                None,
4189                vec![
4190                    (Box::new(col("c3").gt(lit(0))), Box::new(lit("a"))),
4191                    (Box::new(col("c4").lt(lit(0))), Box::new(lit("b"))),
4192                    (Box::new(lit(true)), Box::new(lit("c"))),
4193                    (Box::new(col("c3").eq(lit(0))), Box::new(lit("d"))),
4194                ],
4195                Some(Box::new(lit("e"))),
4196            ))),
4197            Expr::Case(Case::new(
4198                None,
4199                vec![
4200                    (Box::new(col("c3").gt(lit(0))), Box::new(lit("a"))),
4201                    (Box::new(col("c4").lt(lit(0))), Box::new(lit("b"))),
4202                ],
4203                Some(Box::new(lit("c"))),
4204            ))
4205        );
4206
4207        // CASE WHEN c3 > 0 THEN 1 WHEN c4 < 0 THEN 2 WHEN true THEN 3 END (no else)
4208        // --> CASE WHEN c3 > 0 THEN 1 WHEN c4 < 0 THEN 2 ELSE 3 END
4209        assert_eq!(
4210            simplify(Expr::Case(Case::new(
4211                None,
4212                vec![
4213                    (Box::new(col("c3").gt(lit(0))), Box::new(lit(1))),
4214                    (Box::new(col("c4").lt(lit(0))), Box::new(lit(2))),
4215                    (Box::new(lit(true)), Box::new(lit(3))),
4216                ],
4217                None,
4218            ))),
4219            Expr::Case(Case::new(
4220                None,
4221                vec![
4222                    (Box::new(col("c3").gt(lit(0))), Box::new(lit(1))),
4223                    (Box::new(col("c4").lt(lit(0))), Box::new(lit(2))),
4224                ],
4225                Some(Box::new(lit(3))),
4226            ))
4227        );
4228
4229        // Negative test: CASE WHEN c3 > 0 THEN c3 WHEN c4 < 0 THEN 2 ELSE 3 END should not be simplified
4230        let expr = Expr::Case(Case::new(
4231            None,
4232            vec![
4233                (Box::new(col("c3").gt(lit(0))), Box::new(col("c3"))),
4234                (Box::new(col("c4").lt(lit(0))), Box::new(lit(2))),
4235            ],
4236            Some(Box::new(lit(3))),
4237        ));
4238        assert_eq!(simplify(expr.clone()), expr);
4239    }
4240
4241    #[test]
4242    fn simplify_expr_case_when_any_false() {
4243        // CASE WHEN false THEN 'a' END --> NULL
4244        assert_eq!(
4245            simplify(Expr::Case(Case::new(
4246                None,
4247                vec![(Box::new(lit(false)), Box::new(lit("a")))],
4248                None,
4249            ))),
4250            Expr::Literal(ScalarValue::Utf8(None), None)
4251        );
4252
4253        // CASE WHEN false THEN 2 ELSE 1 END --> 1
4254        assert_eq!(
4255            simplify(Expr::Case(Case::new(
4256                None,
4257                vec![(Box::new(lit(false)), Box::new(lit(2)))],
4258                Some(Box::new(lit(1))),
4259            ))),
4260            lit(1),
4261        );
4262
4263        // CASE WHEN c3 < 10 THEN 'b' WHEN false then c3 ELSE c4 END --> CASE WHEN c3 < 10 THEN b ELSE c4 END
4264        assert_eq!(
4265            simplify(Expr::Case(Case::new(
4266                None,
4267                vec![
4268                    (Box::new(col("c3").lt(lit(10))), Box::new(lit("b"))),
4269                    (Box::new(lit(false)), Box::new(col("c3"))),
4270                ],
4271                Some(Box::new(col("c4"))),
4272            ))),
4273            Expr::Case(Case::new(
4274                None,
4275                vec![(Box::new(col("c3").lt(lit(10))), Box::new(lit("b")))],
4276                Some(Box::new(col("c4"))),
4277            ))
4278        );
4279
4280        // Negative test: CASE WHEN c3 = 4 THEN 1 ELSE 2 END should not be simplified
4281        let expr = Expr::Case(Case::new(
4282            None,
4283            vec![(Box::new(col("c3").eq(lit(4))), Box::new(lit(1)))],
4284            Some(Box::new(lit(2))),
4285        ));
4286        assert_eq!(simplify(expr.clone()), expr);
4287    }
4288
4289    fn distinct_from(left: impl Into<Expr>, right: impl Into<Expr>) -> Expr {
4290        Expr::BinaryExpr(BinaryExpr {
4291            left: Box::new(left.into()),
4292            op: Operator::IsDistinctFrom,
4293            right: Box::new(right.into()),
4294        })
4295    }
4296
4297    fn not_distinct_from(left: impl Into<Expr>, right: impl Into<Expr>) -> Expr {
4298        Expr::BinaryExpr(BinaryExpr {
4299            left: Box::new(left.into()),
4300            op: Operator::IsNotDistinctFrom,
4301            right: Box::new(right.into()),
4302        })
4303    }
4304
4305    #[test]
4306    fn simplify_expr_bool_or() {
4307        // col || true is always true
4308        assert_eq!(simplify(col("c2").or(lit(true))), lit(true),);
4309
4310        // col || false is always col
4311        assert_eq!(simplify(col("c2").or(lit(false))), col("c2"),);
4312
4313        // true || null is always true
4314        assert_eq!(simplify(lit(true).or(lit_bool_null())), lit(true),);
4315
4316        // null || true is always true
4317        assert_eq!(simplify(lit_bool_null().or(lit(true))), lit(true),);
4318
4319        // false || null is always null
4320        assert_eq!(simplify(lit(false).or(lit_bool_null())), lit_bool_null(),);
4321
4322        // null || false is always null
4323        assert_eq!(simplify(lit_bool_null().or(lit(false))), lit_bool_null(),);
4324
4325        // ( c1 BETWEEN Int32(0) AND Int32(10) ) OR Boolean(NULL)
4326        // it can be either NULL or  TRUE depending on the value of `c1 BETWEEN Int32(0) AND Int32(10)`
4327        // and should not be rewritten
4328        let expr = col("c1").between(lit(0), lit(10));
4329        let expr = expr.or(lit_bool_null());
4330        let result = simplify(expr);
4331
4332        let expected_expr = or(
4333            and(col("c1").gt_eq(lit(0)), col("c1").lt_eq(lit(10))),
4334            lit_bool_null(),
4335        );
4336        assert_eq!(expected_expr, result);
4337    }
4338
4339    #[test]
4340    fn simplify_inlist() {
4341        assert_eq!(simplify(in_list(col("c1"), vec![], false)), lit(false));
4342        assert_eq!(simplify(in_list(col("c1"), vec![], true)), lit(true));
4343
4344        // null in (...)  --> null
4345        assert_eq!(
4346            simplify(in_list(lit_bool_null(), vec![col("c1"), lit(1)], false)),
4347            lit_bool_null()
4348        );
4349
4350        // null not in (...)  --> null
4351        assert_eq!(
4352            simplify(in_list(lit_bool_null(), vec![col("c1"), lit(1)], true)),
4353            lit_bool_null()
4354        );
4355
4356        assert_eq!(
4357            simplify(in_list(col("c1"), vec![lit(1)], false)),
4358            col("c1").eq(lit(1))
4359        );
4360        assert_eq!(
4361            simplify(in_list(col("c1"), vec![lit(1)], true)),
4362            col("c1").not_eq(lit(1))
4363        );
4364
4365        // more complex expressions can be simplified if list contains
4366        // one element only
4367        assert_eq!(
4368            simplify(in_list(col("c1") * lit(10), vec![lit(2)], false)),
4369            (col("c1") * lit(10)).eq(lit(2))
4370        );
4371
4372        assert_eq!(
4373            simplify(in_list(col("c1"), vec![lit(1), lit(2)], false)),
4374            col("c1").eq(lit(1)).or(col("c1").eq(lit(2)))
4375        );
4376        assert_eq!(
4377            simplify(in_list(col("c1"), vec![lit(1), lit(2)], true)),
4378            col("c1").not_eq(lit(1)).and(col("c1").not_eq(lit(2)))
4379        );
4380
4381        let subquery = Arc::new(test_table_scan_with_name("test").unwrap());
4382        assert_eq!(
4383            simplify(in_list(
4384                col("c1"),
4385                vec![scalar_subquery(Arc::clone(&subquery))],
4386                false
4387            )),
4388            in_subquery(col("c1"), Arc::clone(&subquery))
4389        );
4390        assert_eq!(
4391            simplify(in_list(
4392                col("c1"),
4393                vec![scalar_subquery(Arc::clone(&subquery))],
4394                true
4395            )),
4396            not_in_subquery(col("c1"), subquery)
4397        );
4398
4399        let subquery1 =
4400            scalar_subquery(Arc::new(test_table_scan_with_name("test1").unwrap()));
4401        let subquery2 =
4402            scalar_subquery(Arc::new(test_table_scan_with_name("test2").unwrap()));
4403
4404        // c1 NOT IN (<subquery1>, <subquery2>) -> c1 != <subquery1> AND c1 != <subquery2>
4405        assert_eq!(
4406            simplify(in_list(
4407                col("c1"),
4408                vec![subquery1.clone(), subquery2.clone()],
4409                true
4410            )),
4411            col("c1")
4412                .not_eq(subquery1.clone())
4413                .and(col("c1").not_eq(subquery2.clone()))
4414        );
4415
4416        // c1 IN (<subquery1>, <subquery2>) -> c1 == <subquery1> OR c1 == <subquery2>
4417        assert_eq!(
4418            simplify(in_list(
4419                col("c1"),
4420                vec![subquery1.clone(), subquery2.clone()],
4421                false
4422            )),
4423            col("c1").eq(subquery1).or(col("c1").eq(subquery2))
4424        );
4425
4426        // 1. c1 IN (1,2,3,4) AND c1 IN (5,6,7,8) -> false
4427        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).and(
4428            in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], false),
4429        );
4430        assert_eq!(simplify(expr), lit(false));
4431
4432        // 2. c1 IN (1,2,3,4) AND c1 IN (4,5,6,7) -> c1 = 4
4433        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).and(
4434            in_list(col("c1"), vec![lit(4), lit(5), lit(6), lit(7)], false),
4435        );
4436        assert_eq!(simplify(expr), col("c1").eq(lit(4)));
4437
4438        // 3. c1 NOT IN (1, 2, 3, 4) OR c1 NOT IN (5, 6, 7, 8) -> true
4439        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).or(
4440            in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], true),
4441        );
4442        assert_eq!(simplify(expr), lit(true));
4443
4444        // 3.5 c1 NOT IN (1, 2, 3, 4) OR c1 NOT IN (4, 5, 6, 7) -> c1 != 4 (4 overlaps)
4445        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).or(
4446            in_list(col("c1"), vec![lit(4), lit(5), lit(6), lit(7)], true),
4447        );
4448        assert_eq!(simplify(expr), col("c1").not_eq(lit(4)));
4449
4450        // 4. c1 NOT IN (1,2,3,4) AND c1 NOT IN (4,5,6,7) -> c1 NOT IN (1,2,3,4,5,6,7)
4451        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).and(
4452            in_list(col("c1"), vec![lit(4), lit(5), lit(6), lit(7)], true),
4453        );
4454        assert_eq!(
4455            simplify(expr),
4456            in_list(
4457                col("c1"),
4458                vec![lit(1), lit(2), lit(3), lit(4), lit(5), lit(6), lit(7)],
4459                true
4460            )
4461        );
4462
4463        // 5. c1 IN (1,2,3,4) OR c1 IN (2,3,4,5) -> c1 IN (1,2,3,4,5)
4464        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).or(
4465            in_list(col("c1"), vec![lit(2), lit(3), lit(4), lit(5)], false),
4466        );
4467        assert_eq!(
4468            simplify(expr),
4469            in_list(
4470                col("c1"),
4471                vec![lit(1), lit(2), lit(3), lit(4), lit(5)],
4472                false
4473            )
4474        );
4475
4476        // 6. c1 IN (1,2,3) AND c1 NOT INT (1,2,3,4,5) -> false
4477        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3)], false).and(in_list(
4478            col("c1"),
4479            vec![lit(1), lit(2), lit(3), lit(4), lit(5)],
4480            true,
4481        ));
4482        assert_eq!(simplify(expr), lit(false));
4483
4484        // 7. c1 NOT IN (1,2,3,4) AND c1 IN (1,2,3,4,5) -> c1 = 5
4485        let expr =
4486            in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).and(in_list(
4487                col("c1"),
4488                vec![lit(1), lit(2), lit(3), lit(4), lit(5)],
4489                false,
4490            ));
4491        assert_eq!(simplify(expr), col("c1").eq(lit(5)));
4492
4493        // 8. c1 IN (1,2,3,4) AND c1 NOT IN (5,6,7,8) -> c1 IN (1,2,3,4)
4494        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false).and(
4495            in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], true),
4496        );
4497        assert_eq!(
4498            simplify(expr),
4499            in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], false)
4500        );
4501
4502        // inlist with more than two expressions
4503        // c1 IN (1,2,3,4,5,6) AND c1 IN (1,3,5,6) AND c1 IN (3,6) -> c1 = 3 OR c1 = 6
4504        let expr = in_list(
4505            col("c1"),
4506            vec![lit(1), lit(2), lit(3), lit(4), lit(5), lit(6)],
4507            false,
4508        )
4509        .and(in_list(
4510            col("c1"),
4511            vec![lit(1), lit(3), lit(5), lit(6)],
4512            false,
4513        ))
4514        .and(in_list(col("c1"), vec![lit(3), lit(6)], false));
4515        assert_eq!(
4516            simplify(expr),
4517            col("c1").eq(lit(3)).or(col("c1").eq(lit(6)))
4518        );
4519
4520        // c1 NOT IN (1,2,3,4) AND c1 IN (5,6,7,8) AND c1 NOT IN (3,4,5,6) AND c1 IN (8,9,10) -> c1 = 8
4521        let expr = in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).and(
4522            in_list(col("c1"), vec![lit(5), lit(6), lit(7), lit(8)], false)
4523                .and(in_list(
4524                    col("c1"),
4525                    vec![lit(3), lit(4), lit(5), lit(6)],
4526                    true,
4527                ))
4528                .and(in_list(col("c1"), vec![lit(8), lit(9), lit(10)], false)),
4529        );
4530        assert_eq!(simplify(expr), col("c1").eq(lit(8)));
4531
4532        // Contains non-InList expression
4533        // c1 NOT IN (1,2,3,4) OR c1 != 5 OR c1 NOT IN (6,7,8,9) -> c1 NOT IN (1,2,3,4) OR c1 != 5 OR c1 NOT IN (6,7,8,9)
4534        let expr =
4535            in_list(col("c1"), vec![lit(1), lit(2), lit(3), lit(4)], true).or(col("c1")
4536                .not_eq(lit(5))
4537                .or(in_list(
4538                    col("c1"),
4539                    vec![lit(6), lit(7), lit(8), lit(9)],
4540                    true,
4541                )));
4542        // TODO: Further simplify this expression
4543        // https://github.com/apache/datafusion/issues/8970
4544        // assert_eq!(simplify(expr.clone()), lit(true));
4545        assert_eq!(simplify(expr.clone()), expr);
4546    }
4547
4548    #[test]
4549    fn simplify_null_in_empty_inlist() {
4550        // `NULL::boolean IN ()` == `NULL::boolean IN (SELECT foo FROM empty)` == false
4551        let expr = in_list(lit_bool_null(), vec![], false);
4552        assert_eq!(simplify(expr), lit(false));
4553
4554        // `NULL::boolean NOT IN ()` == `NULL::boolean NOT IN (SELECT foo FROM empty)` == true
4555        let expr = in_list(lit_bool_null(), vec![], true);
4556        assert_eq!(simplify(expr), lit(true));
4557
4558        // `NULL IN ()` == `NULL IN (SELECT foo FROM empty)` == false
4559        let null_null = || Expr::Literal(ScalarValue::Null, None);
4560        let expr = in_list(null_null(), vec![], false);
4561        assert_eq!(simplify(expr), lit(false));
4562
4563        // `NULL NOT IN ()` == `NULL NOT IN (SELECT foo FROM empty)` == true
4564        let expr = in_list(null_null(), vec![], true);
4565        assert_eq!(simplify(expr), lit(true));
4566    }
4567
4568    #[test]
4569    fn just_simplifier_simplify_null_in_empty_inlist() {
4570        let simplify = |expr: Expr| -> Expr {
4571            let schema = expr_test_schema();
4572            let info = SimplifyContext::builder().with_schema(schema).build();
4573            let simplifier = &mut Simplifier::new(&info);
4574            expr.rewrite(simplifier)
4575                .expect("Failed to simplify expression")
4576                .data
4577        };
4578
4579        // `NULL::boolean IN ()` == `NULL::boolean IN (SELECT foo FROM empty)` == false
4580        let expr = in_list(lit_bool_null(), vec![], false);
4581        assert_eq!(simplify(expr), lit(false));
4582
4583        // `NULL::boolean NOT IN ()` == `NULL::boolean NOT IN (SELECT foo FROM empty)` == true
4584        let expr = in_list(lit_bool_null(), vec![], true);
4585        assert_eq!(simplify(expr), lit(true));
4586
4587        // `NULL IN ()` == `NULL IN (SELECT foo FROM empty)` == false
4588        let null_null = || Expr::Literal(ScalarValue::Null, None);
4589        let expr = in_list(null_null(), vec![], false);
4590        assert_eq!(simplify(expr), lit(false));
4591
4592        // `NULL NOT IN ()` == `NULL NOT IN (SELECT foo FROM empty)` == true
4593        let expr = in_list(null_null(), vec![], true);
4594        assert_eq!(simplify(expr), lit(true));
4595    }
4596
4597    #[test]
4598    fn simplify_large_or() {
4599        let expr = (0..5)
4600            .map(|i| col("c1").eq(lit(i)))
4601            .fold(lit(false), |acc, e| acc.or(e));
4602        assert_eq!(
4603            simplify(expr),
4604            in_list(col("c1"), (0..5).map(lit).collect(), false),
4605        );
4606    }
4607
4608    #[test]
4609    fn simplify_expr_bool_and() {
4610        // col & true is always col
4611        assert_eq!(simplify(col("c2").and(lit(true))), col("c2"),);
4612        // col & false is always false
4613        assert_eq!(simplify(col("c2").and(lit(false))), lit(false),);
4614
4615        // true && null is always null
4616        assert_eq!(simplify(lit(true).and(lit_bool_null())), lit_bool_null(),);
4617
4618        // null && true is always null
4619        assert_eq!(simplify(lit_bool_null().and(lit(true))), lit_bool_null(),);
4620
4621        // false && null is always false
4622        assert_eq!(simplify(lit(false).and(lit_bool_null())), lit(false),);
4623
4624        // null && false is always false
4625        assert_eq!(simplify(lit_bool_null().and(lit(false))), lit(false),);
4626
4627        // c1 BETWEEN Int32(0) AND Int32(10) AND Boolean(NULL)
4628        // it can be either NULL or FALSE depending on the value of `c1 BETWEEN Int32(0) AND Int32(10)`
4629        // and the Boolean(NULL) should remain
4630        let expr = col("c1").between(lit(0), lit(10));
4631        let expr = expr.and(lit_bool_null());
4632        let result = simplify(expr);
4633
4634        let expected_expr = and(
4635            and(col("c1").gt_eq(lit(0)), col("c1").lt_eq(lit(10))),
4636            lit_bool_null(),
4637        );
4638        assert_eq!(expected_expr, result);
4639    }
4640
4641    #[test]
4642    fn simplify_expr_between() {
4643        // c2 between 3 and 4 is c2 >= 3 and c2 <= 4
4644        let expr = col("c2").between(lit(3), lit(4));
4645        assert_eq!(
4646            simplify(expr),
4647            and(col("c2").gt_eq(lit(3)), col("c2").lt_eq(lit(4)))
4648        );
4649
4650        // c2 not between 3 and 4 is c2 < 3 or c2 > 4
4651        let expr = col("c2").not_between(lit(3), lit(4));
4652        assert_eq!(
4653            simplify(expr),
4654            or(col("c2").lt(lit(3)), col("c2").gt(lit(4)))
4655        );
4656    }
4657
4658    #[test]
4659    fn test_like_and_ilike() {
4660        let null = lit(ScalarValue::Utf8(None));
4661
4662        // expr [NOT] [I]LIKE NULL
4663        let expr = col("c1").like(null.clone());
4664        assert_eq!(simplify(expr), lit_bool_null());
4665
4666        let expr = col("c1").not_like(null.clone());
4667        assert_eq!(simplify(expr), lit_bool_null());
4668
4669        let expr = col("c1").ilike(null.clone());
4670        assert_eq!(simplify(expr), lit_bool_null());
4671
4672        let expr = col("c1").not_ilike(null.clone());
4673        assert_eq!(simplify(expr), lit_bool_null());
4674
4675        // expr [NOT] [I]LIKE '%'
4676        let expr = col("c1").like(lit("%"));
4677        assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4678
4679        let expr = col("c1").not_like(lit("%"));
4680        assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4681
4682        let expr = col("c1").ilike(lit("%"));
4683        assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4684
4685        let expr = col("c1").not_ilike(lit("%"));
4686        assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4687
4688        // expr [NOT] [I]LIKE '%%'
4689        let expr = col("c1").like(lit("%%"));
4690        assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4691
4692        let expr = col("c1").not_like(lit("%%"));
4693        assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4694
4695        let expr = col("c1").ilike(lit("%%"));
4696        assert_eq!(simplify(expr), if_not_null(col("c1"), true));
4697
4698        let expr = col("c1").not_ilike(lit("%%"));
4699        assert_eq!(simplify(expr), if_not_null(col("c1"), false));
4700
4701        // not_null_expr [NOT] [I]LIKE '%'
4702        let expr = col("c1_non_null").like(lit("%"));
4703        assert_eq!(simplify(expr), lit(true));
4704
4705        let expr = col("c1_non_null").not_like(lit("%"));
4706        assert_eq!(simplify(expr), lit(false));
4707
4708        let expr = col("c1_non_null").ilike(lit("%"));
4709        assert_eq!(simplify(expr), lit(true));
4710
4711        let expr = col("c1_non_null").not_ilike(lit("%"));
4712        assert_eq!(simplify(expr), lit(false));
4713
4714        // not_null_expr [NOT] [I]LIKE '%%'
4715        let expr = col("c1_non_null").like(lit("%%"));
4716        assert_eq!(simplify(expr), lit(true));
4717
4718        let expr = col("c1_non_null").not_like(lit("%%"));
4719        assert_eq!(simplify(expr), lit(false));
4720
4721        let expr = col("c1_non_null").ilike(lit("%%"));
4722        assert_eq!(simplify(expr), lit(true));
4723
4724        let expr = col("c1_non_null").not_ilike(lit("%%"));
4725        assert_eq!(simplify(expr), lit(false));
4726
4727        // null_constant [NOT] [I]LIKE '%'
4728        let expr = null.clone().like(lit("%"));
4729        assert_eq!(simplify(expr), lit_bool_null());
4730
4731        let expr = null.clone().not_like(lit("%"));
4732        assert_eq!(simplify(expr), lit_bool_null());
4733
4734        let expr = null.clone().ilike(lit("%"));
4735        assert_eq!(simplify(expr), lit_bool_null());
4736
4737        let expr = null.clone().not_ilike(lit("%"));
4738        assert_eq!(simplify(expr), lit_bool_null());
4739
4740        // null_constant [NOT] [I]LIKE '%%'
4741        let expr = null.clone().like(lit("%%"));
4742        assert_eq!(simplify(expr), lit_bool_null());
4743
4744        let expr = null.clone().not_like(lit("%%"));
4745        assert_eq!(simplify(expr), lit_bool_null());
4746
4747        let expr = null.clone().ilike(lit("%%"));
4748        assert_eq!(simplify(expr), lit_bool_null());
4749
4750        let expr = null.clone().not_ilike(lit("%%"));
4751        assert_eq!(simplify(expr), lit_bool_null());
4752
4753        // null_constant [NOT] [I]LIKE 'a%'
4754        let expr = null.clone().like(lit("a%"));
4755        assert_eq!(simplify(expr), lit_bool_null());
4756
4757        let expr = null.clone().not_like(lit("a%"));
4758        assert_eq!(simplify(expr), lit_bool_null());
4759
4760        let expr = null.clone().ilike(lit("a%"));
4761        assert_eq!(simplify(expr), lit_bool_null());
4762
4763        let expr = null.clone().not_ilike(lit("a%"));
4764        assert_eq!(simplify(expr), lit_bool_null());
4765
4766        // expr [NOT] [I]LIKE with pattern without wildcards
4767        let expr = col("c1").like(lit("a"));
4768        assert_eq!(simplify(expr), col("c1").eq(lit("a")));
4769        let expr = col("c1").not_like(lit("a"));
4770        assert_eq!(simplify(expr), col("c1").not_eq(lit("a")));
4771        let expr = col("c1").like(lit("a_"));
4772        assert_eq!(simplify(expr), col("c1").like(lit("a_")));
4773        let expr = col("c1").not_like(lit("a_"));
4774        assert_eq!(simplify(expr), col("c1").not_like(lit("a_")));
4775
4776        let expr = col("c1").ilike(lit("a"));
4777        assert_eq!(simplify(expr), col("c1").ilike(lit("a")));
4778        let expr = col("c1").not_ilike(lit("a"));
4779        assert_eq!(simplify(expr), col("c1").not_ilike(lit("a")));
4780    }
4781
4782    #[test]
4783    fn test_simplify_with_guarantee() {
4784        // (c3 >= 3) AND (c4 + 2 < 10 OR (c1 NOT IN ("a", "b")))
4785        let expr_x = col("c3").gt(lit(3_i64));
4786        let expr_y = (col("c4") + lit(2_u32)).lt(lit(10_u32));
4787        let expr_z = col("c1").in_list(vec![lit("a"), lit("b")], true);
4788        let expr = expr_x.clone().and(expr_y.or(expr_z));
4789
4790        // All guaranteed null
4791        let guarantees = vec![
4792            (col("c3"), NullableInterval::from(ScalarValue::Int64(None))),
4793            (col("c4"), NullableInterval::from(ScalarValue::UInt32(None))),
4794            (col("c1"), NullableInterval::from(ScalarValue::Utf8(None))),
4795        ];
4796
4797        let output = simplify_with_guarantee(expr.clone(), guarantees);
4798        assert_eq!(output, lit_bool_null());
4799
4800        // All guaranteed false
4801        let guarantees = vec![
4802            (
4803                col("c3"),
4804                NullableInterval::NotNull {
4805                    values: Interval::make(Some(0_i64), Some(2_i64)).unwrap(),
4806                },
4807            ),
4808            (
4809                col("c4"),
4810                NullableInterval::from(ScalarValue::UInt32(Some(9))),
4811            ),
4812            (col("c1"), NullableInterval::from(ScalarValue::from("a"))),
4813        ];
4814        let output = simplify_with_guarantee(expr.clone(), guarantees);
4815        assert_eq!(output, lit(false));
4816
4817        // Guaranteed false or null -> no change.
4818        let guarantees = vec![
4819            (
4820                col("c3"),
4821                NullableInterval::MaybeNull {
4822                    values: Interval::make(Some(0_i64), Some(2_i64)).unwrap(),
4823                },
4824            ),
4825            (
4826                col("c4"),
4827                NullableInterval::MaybeNull {
4828                    values: Interval::make(Some(9_u32), Some(9_u32)).unwrap(),
4829                },
4830            ),
4831            (
4832                col("c1"),
4833                NullableInterval::NotNull {
4834                    values: Interval::try_new(
4835                        ScalarValue::from("d"),
4836                        ScalarValue::from("f"),
4837                    )
4838                    .unwrap(),
4839                },
4840            ),
4841        ];
4842        let output = simplify_with_guarantee(expr.clone(), guarantees);
4843        assert_eq!(&output, &expr_x);
4844
4845        // Sufficient true guarantees
4846        let guarantees = vec![
4847            (
4848                col("c3"),
4849                NullableInterval::from(ScalarValue::Int64(Some(9))),
4850            ),
4851            (
4852                col("c4"),
4853                NullableInterval::from(ScalarValue::UInt32(Some(3))),
4854            ),
4855        ];
4856        let output = simplify_with_guarantee(expr.clone(), guarantees);
4857        assert_eq!(output, lit(true));
4858
4859        // Only partially simplify
4860        let guarantees = vec![(
4861            col("c4"),
4862            NullableInterval::from(ScalarValue::UInt32(Some(3))),
4863        )];
4864        let output = simplify_with_guarantee(expr, guarantees);
4865        assert_eq!(&output, &expr_x);
4866    }
4867
4868    #[test]
4869    fn test_expression_partial_simplify_1() {
4870        // (1 + 2) + (4 / 0) -> 3 + (4 / 0)
4871        let expr = (lit(1) + lit(2)) + (lit(4) / lit(0));
4872        let expected = (lit(3)) + (lit(4) / lit(0));
4873
4874        assert_eq!(simplify(expr), expected);
4875    }
4876
4877    #[test]
4878    fn test_expression_partial_simplify_2() {
4879        // (1 > 2) and (4 / 0) -> false
4880        let expr = (lit(1).gt(lit(2))).and(lit(4) / lit(0));
4881        let expected = lit(false);
4882
4883        assert_eq!(simplify(expr), expected);
4884    }
4885
4886    #[test]
4887    fn test_simplify_cycles() {
4888        // TRUE
4889        let expr = lit(true);
4890        let expected = lit(true);
4891        let (expr, num_iter) = simplify_with_cycle_count(expr);
4892        assert_eq!(expr, expected);
4893        assert_eq!(num_iter, 1);
4894
4895        // (true != NULL) OR (5 > 10)
4896        let expr = lit(true).not_eq(lit_bool_null()).or(lit(5).gt(lit(10)));
4897        let expected = lit_bool_null();
4898        let (expr, num_iter) = simplify_with_cycle_count(expr);
4899        assert_eq!(expr, expected);
4900        assert_eq!(num_iter, 2);
4901
4902        // NOTE: this currently does not simplify
4903        // (((c4 - 10) + 10) *100) / 100
4904        let expr = (((col("c4") - lit(10)) + lit(10)) * lit(100)) / lit(100);
4905        let expected = expr.clone();
4906        let (expr, num_iter) = simplify_with_cycle_count(expr);
4907        assert_eq!(expr, expected);
4908        assert_eq!(num_iter, 1);
4909
4910        // ((c4<1 or c3<2) and c3_non_null<3) and false
4911        let expr = col("c4")
4912            .lt(lit(1))
4913            .or(col("c3").lt(lit(2)))
4914            .and(col("c3_non_null").lt(lit(3)))
4915            .and(lit(false));
4916        let expected = lit(false);
4917        let (expr, num_iter) = simplify_with_cycle_count(expr);
4918        assert_eq!(expr, expected);
4919        assert_eq!(num_iter, 2);
4920    }
4921
4922    fn boolean_test_schema() -> DFSchemaRef {
4923        static BOOLEAN_TEST_SCHEMA: LazyLock<DFSchemaRef> = LazyLock::new(|| {
4924            Schema::new(vec![
4925                Field::new("A", DataType::Boolean, false),
4926                Field::new("B", DataType::Boolean, false),
4927                Field::new("C", DataType::Boolean, false),
4928                Field::new("D", DataType::Boolean, false),
4929            ])
4930            .to_dfschema_ref()
4931            .unwrap()
4932        });
4933        Arc::clone(&BOOLEAN_TEST_SCHEMA)
4934    }
4935
4936    #[test]
4937    fn simplify_common_factor_conjunction_in_disjunction() {
4938        let schema = boolean_test_schema();
4939        let simplifier =
4940            ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
4941
4942        let a = || col("A");
4943        let b = || col("B");
4944        let c = || col("C");
4945        let d = || col("D");
4946
4947        // (A AND B) OR (A AND C) -> A AND (B OR C)
4948        let expr = a().and(b()).or(a().and(c()));
4949        let expected = a().and(b().or(c()));
4950
4951        assert_eq!(expected, simplifier.simplify(expr).unwrap());
4952
4953        // (A AND B) OR (A AND C) OR (A AND D) -> A AND (B OR C OR D)
4954        let expr = a().and(b()).or(a().and(c())).or(a().and(d()));
4955        let expected = a().and(b().or(c()).or(d()));
4956        assert_eq!(expected, simplifier.simplify(expr).unwrap());
4957
4958        // A OR (B AND C AND A) -> A
4959        let expr = a().or(b().and(c().and(a())));
4960        let expected = a();
4961        assert_eq!(expected, simplifier.simplify(expr).unwrap());
4962    }
4963
4964    #[test]
4965    fn test_simplify_udaf() {
4966        let udaf = AggregateUDF::new_from_impl(SimplifyMockUdaf::new_with_simplify());
4967        let aggregate_function_expr =
4968            Expr::AggregateFunction(expr::AggregateFunction::new_udf(
4969                udaf.into(),
4970                vec![],
4971                false,
4972                None,
4973                vec![],
4974                None,
4975            ));
4976
4977        let expected = col("result_column");
4978        assert_eq!(simplify(aggregate_function_expr), expected);
4979
4980        let udaf = AggregateUDF::new_from_impl(SimplifyMockUdaf::new_without_simplify());
4981        let aggregate_function_expr =
4982            Expr::AggregateFunction(expr::AggregateFunction::new_udf(
4983                udaf.into(),
4984                vec![],
4985                false,
4986                None,
4987                vec![],
4988                None,
4989            ));
4990
4991        let expected = aggregate_function_expr.clone();
4992        assert_eq!(simplify(aggregate_function_expr), expected);
4993    }
4994
4995    /// A Mock UDAF which defines `simplify` to be used in tests
4996    /// related to UDAF simplification
4997    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
4998    struct SimplifyMockUdaf {
4999        simplify: bool,
5000    }
5001
5002    impl SimplifyMockUdaf {
5003        /// make simplify method return new expression
5004        fn new_with_simplify() -> Self {
5005            Self { simplify: true }
5006        }
5007        /// make simplify method return no change
5008        fn new_without_simplify() -> Self {
5009            Self { simplify: false }
5010        }
5011    }
5012
5013    impl AggregateUDFImpl for SimplifyMockUdaf {
5014        fn name(&self) -> &str {
5015            "mock_simplify"
5016        }
5017
5018        fn signature(&self) -> &Signature {
5019            unimplemented!()
5020        }
5021
5022        fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
5023            unimplemented!("not needed for tests")
5024        }
5025
5026        fn accumulator(
5027            &self,
5028            _acc_args: AccumulatorArgs,
5029        ) -> Result<Box<dyn Accumulator>> {
5030            unimplemented!("not needed for tests")
5031        }
5032
5033        fn groups_accumulator_supported(&self, _args: AccumulatorArgs) -> bool {
5034            unimplemented!("not needed for testing")
5035        }
5036
5037        fn create_groups_accumulator(
5038            &self,
5039            _args: AccumulatorArgs,
5040        ) -> Result<Box<dyn GroupsAccumulator>> {
5041            unimplemented!("not needed for testing")
5042        }
5043
5044        fn simplify(&self) -> Option<AggregateFunctionSimplification> {
5045            if self.simplify {
5046                Some(Box::new(|_, _| Ok(col("result_column"))))
5047            } else {
5048                None
5049            }
5050        }
5051    }
5052
5053    #[test]
5054    fn test_simplify_udwf() {
5055        let udwf = WindowFunctionDefinition::WindowUDF(
5056            WindowUDF::new_from_impl(SimplifyMockUdwf::new_with_simplify()).into(),
5057        );
5058        let window_function_expr = Expr::from(WindowFunction::new(udwf, vec![]));
5059
5060        let expected = col("result_column");
5061        assert_eq!(simplify(window_function_expr), expected);
5062
5063        let udwf = WindowFunctionDefinition::WindowUDF(
5064            WindowUDF::new_from_impl(SimplifyMockUdwf::new_without_simplify()).into(),
5065        );
5066        let window_function_expr = Expr::from(WindowFunction::new(udwf, vec![]));
5067
5068        let expected = window_function_expr.clone();
5069        assert_eq!(simplify(window_function_expr), expected);
5070    }
5071
5072    /// A Mock UDWF which defines `simplify` to be used in tests
5073    /// related to UDWF simplification
5074    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
5075    struct SimplifyMockUdwf {
5076        simplify: bool,
5077    }
5078
5079    impl SimplifyMockUdwf {
5080        /// make simplify method return new expression
5081        fn new_with_simplify() -> Self {
5082            Self { simplify: true }
5083        }
5084        /// make simplify method return no change
5085        fn new_without_simplify() -> Self {
5086            Self { simplify: false }
5087        }
5088    }
5089
5090    impl WindowUDFImpl for SimplifyMockUdwf {
5091        fn name(&self) -> &str {
5092            "mock_simplify"
5093        }
5094
5095        fn signature(&self) -> &Signature {
5096            unimplemented!()
5097        }
5098
5099        fn simplify(&self) -> Option<WindowFunctionSimplification> {
5100            if self.simplify {
5101                Some(Box::new(|_, _| Ok(col("result_column"))))
5102            } else {
5103                None
5104            }
5105        }
5106
5107        fn partition_evaluator(
5108            &self,
5109            _partition_evaluator_args: PartitionEvaluatorArgs,
5110        ) -> Result<Box<dyn PartitionEvaluator>> {
5111            unimplemented!("not needed for tests")
5112        }
5113
5114        fn field(&self, _field_args: WindowUDFFieldArgs) -> Result<FieldRef> {
5115            unimplemented!("not needed for tests")
5116        }
5117
5118        fn limit_effect(&self, _args: &[Arc<dyn PhysicalExpr>]) -> LimitEffect {
5119            LimitEffect::Unknown
5120        }
5121    }
5122    #[derive(Debug, PartialEq, Eq, Hash)]
5123    struct VolatileUdf {
5124        signature: Signature,
5125    }
5126
5127    impl VolatileUdf {
5128        pub fn new() -> Self {
5129            Self {
5130                signature: Signature::exact(vec![], Volatility::Volatile),
5131            }
5132        }
5133    }
5134    impl ScalarUDFImpl for VolatileUdf {
5135        fn name(&self) -> &str {
5136            "VolatileUdf"
5137        }
5138
5139        fn signature(&self) -> &Signature {
5140            &self.signature
5141        }
5142
5143        fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
5144            Ok(DataType::Int16)
5145        }
5146
5147        fn invoke_with_args(&self, _args: ScalarFunctionArgs) -> Result<ColumnarValue> {
5148            panic!("dummy - not implemented")
5149        }
5150    }
5151
5152    #[test]
5153    fn test_optimize_volatile_conditions() {
5154        let fun = Arc::new(ScalarUDF::new_from_impl(VolatileUdf::new()));
5155        let rand = Expr::ScalarFunction(ScalarFunction::new_udf(fun, vec![]));
5156        {
5157            let expr = rand
5158                .clone()
5159                .eq(lit(0))
5160                .or(col("column1").eq(lit(2)).and(rand.clone().eq(lit(0))));
5161
5162            assert_eq!(simplify(expr.clone()), expr);
5163        }
5164
5165        {
5166            let expr = col("column1")
5167                .eq(lit(2))
5168                .or(col("column1").eq(lit(2)).and(rand.clone().eq(lit(0))));
5169
5170            assert_eq!(simplify(expr), col("column1").eq(lit(2)));
5171        }
5172
5173        {
5174            let expr = (col("column1").eq(lit(2)).and(rand.clone().eq(lit(0)))).or(col(
5175                "column1",
5176            )
5177            .eq(lit(2))
5178            .and(rand.clone().eq(lit(0))));
5179
5180            assert_eq!(
5181                simplify(expr),
5182                col("column1")
5183                    .eq(lit(2))
5184                    .and((rand.clone().eq(lit(0))).or(rand.clone().eq(lit(0))))
5185            );
5186        }
5187    }
5188
5189    #[test]
5190    fn simplify_fixed_size_binary_eq_lit() {
5191        let bytes = [1u8, 2, 3].as_slice();
5192
5193        // The expression starts simple.
5194        let expr = col("c5").eq(lit(bytes));
5195
5196        // The type coercer introduces a cast.
5197        let coerced = coerce(expr.clone());
5198        let schema = expr_test_schema();
5199        assert_eq!(
5200            coerced,
5201            col("c5")
5202                .cast_to(&DataType::Binary, schema.as_ref())
5203                .unwrap()
5204                .eq(lit(bytes))
5205        );
5206
5207        // The simplifier removes the cast.
5208        assert_eq!(
5209            simplify(coerced),
5210            col("c5").eq(Expr::Literal(
5211                ScalarValue::FixedSizeBinary(3, Some(bytes.to_vec()),),
5212                None
5213            ))
5214        );
5215    }
5216
5217    #[test]
5218    fn simplify_cast_literal() {
5219        // Test that CAST(literal) expressions are evaluated at plan time
5220
5221        // CAST(123 AS Int64) should become 123i64
5222        let expr = Expr::Cast(Cast::new(Box::new(lit(123i32)), DataType::Int64));
5223        let expected = lit(123i64);
5224        assert_eq!(simplify(expr), expected);
5225
5226        // CAST(1761630189642 AS Timestamp(Nanosecond, Some("+00:00")))
5227        // Integer to timestamp cast
5228        let expr = Expr::Cast(Cast::new(
5229            Box::new(lit(1761630189642i64)),
5230            DataType::Timestamp(
5231                arrow::datatypes::TimeUnit::Nanosecond,
5232                Some("+00:00".into()),
5233            ),
5234        ));
5235        // Should evaluate to a timestamp literal
5236        let result = simplify(expr);
5237        match result {
5238            Expr::Literal(ScalarValue::TimestampNanosecond(Some(val), tz), _) => {
5239                assert_eq!(val, 1761630189642i64);
5240                assert_eq!(tz.as_deref(), Some("+00:00"));
5241            }
5242            other => panic!("Expected TimestampNanosecond literal, got: {other:?}"),
5243        }
5244
5245        // Test CAST of invalid string to timestamp - should return an error at plan time
5246        // This represents the case from the issue: CAST(Utf8("1761630189642") AS Timestamp)
5247        // "1761630189642" is NOT a valid timestamp string format
5248        let expr = Expr::Cast(Cast::new(
5249            Box::new(lit("1761630189642")),
5250            DataType::Timestamp(
5251                arrow::datatypes::TimeUnit::Nanosecond,
5252                Some("+00:00".into()),
5253            ),
5254        ));
5255
5256        // The simplification should now fail with an error at plan time
5257        let schema = test_schema();
5258        let simplifier =
5259            ExprSimplifier::new(SimplifyContext::builder().with_schema(schema).build());
5260        let result = simplifier.simplify(expr);
5261        assert!(result.is_err(), "Expected error for invalid cast");
5262        let err_msg = result.unwrap_err().to_string();
5263        assert_contains!(err_msg, "Error parsing timestamp");
5264    }
5265
5266    fn if_not_null(expr: Expr, then: bool) -> Expr {
5267        Expr::Case(Case {
5268            expr: Some(expr.is_not_null().into()),
5269            when_then_expr: vec![(lit(true).into(), lit(then).into())],
5270            else_expr: None,
5271        })
5272    }
5273
5274    // --------------------------------
5275    // --- Struct Cast Tests -----
5276    // --------------------------------
5277
5278    /// Helper to create a `Struct` literal cast expression from `source_fields` and `target_fields`.
5279    fn make_struct_cast_expr(source_fields: Fields, target_fields: Fields) -> Expr {
5280        // Create 1-row struct array (not 0-row) so it can be evaluated by simplifier
5281        let arrays: Vec<Arc<dyn Array>> = vec![
5282            Arc::new(Int32Array::from(vec![Some(1)])),
5283            Arc::new(Int32Array::from(vec![Some(2)])),
5284        ];
5285        let struct_array = StructArray::try_new(source_fields, arrays, None).unwrap();
5286
5287        Expr::Cast(Cast::new(
5288            Box::new(Expr::Literal(
5289                ScalarValue::Struct(Arc::new(struct_array)),
5290                None,
5291            )),
5292            DataType::Struct(target_fields),
5293        ))
5294    }
5295
5296    #[test]
5297    fn test_struct_cast_different_field_counts_not_foldable() {
5298        // Test that struct casts with different field counts are NOT marked as foldable
5299        // When field counts differ, const-folding should not be attempted
5300
5301        let source_fields = Fields::from(vec![
5302            Arc::new(Field::new("a", DataType::Int32, true)),
5303            Arc::new(Field::new("b", DataType::Int32, true)),
5304        ]);
5305
5306        let target_fields = Fields::from(vec![
5307            Arc::new(Field::new("x", DataType::Int32, true)),
5308            Arc::new(Field::new("y", DataType::Int32, true)),
5309            Arc::new(Field::new("z", DataType::Int32, true)),
5310        ]);
5311
5312        let expr = make_struct_cast_expr(source_fields, target_fields);
5313
5314        let simplifier = ExprSimplifier::new(
5315            SimplifyContext::builder()
5316                .with_schema(test_schema())
5317                .build(),
5318        );
5319
5320        // The cast should remain unchanged since field counts differ
5321        let result = simplifier.simplify(expr.clone()).unwrap();
5322        // Ensure const-folding was not attempted (the expression remains exactly the same)
5323        assert_eq!(
5324            result, expr,
5325            "Struct cast with different field counts should remain unchanged (no const-folding)"
5326        );
5327    }
5328
5329    #[test]
5330    fn test_struct_cast_same_field_count_foldable() {
5331        // Test that struct casts with same field counts can be considered for const-folding
5332
5333        let source_fields = Fields::from(vec![
5334            Arc::new(Field::new("a", DataType::Int32, true)),
5335            Arc::new(Field::new("b", DataType::Int32, true)),
5336        ]);
5337
5338        let target_fields = Fields::from(vec![
5339            Arc::new(Field::new("a", DataType::Int32, true)),
5340            Arc::new(Field::new("b", DataType::Int32, true)),
5341        ]);
5342
5343        let expr = make_struct_cast_expr(source_fields, target_fields);
5344
5345        let simplifier = ExprSimplifier::new(
5346            SimplifyContext::builder()
5347                .with_schema(test_schema())
5348                .build(),
5349        );
5350
5351        // The cast should be simplified
5352        let result = simplifier.simplify(expr.clone()).unwrap();
5353        // Struct casts with same field count should be const-folded to a literal
5354        assert!(matches!(result, Expr::Literal(_, _)));
5355        // Ensure the simplifier made a change (not identical to original)
5356        assert_ne!(
5357            result, expr,
5358            "Struct cast with same field count should be simplified (not identical to input)"
5359        );
5360    }
5361
5362    #[test]
5363    fn test_struct_cast_different_names_same_count() {
5364        // Test struct cast with same field count but different names
5365        // Field count matches; simplification should be skipped because names do not overlap
5366
5367        let source_fields = Fields::from(vec![
5368            Arc::new(Field::new("a", DataType::Int32, true)),
5369            Arc::new(Field::new("b", DataType::Int32, true)),
5370        ]);
5371
5372        let target_fields = Fields::from(vec![
5373            Arc::new(Field::new("x", DataType::Int32, true)),
5374            Arc::new(Field::new("y", DataType::Int32, true)),
5375        ]);
5376
5377        let expr = make_struct_cast_expr(source_fields, target_fields);
5378
5379        let simplifier = ExprSimplifier::new(
5380            SimplifyContext::builder()
5381                .with_schema(test_schema())
5382                .build(),
5383        );
5384
5385        // The cast should remain unchanged because there is no name overlap
5386        let result = simplifier.simplify(expr.clone()).unwrap();
5387        assert_eq!(
5388            result, expr,
5389            "Struct cast with different names but same field count should not be simplified"
5390        );
5391    }
5392
5393    #[test]
5394    fn test_struct_cast_empty_array_not_foldable() {
5395        // Test that struct casts with 0-row (empty) struct arrays are NOT const-folded
5396        // The simplifier uses a 1-row input batch, which causes dimension mismatches
5397        // when evaluating 0-row struct literals
5398
5399        let source_fields = Fields::from(vec![
5400            Arc::new(Field::new("a", DataType::Int32, true)),
5401            Arc::new(Field::new("b", DataType::Int32, true)),
5402        ]);
5403
5404        let target_fields = Fields::from(vec![
5405            Arc::new(Field::new("a", DataType::Int32, true)),
5406            Arc::new(Field::new("b", DataType::Int32, true)),
5407        ]);
5408
5409        // Create a 0-row (empty) struct array
5410        let arrays: Vec<Arc<dyn Array>> = vec![
5411            Arc::new(Int32Array::new(vec![].into(), None)),
5412            Arc::new(Int32Array::new(vec![].into(), None)),
5413        ];
5414        let struct_array = StructArray::try_new(source_fields, arrays, None).unwrap();
5415
5416        let expr = Expr::Cast(Cast::new(
5417            Box::new(Expr::Literal(
5418                ScalarValue::Struct(Arc::new(struct_array)),
5419                None,
5420            )),
5421            DataType::Struct(target_fields),
5422        ));
5423
5424        let simplifier = ExprSimplifier::new(
5425            SimplifyContext::builder()
5426                .with_schema(test_schema())
5427                .build(),
5428        );
5429
5430        // The cast should remain unchanged since the struct array is empty (0-row)
5431        let result = simplifier.simplify(expr.clone()).unwrap();
5432        assert_eq!(
5433            result, expr,
5434            "Struct cast with empty (0-row) array should remain unchanged"
5435        );
5436    }
5437}