Skip to main content

datafusion_expr/
expr.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//! Logical Expressions: [`Expr`]
19
20use std::cmp::Ordering;
21use std::collections::HashSet;
22use std::fmt::{self, Display, Formatter, Write};
23use std::hash::{Hash, Hasher};
24use std::mem;
25use std::sync::Arc;
26
27use crate::expr_fn::binary_expr;
28use crate::function::WindowFunctionSimplification;
29use crate::logical_plan::Subquery;
30use crate::{AggregateUDF, Volatility};
31use crate::{ExprSchemable, Operator, Signature, WindowFrame, WindowUDF};
32
33use arrow::datatypes::{DataType, Field, FieldRef};
34use datafusion_common::cse::{HashNode, NormalizeEq, Normalizeable};
35use datafusion_common::tree_node::{
36    Transformed, TransformedResult, TreeNode, TreeNodeContainer, TreeNodeRecursion,
37};
38use datafusion_common::{
39    Column, DFSchema, HashMap, Result, ScalarValue, Spans, TableReference,
40};
41use datafusion_expr_common::placement::ExpressionPlacement;
42use datafusion_functions_window_common::field::WindowUDFFieldArgs;
43#[cfg(feature = "sql")]
44use sqlparser::ast::{
45    ExceptSelectItem, ExcludeSelectItem, IlikeSelectItem, RenameSelectItem,
46    ReplaceSelectElement,
47};
48
49// Moved in 51.0.0 to datafusion_common
50pub use datafusion_common::metadata::FieldMetadata;
51use datafusion_common::metadata::ScalarAndMetadata;
52
53// This mirrors sqlparser::ast::NullTreatment but we need our own variant
54// for when the sql feature is disabled.
55#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
56pub enum NullTreatment {
57    IgnoreNulls,
58    RespectNulls,
59}
60
61impl Display for NullTreatment {
62    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
63        f.write_str(match self {
64            NullTreatment::IgnoreNulls => "IGNORE NULLS",
65            NullTreatment::RespectNulls => "RESPECT NULLS",
66        })
67    }
68}
69
70#[cfg(feature = "sql")]
71impl From<sqlparser::ast::NullTreatment> for NullTreatment {
72    fn from(value: sqlparser::ast::NullTreatment) -> Self {
73        match value {
74            sqlparser::ast::NullTreatment::IgnoreNulls => Self::IgnoreNulls,
75            sqlparser::ast::NullTreatment::RespectNulls => Self::RespectNulls,
76        }
77    }
78}
79
80/// Represents logical expressions such as `A + 1`, or `CAST(c1 AS int)`.
81///
82/// For example the expression `A + 1` will be represented as
83///
84///```text
85///  BinaryExpr {
86///    left: Expr::Column("A"),
87///    op: Operator::Plus,
88///    right: Expr::Literal(ScalarValue::Int32(Some(1)), None)
89/// }
90/// ```
91///
92/// # Creating Expressions
93///
94/// `Expr`s can be created directly, but it is often easier and less verbose to
95/// use the fluent APIs in [`crate::expr_fn`] such as [`col`] and [`lit`], or
96/// methods such as [`Expr::alias`], [`Expr::cast_to`], and [`Expr::Like`]).
97///
98/// See also [`ExprFunctionExt`] for creating aggregate and window functions.
99///
100/// [`ExprFunctionExt`]: crate::expr_fn::ExprFunctionExt
101///
102/// # Printing Expressions
103///
104/// You can print `Expr`s using the `Debug` trait, `Display` trait, or
105/// [`Self::human_display`]. See the [examples](#examples-displaying-exprs) below.
106///
107/// If you need  SQL to pass to other systems, consider using [`Unparser`].
108///
109/// [`Unparser`]: https://docs.rs/datafusion/latest/datafusion/sql/unparser/struct.Unparser.html
110///
111/// # Schema Access
112///
113/// See [`ExprSchemable::get_type`] to access the [`DataType`] and nullability
114/// of an `Expr`.
115///
116/// # Visiting and Rewriting `Expr`s
117///
118/// The `Expr` struct implements the [`TreeNode`] trait for walking and
119/// rewriting expressions. For example [`TreeNode::apply`] recursively visits an
120/// `Expr` and [`TreeNode::transform`] can be used to rewrite an expression. See
121/// the examples below and [`TreeNode`] for more information.
122///
123/// # Examples: Creating and Using `Expr`s
124///
125/// ## Column References and Literals
126///
127/// [`Expr::Column`] refer to the values of columns and are often created with
128/// the [`col`] function. For example to create an expression `c1` referring to
129/// column named "c1":
130///
131/// [`col`]: crate::expr_fn::col
132///
133/// ```
134/// # use datafusion_common::Column;
135/// # use datafusion_expr::{lit, col, Expr};
136/// let expr = col("c1");
137/// assert_eq!(expr, Expr::Column(Column::from_name("c1")));
138/// ```
139///
140/// [`Expr::Literal`] refer to literal, or constant, values. These are created
141/// with the [`lit`] function. For example to create an expression `42`:
142///
143/// [`lit`]: crate::lit
144///
145/// ```
146/// # use datafusion_common::{Column, ScalarValue};
147/// # use datafusion_expr::{lit, col, Expr};
148/// // All literals are strongly typed in DataFusion. To make an `i64` 42:
149/// let expr = lit(42i64);
150/// assert_eq!(expr, Expr::Literal(ScalarValue::Int64(Some(42)), None));
151/// assert_eq!(expr, Expr::Literal(ScalarValue::Int64(Some(42)), None));
152/// // To make a (typed) NULL:
153/// let expr = Expr::Literal(ScalarValue::Int64(None), None);
154/// // to make an (untyped) NULL (the optimizer will coerce this to the correct type):
155/// let expr = lit(ScalarValue::Null);
156/// ```
157///
158/// ## Binary Expressions
159///
160/// Exprs implement traits that allow easy to understand construction of more
161/// complex expressions. For example, to create `c1 + c2` to add columns "c1" and
162/// "c2" together
163///
164/// ```
165/// # use datafusion_expr::{lit, col, Operator, Expr};
166/// // Use the `+` operator to add two columns together
167/// let expr = col("c1") + col("c2");
168/// assert!(matches!(expr, Expr::BinaryExpr { .. }));
169/// if let Expr::BinaryExpr(binary_expr) = expr {
170///     assert_eq!(*binary_expr.left, col("c1"));
171///     assert_eq!(*binary_expr.right, col("c2"));
172///     assert_eq!(binary_expr.op, Operator::Plus);
173/// }
174/// ```
175///
176/// The expression `c1 = 42` to compares the value in column "c1" to the
177/// literal value `42`:
178///
179/// ```
180/// # use datafusion_common::ScalarValue;
181/// # use datafusion_expr::{lit, col, Operator, Expr};
182/// let expr = col("c1").eq(lit(42_i32));
183/// assert!(matches!(expr, Expr::BinaryExpr { .. }));
184/// if let Expr::BinaryExpr(binary_expr) = expr {
185///     assert_eq!(*binary_expr.left, col("c1"));
186///     let scalar = ScalarValue::Int32(Some(42));
187///     assert_eq!(*binary_expr.right, Expr::Literal(scalar, None));
188///     assert_eq!(binary_expr.op, Operator::Eq);
189/// }
190/// ```
191///
192/// Here is how to implement the equivalent of `SELECT *` to select all
193/// [`Expr::Column`] from a [`DFSchema`]'s columns:
194///
195/// ```
196/// # use arrow::datatypes::{DataType, Field, Schema};
197/// # use datafusion_common::{DFSchema, Column};
198/// # use datafusion_expr::Expr;
199/// // Create a schema c1(int, c2 float)
200/// let arrow_schema = Schema::new(vec![
201///     Field::new("c1", DataType::Int32, false),
202///     Field::new("c2", DataType::Float64, false),
203/// ]);
204/// // DFSchema is a an Arrow schema with optional relation name
205/// let df_schema = DFSchema::try_from_qualified_schema("t1", &arrow_schema).unwrap();
206///
207/// // Form Vec<Expr> with an expression for each column in the schema
208/// let exprs: Vec<_> = df_schema.iter().map(Expr::from).collect();
209///
210/// assert_eq!(
211///     exprs,
212///     vec![
213///         Expr::from(Column::from_qualified_name("t1.c1")),
214///         Expr::from(Column::from_qualified_name("t1.c2")),
215///     ]
216/// );
217/// ```
218///
219/// # Examples: Displaying `Exprs`
220///
221/// There are three ways to print an `Expr` depending on the usecase.
222///
223/// ## Use `Debug` trait
224///
225/// Following Rust conventions, the `Debug` implementation prints out the
226/// internal structure of the expression, which is useful for debugging.
227///
228/// ```
229/// # use datafusion_expr::{lit, col};
230/// let expr = col("c1") + lit(42);
231/// assert_eq!(format!("{expr:?}"), "BinaryExpr(BinaryExpr { left: Column(Column { relation: None, name: \"c1\" }), op: Plus, right: Literal(Int32(42), None) })");
232/// ```
233///
234/// ## Use the `Display` trait  (detailed expression)
235///
236/// The `Display` implementation prints out the expression in a SQL-like form,
237/// but has additional details such as the data type of literals. This is useful
238/// for understanding the expression in more detail and is used for the low level
239/// [`ExplainFormat::Indent`] explain plan format.
240///
241/// [`ExplainFormat::Indent`]: crate::logical_plan::ExplainFormat::Indent
242///
243/// ```
244/// # use datafusion_expr::{lit, col};
245/// let expr = col("c1") + lit(42);
246/// assert_eq!(format!("{expr}"), "c1 + Int32(42)");
247/// ```
248///
249/// ## Use [`Self::human_display`] (human readable)
250///
251/// [`Self::human_display`]  prints out the expression in a SQL-like form, optimized
252/// for human consumption by end users. It is used for the
253/// [`ExplainFormat::Tree`] explain plan format.
254///
255/// [`ExplainFormat::Tree`]: crate::logical_plan::ExplainFormat::Tree
256///
257///```
258/// # use datafusion_expr::{lit, col};
259/// let expr = col("c1") + lit(42);
260/// assert_eq!(format!("{}", expr.human_display()), "c1 + 42");
261/// ```
262///
263/// # Examples: Visiting and Rewriting `Expr`s
264///
265/// Here is an example that finds all literals in an `Expr` tree:
266/// ```
267/// # use std::collections::{HashSet};
268/// use datafusion_common::ScalarValue;
269/// # use datafusion_expr::{col, Expr, lit};
270/// use datafusion_common::tree_node::{TreeNode, TreeNodeRecursion};
271/// // Expression a = 5 AND b = 6
272/// let expr = col("a").eq(lit(5)) & col("b").eq(lit(6));
273/// // find all literals in a HashMap
274/// let mut scalars = HashSet::new();
275/// // apply recursively visits all nodes in the expression tree
276/// expr.apply(|e| {
277///     if let Expr::Literal(scalar, _) = e {
278///         scalars.insert(scalar);
279///     }
280///     // The return value controls whether to continue visiting the tree
281///     Ok(TreeNodeRecursion::Continue)
282/// })
283/// .unwrap();
284/// // All subtrees have been visited and literals found
285/// assert_eq!(scalars.len(), 2);
286/// assert!(scalars.contains(&ScalarValue::Int32(Some(5))));
287/// assert!(scalars.contains(&ScalarValue::Int32(Some(6))));
288/// ```
289///
290/// Rewrite an expression, replacing references to column "a" in an
291/// to the literal `42`:
292///
293///  ```
294/// # use datafusion_common::tree_node::{Transformed, TreeNode};
295/// # use datafusion_expr::{col, Expr, lit};
296/// // expression a = 5 AND b = 6
297/// let expr = col("a").eq(lit(5)).and(col("b").eq(lit(6)));
298/// // rewrite all references to column "a" to the literal 42
299/// let rewritten = expr.transform(|e| {
300///   if let Expr::Column(c) = &e {
301///     if &c.name == "a" {
302///       // return Transformed::yes to indicate the node was changed
303///       return Ok(Transformed::yes(lit(42)))
304///     }
305///   }
306///   // return Transformed::no to indicate the node was not changed
307///   Ok(Transformed::no(e))
308/// }).unwrap();
309/// // The expression has been rewritten
310/// assert!(rewritten.transformed);
311/// // to 42 = 5 AND b = 6
312/// assert_eq!(rewritten.data, lit(42).eq(lit(5)).and(col("b").eq(lit(6))));
313/// ```
314#[derive(Clone, PartialEq, PartialOrd, Eq, Debug, Hash)]
315pub enum Expr {
316    /// An expression with a specific name.
317    Alias(Alias),
318    /// A named reference to a qualified field in a schema.
319    Column(Column),
320    /// A named reference to a variable in a registry.
321    ScalarVariable(FieldRef, Vec<String>),
322    /// A constant value along with associated [`FieldMetadata`].
323    Literal(ScalarValue, Option<FieldMetadata>),
324    /// A binary expression such as "age > 21"
325    BinaryExpr(BinaryExpr),
326    /// LIKE expression
327    Like(Like),
328    /// LIKE expression that uses regular expressions
329    SimilarTo(Like),
330    /// Negation of an expression. The expression's type must be a boolean to make sense.
331    Not(Box<Expr>),
332    /// True if argument is not NULL, false otherwise. This expression itself is never NULL.
333    IsNotNull(Box<Expr>),
334    /// True if argument is NULL, false otherwise. This expression itself is never NULL.
335    IsNull(Box<Expr>),
336    /// True if argument is true, false otherwise. This expression itself is never NULL.
337    IsTrue(Box<Expr>),
338    /// True if argument is  false, false otherwise. This expression itself is never NULL.
339    IsFalse(Box<Expr>),
340    /// True if argument is NULL, false otherwise. This expression itself is never NULL.
341    IsUnknown(Box<Expr>),
342    /// True if argument is FALSE or NULL, false otherwise. This expression itself is never NULL.
343    IsNotTrue(Box<Expr>),
344    /// True if argument is TRUE OR NULL, false otherwise. This expression itself is never NULL.
345    IsNotFalse(Box<Expr>),
346    /// True if argument is TRUE or FALSE, false otherwise. This expression itself is never NULL.
347    IsNotUnknown(Box<Expr>),
348    /// arithmetic negation of an expression, the operand must be of a signed numeric data type
349    Negative(Box<Expr>),
350    /// Whether an expression is between a given range.
351    Between(Between),
352    /// A CASE expression (see docs on [`Case`])
353    Case(Case),
354    /// Casts the expression to a given type and will return a runtime error if the expression cannot be cast.
355    /// This expression is guaranteed to have a fixed type.
356    Cast(Cast),
357    /// Casts the expression to a given type and will return a null value if the expression cannot be cast.
358    /// This expression is guaranteed to have a fixed type.
359    TryCast(TryCast),
360    /// Call a scalar function with a set of arguments.
361    ScalarFunction(ScalarFunction),
362    /// Calls an aggregate function with arguments, and optional
363    /// `ORDER BY`, `FILTER`, `DISTINCT` and `NULL TREATMENT`.
364    ///
365    /// See also [`ExprFunctionExt`] to set these fields.
366    ///
367    /// [`ExprFunctionExt`]: crate::expr_fn::ExprFunctionExt
368    AggregateFunction(AggregateFunction),
369    /// Call a window function with a set of arguments.
370    WindowFunction(Box<WindowFunction>),
371    /// Returns whether the list contains the expr value.
372    InList(InList),
373    /// EXISTS subquery
374    Exists(Exists),
375    /// IN subquery
376    InSubquery(InSubquery),
377    /// Set comparison subquery (e.g. `= ANY`, `> ALL`)
378    SetComparison(SetComparison),
379    /// Scalar subquery
380    ScalarSubquery(Subquery),
381    /// Represents a reference to all available fields in a specific schema,
382    /// with an optional (schema) qualifier.
383    ///
384    /// This expr has to be resolved to a list of columns before translating logical
385    /// plan into physical plan.
386    #[deprecated(
387        since = "46.0.0",
388        note = "A wildcard needs to be resolved to concrete expressions when constructing the logical plan. See https://github.com/apache/datafusion/issues/7765"
389    )]
390    Wildcard {
391        qualifier: Option<TableReference>,
392        options: Box<WildcardOptions>,
393    },
394    /// List of grouping set expressions. Only valid in the context of an aggregate
395    /// GROUP BY expression list
396    GroupingSet(GroupingSet),
397    /// A place holder for parameters in a prepared statement
398    /// (e.g. `$foo` or `$1`)
399    Placeholder(Placeholder),
400    /// A placeholder which holds a reference to a qualified field
401    /// in the outer query, used for correlated sub queries.
402    OuterReferenceColumn(FieldRef, Column),
403    /// Unnest expression
404    Unnest(Unnest),
405}
406
407impl Default for Expr {
408    fn default() -> Self {
409        Expr::Literal(ScalarValue::Null, None)
410    }
411}
412
413impl AsRef<Expr> for Expr {
414    fn as_ref(&self) -> &Expr {
415        self
416    }
417}
418
419/// Create an [`Expr`] from a [`Column`]
420impl From<Column> for Expr {
421    fn from(value: Column) -> Self {
422        Expr::Column(value)
423    }
424}
425
426/// Create an [`Expr`] from a [`WindowFunction`]
427impl From<WindowFunction> for Expr {
428    fn from(value: WindowFunction) -> Self {
429        Expr::WindowFunction(Box::new(value))
430    }
431}
432
433/// Create an [`Expr`] from an [`ScalarAndMetadata`]
434impl From<ScalarAndMetadata> for Expr {
435    fn from(value: ScalarAndMetadata) -> Self {
436        let (value, metadata) = value.into_inner();
437        Expr::Literal(value, metadata)
438    }
439}
440
441/// Create an [`Expr`] from an optional qualifier and a [`FieldRef`]. This is
442/// useful for creating [`Expr`] from a [`DFSchema`].
443///
444/// See example on [`Expr`]
445impl<'a> From<(Option<&'a TableReference>, &'a FieldRef)> for Expr {
446    fn from(value: (Option<&'a TableReference>, &'a FieldRef)) -> Self {
447        Expr::from(Column::from(value))
448    }
449}
450
451impl<'a> TreeNodeContainer<'a, Self> for Expr {
452    fn apply_elements<F: FnMut(&'a Self) -> Result<TreeNodeRecursion>>(
453        &'a self,
454        mut f: F,
455    ) -> Result<TreeNodeRecursion> {
456        f(self)
457    }
458
459    fn map_elements<F: FnMut(Self) -> Result<Transformed<Self>>>(
460        self,
461        mut f: F,
462    ) -> Result<Transformed<Self>> {
463        f(self)
464    }
465}
466
467/// The metadata used in [`Field::metadata`].
468///
469/// This represents the metadata associated with an Arrow [`Field`]. The metadata consists of key-value pairs.
470///
471/// # Common Use Cases
472///
473/// Field metadata is commonly used to store:
474/// - Default values for columns when data is missing
475/// - Column descriptions or documentation
476/// - Data lineage information
477/// - Custom application-specific annotations
478/// - Encoding hints or display formatting preferences
479///
480/// # Example: Storing Default Values
481///
482/// A practical example of using field metadata is storing default values for columns
483/// that may be missing in the physical data but present in the logical schema.
484/// See the [default_column_values.rs] example implementation.
485///
486/// [default_column_values.rs]: https://github.com/apache/datafusion/blob/main/datafusion-examples/examples/custom_data_source/default_column_values.rs
487pub type SchemaFieldMetadata = std::collections::HashMap<String, String>;
488
489/// Intersects multiple metadata instances for UNION operations.
490///
491/// This function implements the intersection strategy used by UNION operations,
492/// where only metadata keys that exist in ALL inputs with identical values
493/// are preserved in the result.
494///
495/// # Union Metadata Behavior
496///
497/// Union operations require consistent metadata across all branches:
498/// - Only metadata keys present in ALL union branches are kept
499/// - For each kept key, the value must be identical across all branches
500/// - If a key has different values across branches, it is excluded from the result
501/// - If any input has no metadata, the result will be empty
502///
503/// # Arguments
504///
505/// * `metadatas` - An iterator of `SchemaFieldMetadata` instances to intersect
506///
507/// # Returns
508///
509/// A new `SchemaFieldMetadata` containing only the intersected metadata
510pub fn intersect_metadata_for_union<'a>(
511    metadatas: impl IntoIterator<Item = &'a SchemaFieldMetadata>,
512) -> SchemaFieldMetadata {
513    let mut metadatas = metadatas.into_iter();
514    let Some(mut intersected) = metadatas.next().cloned() else {
515        return Default::default();
516    };
517
518    for metadata in metadatas {
519        // Only keep keys that exist in both with the same value
520        intersected.retain(|k, v| metadata.get(k) == Some(v));
521    }
522
523    intersected
524}
525
526/// UNNEST expression.
527#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
528pub struct Unnest {
529    pub expr: Box<Expr>,
530}
531
532impl Unnest {
533    /// Create a new Unnest expression.
534    pub fn new(expr: Expr) -> Self {
535        Self {
536            expr: Box::new(expr),
537        }
538    }
539
540    /// Create a new Unnest expression.
541    pub fn new_boxed(boxed: Box<Expr>) -> Self {
542        Self { expr: boxed }
543    }
544}
545
546/// Alias expression
547#[derive(Clone, PartialEq, Eq, Debug)]
548pub struct Alias {
549    pub expr: Box<Expr>,
550    pub relation: Option<TableReference>,
551    pub name: String,
552    pub metadata: Option<FieldMetadata>,
553}
554
555impl Hash for Alias {
556    fn hash<H: Hasher>(&self, state: &mut H) {
557        self.expr.hash(state);
558        self.relation.hash(state);
559        self.name.hash(state);
560    }
561}
562
563impl PartialOrd for Alias {
564    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
565        let cmp = self.expr.partial_cmp(&other.expr);
566        let Some(Ordering::Equal) = cmp else {
567            return cmp;
568        };
569        let cmp = self.relation.partial_cmp(&other.relation);
570        let Some(Ordering::Equal) = cmp else {
571            return cmp;
572        };
573        self.name
574            .partial_cmp(&other.name)
575            // TODO (https://github.com/apache/datafusion/issues/17477) avoid recomparing all fields
576            .filter(|cmp| *cmp != Ordering::Equal || self == other)
577    }
578}
579
580impl Alias {
581    /// Create an alias with an optional schema/field qualifier.
582    pub fn new(
583        expr: Expr,
584        relation: Option<impl Into<TableReference>>,
585        name: impl Into<String>,
586    ) -> Self {
587        Self {
588            expr: Box::new(expr),
589            relation: relation.map(|r| r.into()),
590            name: name.into(),
591            metadata: None,
592        }
593    }
594
595    pub fn with_metadata(mut self, metadata: Option<FieldMetadata>) -> Self {
596        self.metadata = metadata;
597        self
598    }
599}
600
601/// Binary expression
602#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
603pub struct BinaryExpr {
604    /// Left-hand side of the expression
605    pub left: Box<Expr>,
606    /// The comparison operator
607    pub op: Operator,
608    /// Right-hand side of the expression
609    pub right: Box<Expr>,
610}
611
612impl BinaryExpr {
613    /// Create a new binary expression
614    pub fn new(left: Box<Expr>, op: Operator, right: Box<Expr>) -> Self {
615        Self { left, op, right }
616    }
617}
618
619impl Display for BinaryExpr {
620    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
621        // Put parentheses around child binary expressions so that we can see the difference
622        // between `(a OR b) AND c` and `a OR (b AND c)`. We only insert parentheses when needed,
623        // based on operator precedence. For example, `(a AND b) OR c` and `a AND b OR c` are
624        // equivalent and the parentheses are not necessary.
625
626        fn write_child(
627            f: &mut Formatter<'_>,
628            expr: &Expr,
629            precedence: u8,
630        ) -> fmt::Result {
631            match expr {
632                Expr::BinaryExpr(child) => {
633                    let p = child.op.precedence();
634                    if p == 0 || p < precedence {
635                        write!(f, "({child})")?;
636                    } else {
637                        write!(f, "{child}")?;
638                    }
639                }
640                _ => write!(f, "{expr}")?,
641            }
642            Ok(())
643        }
644
645        let precedence = self.op.precedence();
646        write_child(f, self.left.as_ref(), precedence)?;
647        write!(f, " {} ", self.op)?;
648        write_child(f, self.right.as_ref(), precedence)
649    }
650}
651
652/// CASE expression
653///
654/// The CASE expression is similar to a series of nested if/else and there are two forms that
655/// can be used. The first form consists of a series of boolean "when" expressions with
656/// corresponding "then" expressions, and an optional "else" expression.
657///
658/// ```text
659/// CASE WHEN condition THEN result
660///      [WHEN ...]
661///      [ELSE result]
662/// END
663/// ```
664///
665/// The second form uses a base expression and then a series of "when" clauses that match on a
666/// literal value.
667///
668/// ```text
669/// CASE expression
670///     WHEN value THEN result
671///     [WHEN ...]
672///     [ELSE result]
673/// END
674/// ```
675#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Hash)]
676pub struct Case {
677    /// Optional base expression that can be compared to literal values in the "when" expressions
678    pub expr: Option<Box<Expr>>,
679    /// One or more when/then expressions
680    pub when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
681    /// Optional "else" expression
682    pub else_expr: Option<Box<Expr>>,
683}
684
685impl Case {
686    /// Create a new Case expression
687    pub fn new(
688        expr: Option<Box<Expr>>,
689        when_then_expr: Vec<(Box<Expr>, Box<Expr>)>,
690        else_expr: Option<Box<Expr>>,
691    ) -> Self {
692        Self {
693            expr,
694            when_then_expr,
695            else_expr,
696        }
697    }
698}
699
700/// LIKE expression
701#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
702pub struct Like {
703    pub negated: bool,
704    pub expr: Box<Expr>,
705    pub pattern: Box<Expr>,
706    pub escape_char: Option<char>,
707    /// Whether to ignore case on comparing
708    pub case_insensitive: bool,
709}
710
711impl Like {
712    /// Create a new Like expression
713    pub fn new(
714        negated: bool,
715        expr: Box<Expr>,
716        pattern: Box<Expr>,
717        escape_char: Option<char>,
718        case_insensitive: bool,
719    ) -> Self {
720        Self {
721            negated,
722            expr,
723            pattern,
724            escape_char,
725            case_insensitive,
726        }
727    }
728}
729
730/// BETWEEN expression
731#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
732pub struct Between {
733    /// The value to compare
734    pub expr: Box<Expr>,
735    /// Whether the expression is negated
736    pub negated: bool,
737    /// The low end of the range
738    pub low: Box<Expr>,
739    /// The high end of the range
740    pub high: Box<Expr>,
741}
742
743impl Between {
744    /// Create a new Between expression
745    pub fn new(expr: Box<Expr>, negated: bool, low: Box<Expr>, high: Box<Expr>) -> Self {
746        Self {
747            expr,
748            negated,
749            low,
750            high,
751        }
752    }
753}
754
755/// Invoke a [`ScalarUDF`] with a set of arguments
756///
757/// [`ScalarUDF`]: crate::ScalarUDF
758#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
759pub struct ScalarFunction {
760    /// The function
761    pub func: Arc<crate::ScalarUDF>,
762    /// List of expressions to feed to the functions as arguments
763    pub args: Vec<Expr>,
764}
765
766impl ScalarFunction {
767    // return the Function's name
768    pub fn name(&self) -> &str {
769        self.func.name()
770    }
771}
772
773impl ScalarFunction {
774    /// Create a new `ScalarFunction` from a [`ScalarUDF`]
775    ///
776    /// [`ScalarUDF`]: crate::ScalarUDF
777    pub fn new_udf(udf: Arc<crate::ScalarUDF>, args: Vec<Expr>) -> Self {
778        Self { func: udf, args }
779    }
780}
781
782/// Access a sub field of a nested type, such as `Field` or `List`
783#[derive(Clone, PartialEq, Eq, Hash, Debug)]
784pub enum GetFieldAccess {
785    /// Named field, for example `struct["name"]`
786    NamedStructField { name: ScalarValue },
787    /// Single list index, for example: `list[i]`
788    ListIndex { key: Box<Expr> },
789    /// List stride, for example `list[i:j:k]`
790    ListRange {
791        start: Box<Expr>,
792        stop: Box<Expr>,
793        stride: Box<Expr>,
794    },
795}
796
797/// Cast expression
798#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
799pub struct Cast {
800    /// The expression being cast
801    pub expr: Box<Expr>,
802    /// The `DataType` the expression will yield
803    pub data_type: DataType,
804}
805
806impl Cast {
807    /// Create a new Cast expression
808    pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
809        Self { expr, data_type }
810    }
811}
812
813/// TryCast Expression
814#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
815pub struct TryCast {
816    /// The expression being cast
817    pub expr: Box<Expr>,
818    /// The `DataType` the expression will yield
819    pub data_type: DataType,
820}
821
822impl TryCast {
823    /// Create a new TryCast expression
824    pub fn new(expr: Box<Expr>, data_type: DataType) -> Self {
825        Self { expr, data_type }
826    }
827}
828
829/// SORT expression
830#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
831pub struct Sort {
832    /// The expression to sort on
833    pub expr: Expr,
834    /// The direction of the sort
835    pub asc: bool,
836    /// Whether to put Nulls before all other data values
837    pub nulls_first: bool,
838}
839
840impl Sort {
841    /// Create a new Sort expression
842    pub fn new(expr: Expr, asc: bool, nulls_first: bool) -> Self {
843        Self {
844            expr,
845            asc,
846            nulls_first,
847        }
848    }
849
850    /// Create a new Sort expression with the opposite sort direction
851    pub fn reverse(&self) -> Self {
852        Self {
853            expr: self.expr.clone(),
854            asc: !self.asc,
855            nulls_first: !self.nulls_first,
856        }
857    }
858
859    /// Replaces the Sort expressions with `expr`
860    pub fn with_expr(&self, expr: Expr) -> Self {
861        Self {
862            expr,
863            asc: self.asc,
864            nulls_first: self.nulls_first,
865        }
866    }
867}
868
869impl Display for Sort {
870    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
871        write!(f, "{}", self.expr)?;
872        if self.asc {
873            write!(f, " ASC")?;
874        } else {
875            write!(f, " DESC")?;
876        }
877        if self.nulls_first {
878            write!(f, " NULLS FIRST")?;
879        } else {
880            write!(f, " NULLS LAST")?;
881        }
882        Ok(())
883    }
884}
885
886impl<'a> TreeNodeContainer<'a, Expr> for Sort {
887    fn apply_elements<F: FnMut(&'a Expr) -> Result<TreeNodeRecursion>>(
888        &'a self,
889        f: F,
890    ) -> Result<TreeNodeRecursion> {
891        self.expr.apply_elements(f)
892    }
893
894    fn map_elements<F: FnMut(Expr) -> Result<Transformed<Expr>>>(
895        self,
896        f: F,
897    ) -> Result<Transformed<Self>> {
898        self.expr
899            .map_elements(f)?
900            .map_data(|expr| Ok(Self { expr, ..self }))
901    }
902}
903
904/// Aggregate function
905///
906/// See also  [`ExprFunctionExt`] to set these fields on `Expr`
907///
908/// [`ExprFunctionExt`]: crate::expr_fn::ExprFunctionExt
909#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
910pub struct AggregateFunction {
911    /// Name of the function
912    pub func: Arc<AggregateUDF>,
913    pub params: AggregateFunctionParams,
914}
915
916#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
917pub struct AggregateFunctionParams {
918    pub args: Vec<Expr>,
919    /// Whether this is a DISTINCT aggregation or not
920    pub distinct: bool,
921    /// Optional filter
922    pub filter: Option<Box<Expr>>,
923    /// Optional ordering
924    pub order_by: Vec<Sort>,
925    pub null_treatment: Option<NullTreatment>,
926}
927
928impl AggregateFunction {
929    /// Create a new AggregateFunction expression with a user-defined function (UDF)
930    pub fn new_udf(
931        func: Arc<AggregateUDF>,
932        args: Vec<Expr>,
933        distinct: bool,
934        filter: Option<Box<Expr>>,
935        order_by: Vec<Sort>,
936        null_treatment: Option<NullTreatment>,
937    ) -> Self {
938        Self {
939            func,
940            params: AggregateFunctionParams {
941                args,
942                distinct,
943                filter,
944                order_by,
945                null_treatment,
946            },
947        }
948    }
949}
950
951/// A function used as a SQL window function
952///
953/// In SQL, you can use:
954/// - Actual window functions ([`WindowUDF`])
955/// - Normal aggregate functions ([`AggregateUDF`])
956#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
957pub enum WindowFunctionDefinition {
958    /// A user defined aggregate function
959    AggregateUDF(Arc<AggregateUDF>),
960    /// A user defined window function
961    WindowUDF(Arc<WindowUDF>),
962}
963
964impl WindowFunctionDefinition {
965    /// Returns the datatype of the window function
966    pub fn return_field(
967        &self,
968        input_expr_fields: &[FieldRef],
969        display_name: &str,
970    ) -> Result<FieldRef> {
971        match self {
972            WindowFunctionDefinition::AggregateUDF(fun) => {
973                fun.return_field(input_expr_fields)
974            }
975            WindowFunctionDefinition::WindowUDF(fun) => {
976                fun.field(WindowUDFFieldArgs::new(input_expr_fields, display_name))
977            }
978        }
979    }
980
981    /// The signatures supported by the function `fun`.
982    pub fn signature(&self) -> Signature {
983        match self {
984            WindowFunctionDefinition::AggregateUDF(fun) => fun.signature().clone(),
985            WindowFunctionDefinition::WindowUDF(fun) => fun.signature().clone(),
986        }
987    }
988
989    /// Function's name for display
990    pub fn name(&self) -> &str {
991        match self {
992            WindowFunctionDefinition::WindowUDF(fun) => fun.name(),
993            WindowFunctionDefinition::AggregateUDF(fun) => fun.name(),
994        }
995    }
996
997    /// Return the inner window simplification function, if any
998    ///
999    /// See [`WindowFunctionSimplification`] for more information
1000    pub fn simplify(&self) -> Option<WindowFunctionSimplification> {
1001        match self {
1002            WindowFunctionDefinition::AggregateUDF(_) => None,
1003            WindowFunctionDefinition::WindowUDF(udwf) => udwf.simplify(),
1004        }
1005    }
1006}
1007
1008impl Display for WindowFunctionDefinition {
1009    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1010        match self {
1011            WindowFunctionDefinition::AggregateUDF(fun) => Display::fmt(fun, f),
1012            WindowFunctionDefinition::WindowUDF(fun) => Display::fmt(fun, f),
1013        }
1014    }
1015}
1016
1017impl From<Arc<AggregateUDF>> for WindowFunctionDefinition {
1018    fn from(value: Arc<AggregateUDF>) -> Self {
1019        Self::AggregateUDF(value)
1020    }
1021}
1022
1023impl From<Arc<WindowUDF>> for WindowFunctionDefinition {
1024    fn from(value: Arc<WindowUDF>) -> Self {
1025        Self::WindowUDF(value)
1026    }
1027}
1028
1029/// Window function
1030///
1031/// Holds the actual function to call [`WindowFunction`] as well as its
1032/// arguments (`args`) and the contents of the `OVER` clause:
1033///
1034/// 1. `PARTITION BY`
1035/// 2. `ORDER BY`
1036/// 3. Window frame (e.g. `ROWS 1 PRECEDING AND 1 FOLLOWING`)
1037///
1038/// See [`ExprFunctionExt`] for examples of how to create a `WindowFunction`.
1039///
1040/// [`ExprFunctionExt`]: crate::ExprFunctionExt
1041#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1042pub struct WindowFunction {
1043    /// Name of the function
1044    pub fun: WindowFunctionDefinition,
1045    pub params: WindowFunctionParams,
1046}
1047
1048#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1049pub struct WindowFunctionParams {
1050    /// List of expressions to feed to the functions as arguments
1051    pub args: Vec<Expr>,
1052    /// List of partition by expressions
1053    pub partition_by: Vec<Expr>,
1054    /// List of order by expressions
1055    pub order_by: Vec<Sort>,
1056    /// Window frame
1057    pub window_frame: WindowFrame,
1058    /// Optional filter expression (FILTER (WHERE ...))
1059    pub filter: Option<Box<Expr>>,
1060    /// Specifies how NULL value is treated: ignore or respect
1061    pub null_treatment: Option<NullTreatment>,
1062    /// Distinct flag
1063    pub distinct: bool,
1064}
1065
1066impl WindowFunction {
1067    /// Create a new Window expression with the specified argument an
1068    /// empty `OVER` clause
1069    pub fn new(fun: impl Into<WindowFunctionDefinition>, args: Vec<Expr>) -> Self {
1070        Self {
1071            fun: fun.into(),
1072            params: WindowFunctionParams {
1073                args,
1074                partition_by: Vec::default(),
1075                order_by: Vec::default(),
1076                window_frame: WindowFrame::new(None),
1077                filter: None,
1078                null_treatment: None,
1079                distinct: false,
1080            },
1081        }
1082    }
1083
1084    /// Return the inner window simplification function, if any
1085    ///
1086    /// See [`WindowFunctionSimplification`] for more information
1087    pub fn simplify(&self) -> Option<WindowFunctionSimplification> {
1088        self.fun.simplify()
1089    }
1090}
1091
1092/// EXISTS expression
1093#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1094pub struct Exists {
1095    /// Subquery that will produce a single column of data
1096    pub subquery: Subquery,
1097    /// Whether the expression is negated
1098    pub negated: bool,
1099}
1100
1101impl Exists {
1102    // Create a new Exists expression.
1103    pub fn new(subquery: Subquery, negated: bool) -> Self {
1104        Self { subquery, negated }
1105    }
1106}
1107
1108/// Whether the set comparison uses `ANY`/`SOME` or `ALL`
1109#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Hash, Debug)]
1110pub enum SetQuantifier {
1111    /// `ANY` (or `SOME`)
1112    Any,
1113    /// `ALL`
1114    All,
1115}
1116
1117impl Display for SetQuantifier {
1118    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1119        match self {
1120            SetQuantifier::Any => write!(f, "ANY"),
1121            SetQuantifier::All => write!(f, "ALL"),
1122        }
1123    }
1124}
1125
1126/// Set comparison subquery (e.g. `= ANY`, `> ALL`)
1127#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1128pub struct SetComparison {
1129    /// The expression to compare
1130    pub expr: Box<Expr>,
1131    /// Subquery that will produce a single column of data to compare against
1132    pub subquery: Subquery,
1133    /// Comparison operator (e.g. `=`, `>`, `<`)
1134    pub op: Operator,
1135    /// Quantifier (`ANY`/`ALL`)
1136    pub quantifier: SetQuantifier,
1137}
1138
1139impl SetComparison {
1140    /// Create a new set comparison expression
1141    pub fn new(
1142        expr: Box<Expr>,
1143        subquery: Subquery,
1144        op: Operator,
1145        quantifier: SetQuantifier,
1146    ) -> Self {
1147        Self {
1148            expr,
1149            subquery,
1150            op,
1151            quantifier,
1152        }
1153    }
1154}
1155
1156/// InList expression
1157#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1158pub struct InList {
1159    /// The expression to compare
1160    pub expr: Box<Expr>,
1161    /// The list of values to compare against
1162    pub list: Vec<Expr>,
1163    /// Whether the expression is negated
1164    pub negated: bool,
1165}
1166
1167impl InList {
1168    /// Create a new InList expression
1169    pub fn new(expr: Box<Expr>, list: Vec<Expr>, negated: bool) -> Self {
1170        Self {
1171            expr,
1172            list,
1173            negated,
1174        }
1175    }
1176}
1177
1178/// IN subquery
1179#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1180pub struct InSubquery {
1181    /// The expression to compare
1182    pub expr: Box<Expr>,
1183    /// Subquery that will produce a single column of data to compare against
1184    pub subquery: Subquery,
1185    /// Whether the expression is negated
1186    pub negated: bool,
1187}
1188
1189impl InSubquery {
1190    /// Create a new InSubquery expression
1191    pub fn new(expr: Box<Expr>, subquery: Subquery, negated: bool) -> Self {
1192        Self {
1193            expr,
1194            subquery,
1195            negated,
1196        }
1197    }
1198}
1199
1200/// Placeholder, representing bind parameter values such as `$1` or `$name`.
1201///
1202/// The type of these parameters is inferred using [`Expr::infer_placeholder_types`]
1203/// or can be specified directly using `PREPARE` statements.
1204#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1205pub struct Placeholder {
1206    /// The identifier of the parameter, including the leading `$` (e.g, `"$1"` or `"$foo"`)
1207    pub id: String,
1208    /// The type the parameter will be filled in with
1209    pub field: Option<FieldRef>,
1210}
1211
1212impl Placeholder {
1213    /// Create a new Placeholder expression
1214    #[deprecated(since = "51.0.0", note = "Use new_with_field instead")]
1215    pub fn new(id: String, data_type: Option<DataType>) -> Self {
1216        Self {
1217            id,
1218            field: data_type.map(|dt| Arc::new(Field::new("", dt, true))),
1219        }
1220    }
1221
1222    /// Create a new Placeholder expression from a Field
1223    pub fn new_with_field(id: String, field: Option<FieldRef>) -> Self {
1224        Self { id, field }
1225    }
1226}
1227
1228/// Grouping sets
1229///
1230/// See <https://www.postgresql.org/docs/current/queries-table-expressions.html#QUERIES-GROUPING-SETS>
1231/// for Postgres definition.
1232/// See <https://spark.apache.org/docs/latest/sql-ref-syntax-qry-select-groupby.html>
1233/// for Apache Spark definition.
1234#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1235pub enum GroupingSet {
1236    /// Rollup grouping sets
1237    Rollup(Vec<Expr>),
1238    /// Cube grouping sets
1239    Cube(Vec<Expr>),
1240    /// User-defined grouping sets
1241    GroupingSets(Vec<Vec<Expr>>),
1242}
1243
1244impl GroupingSet {
1245    /// Return all distinct exprs in the grouping set. For `CUBE` and `ROLLUP` this
1246    /// is just the underlying list of exprs. For `GROUPING SET` we need to deduplicate
1247    /// the exprs in the underlying sets.
1248    pub fn distinct_expr(&self) -> Vec<&Expr> {
1249        match self {
1250            GroupingSet::Rollup(exprs) | GroupingSet::Cube(exprs) => {
1251                exprs.iter().collect()
1252            }
1253            GroupingSet::GroupingSets(groups) => {
1254                let mut exprs: Vec<&Expr> = vec![];
1255                for exp in groups.iter().flatten() {
1256                    if !exprs.contains(&exp) {
1257                        exprs.push(exp);
1258                    }
1259                }
1260                exprs
1261            }
1262        }
1263    }
1264}
1265
1266#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1267#[cfg(not(feature = "sql"))]
1268pub struct IlikeSelectItem {
1269    pub pattern: String,
1270}
1271#[cfg(not(feature = "sql"))]
1272impl Display for IlikeSelectItem {
1273    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1274        write!(f, "ILIKE '{}'", &self.pattern)?;
1275        Ok(())
1276    }
1277}
1278#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1279#[cfg(not(feature = "sql"))]
1280pub enum ExcludeSelectItem {
1281    Single(Ident),
1282    Multiple(Vec<Ident>),
1283}
1284#[cfg(not(feature = "sql"))]
1285impl Display for ExcludeSelectItem {
1286    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1287        write!(f, "EXCLUDE")?;
1288        match self {
1289            Self::Single(column) => {
1290                write!(f, " {column}")?;
1291            }
1292            Self::Multiple(columns) => {
1293                write!(f, " ({})", display_comma_separated(columns))?;
1294            }
1295        }
1296        Ok(())
1297    }
1298}
1299#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1300#[cfg(not(feature = "sql"))]
1301pub struct ExceptSelectItem {
1302    pub first_element: Ident,
1303    pub additional_elements: Vec<Ident>,
1304}
1305#[cfg(not(feature = "sql"))]
1306impl Display for ExceptSelectItem {
1307    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1308        write!(f, "EXCEPT ")?;
1309        if self.additional_elements.is_empty() {
1310            write!(f, "({})", self.first_element)?;
1311        } else {
1312            write!(
1313                f,
1314                "({}, {})",
1315                self.first_element,
1316                display_comma_separated(&self.additional_elements)
1317            )?;
1318        }
1319        Ok(())
1320    }
1321}
1322
1323pub fn display_comma_separated<T>(slice: &[T]) -> String
1324where
1325    T: Display,
1326{
1327    use itertools::Itertools;
1328    slice.iter().map(|v| format!("{v}")).join(", ")
1329}
1330
1331#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1332#[cfg(not(feature = "sql"))]
1333pub enum RenameSelectItem {
1334    Single(String),
1335    Multiple(Vec<String>),
1336}
1337#[cfg(not(feature = "sql"))]
1338impl Display for RenameSelectItem {
1339    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1340        write!(f, "RENAME")?;
1341        match self {
1342            Self::Single(column) => {
1343                write!(f, " {column}")?;
1344            }
1345            Self::Multiple(columns) => {
1346                write!(f, " ({})", display_comma_separated(columns))?;
1347            }
1348        }
1349        Ok(())
1350    }
1351}
1352
1353#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1354#[cfg(not(feature = "sql"))]
1355pub struct Ident {
1356    /// The value of the identifier without quotes.
1357    pub value: String,
1358    /// The starting quote if any. Valid quote characters are the single quote,
1359    /// double quote, backtick, and opening square bracket.
1360    pub quote_style: Option<char>,
1361    /// The span of the identifier in the original SQL string.
1362    pub span: String,
1363}
1364#[cfg(not(feature = "sql"))]
1365impl Display for Ident {
1366    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1367        write!(f, "[{}]", self.value)
1368    }
1369}
1370
1371#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug)]
1372#[cfg(not(feature = "sql"))]
1373pub struct ReplaceSelectElement {
1374    pub expr: String,
1375    pub column_name: Ident,
1376    pub as_keyword: bool,
1377}
1378#[cfg(not(feature = "sql"))]
1379impl Display for ReplaceSelectElement {
1380    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1381        if self.as_keyword {
1382            write!(f, "{} AS {}", self.expr, self.column_name)
1383        } else {
1384            write!(f, "{} {}", self.expr, self.column_name)
1385        }
1386    }
1387}
1388
1389/// Additional options for wildcards, e.g. Snowflake `EXCLUDE`/`RENAME` and Bigquery `EXCEPT`.
1390#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1391pub struct WildcardOptions {
1392    /// `[ILIKE...]`.
1393    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
1394    pub ilike: Option<IlikeSelectItem>,
1395    /// `[EXCLUDE...]`.
1396    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
1397    pub exclude: Option<ExcludeSelectItem>,
1398    /// `[EXCEPT...]`.
1399    ///  BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_except>
1400    ///  Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#except>
1401    pub except: Option<ExceptSelectItem>,
1402    /// `[REPLACE]`
1403    ///  BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
1404    ///  Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#replace>
1405    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
1406    pub replace: Option<PlannedReplaceSelectItem>,
1407    /// `[RENAME ...]`.
1408    ///  Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
1409    pub rename: Option<RenameSelectItem>,
1410}
1411
1412impl WildcardOptions {
1413    pub fn with_replace(self, replace: PlannedReplaceSelectItem) -> Self {
1414        WildcardOptions {
1415            ilike: self.ilike,
1416            exclude: self.exclude,
1417            except: self.except,
1418            replace: Some(replace),
1419            rename: self.rename,
1420        }
1421    }
1422}
1423
1424impl Display for WildcardOptions {
1425    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1426        if let Some(ilike) = &self.ilike {
1427            write!(f, " {ilike}")?;
1428        }
1429        if let Some(exclude) = &self.exclude {
1430            write!(f, " {exclude}")?;
1431        }
1432        if let Some(except) = &self.except {
1433            write!(f, " {except}")?;
1434        }
1435        if let Some(replace) = &self.replace {
1436            write!(f, " {replace}")?;
1437        }
1438        if let Some(rename) = &self.rename {
1439            write!(f, " {rename}")?;
1440        }
1441        Ok(())
1442    }
1443}
1444
1445/// The planned expressions for `REPLACE`
1446#[derive(Clone, PartialEq, Eq, PartialOrd, Hash, Debug, Default)]
1447pub struct PlannedReplaceSelectItem {
1448    /// The original ast nodes
1449    pub items: Vec<ReplaceSelectElement>,
1450    /// The expression planned from the ast nodes. They will be used when expanding the wildcard.
1451    pub planned_expressions: Vec<Expr>,
1452}
1453
1454impl Display for PlannedReplaceSelectItem {
1455    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1456        write!(f, "REPLACE")?;
1457        write!(f, " ({})", display_comma_separated(&self.items))?;
1458        Ok(())
1459    }
1460}
1461
1462impl PlannedReplaceSelectItem {
1463    pub fn items(&self) -> &[ReplaceSelectElement] {
1464        &self.items
1465    }
1466
1467    pub fn expressions(&self) -> &[Expr] {
1468        &self.planned_expressions
1469    }
1470}
1471
1472impl Expr {
1473    /// The name of the column (field) that this `Expr` will produce.
1474    ///
1475    /// For example, for a projection (e.g. `SELECT <expr>`) the resulting arrow
1476    /// [`Schema`] will have a field with this name.
1477    ///
1478    /// Note that the resulting string is subtlety different from the `Display`
1479    /// representation for certain `Expr`. Some differences:
1480    ///
1481    /// 1. [`Expr::Alias`], which shows only the alias itself
1482    /// 2. [`Expr::Cast`] / [`Expr::TryCast`], which only displays the expression
1483    ///
1484    /// # Example
1485    /// ```
1486    /// # use datafusion_expr::{col, lit};
1487    /// let expr = col("foo").eq(lit(42));
1488    /// assert_eq!("foo = Int32(42)", expr.schema_name().to_string());
1489    ///
1490    /// let expr = col("foo").alias("bar").eq(lit(11));
1491    /// assert_eq!("bar = Int32(11)", expr.schema_name().to_string());
1492    /// ```
1493    ///
1494    /// [`Schema`]: arrow::datatypes::Schema
1495    pub fn schema_name(&self) -> impl Display + '_ {
1496        SchemaDisplay(self)
1497    }
1498
1499    /// Human readable display formatting for this expression.
1500    ///
1501    /// This function is primarily used in printing the explain tree output,
1502    /// (e.g. `EXPLAIN FORMAT TREE <query>`), providing a readable format to
1503    /// show how expressions are used in physical and logical plans. See the
1504    /// [`Expr`] for other ways to format expressions
1505    ///
1506    /// Note this format is intended for human consumption rather than SQL for
1507    /// other systems. If you need  SQL to pass to other systems, consider using
1508    /// [`Unparser`].
1509    ///
1510    /// [`Unparser`]: https://docs.rs/datafusion/latest/datafusion/sql/unparser/struct.Unparser.html
1511    ///
1512    /// # Example
1513    /// ```
1514    /// # use datafusion_expr::{col, lit};
1515    /// let expr = col("foo") + lit(42);
1516    /// // For EXPLAIN output:
1517    /// // "foo + 42"
1518    /// println!("{}", expr.human_display());
1519    /// ```
1520    pub fn human_display(&self) -> impl Display + '_ {
1521        SqlDisplay(self)
1522    }
1523
1524    /// Returns the qualifier and the schema name of this expression.
1525    ///
1526    /// Used when the expression forms the output field of a certain plan.
1527    /// The result is the field's qualifier and field name in the plan's
1528    /// output schema. We can use this qualified name to reference the field.
1529    pub fn qualified_name(&self) -> (Option<TableReference>, String) {
1530        match self {
1531            Expr::Column(Column {
1532                relation,
1533                name,
1534                spans: _,
1535            }) => (relation.clone(), name.clone()),
1536            Expr::Alias(Alias { relation, name, .. }) => (relation.clone(), name.clone()),
1537            _ => (None, self.schema_name().to_string()),
1538        }
1539    }
1540
1541    /// Returns placement information for this expression.
1542    ///
1543    /// This is used by optimizers to make decisions about expression placement,
1544    /// such as whether to push expressions down through projections.
1545    pub fn placement(&self) -> ExpressionPlacement {
1546        match self {
1547            Expr::Column(_) => ExpressionPlacement::Column,
1548            Expr::Literal(_, _) => ExpressionPlacement::Literal,
1549            Expr::Alias(inner) => inner.expr.placement(),
1550            Expr::ScalarFunction(func) => {
1551                let arg_placements: Vec<_> =
1552                    func.args.iter().map(|arg| arg.placement()).collect();
1553                func.func.placement(&arg_placements)
1554            }
1555            _ => ExpressionPlacement::KeepInPlace,
1556        }
1557    }
1558
1559    /// Return String representation of the variant represented by `self`
1560    /// Useful for non-rust based bindings
1561    pub fn variant_name(&self) -> &str {
1562        match self {
1563            Expr::AggregateFunction { .. } => "AggregateFunction",
1564            Expr::Alias(..) => "Alias",
1565            Expr::Between { .. } => "Between",
1566            Expr::BinaryExpr { .. } => "BinaryExpr",
1567            Expr::Case { .. } => "Case",
1568            Expr::Cast { .. } => "Cast",
1569            Expr::Column(..) => "Column",
1570            Expr::OuterReferenceColumn(_, _) => "Outer",
1571            Expr::Exists { .. } => "Exists",
1572            Expr::GroupingSet(..) => "GroupingSet",
1573            Expr::InList { .. } => "InList",
1574            Expr::InSubquery(..) => "InSubquery",
1575            Expr::SetComparison(..) => "SetComparison",
1576            Expr::IsNotNull(..) => "IsNotNull",
1577            Expr::IsNull(..) => "IsNull",
1578            Expr::Like { .. } => "Like",
1579            Expr::SimilarTo { .. } => "RLike",
1580            Expr::IsTrue(..) => "IsTrue",
1581            Expr::IsFalse(..) => "IsFalse",
1582            Expr::IsUnknown(..) => "IsUnknown",
1583            Expr::IsNotTrue(..) => "IsNotTrue",
1584            Expr::IsNotFalse(..) => "IsNotFalse",
1585            Expr::IsNotUnknown(..) => "IsNotUnknown",
1586            Expr::Literal(..) => "Literal",
1587            Expr::Negative(..) => "Negative",
1588            Expr::Not(..) => "Not",
1589            Expr::Placeholder(_) => "Placeholder",
1590            Expr::ScalarFunction(..) => "ScalarFunction",
1591            Expr::ScalarSubquery { .. } => "ScalarSubquery",
1592            Expr::ScalarVariable(..) => "ScalarVariable",
1593            Expr::TryCast { .. } => "TryCast",
1594            Expr::WindowFunction { .. } => "WindowFunction",
1595            #[expect(deprecated)]
1596            Expr::Wildcard { .. } => "Wildcard",
1597            Expr::Unnest { .. } => "Unnest",
1598        }
1599    }
1600
1601    /// Return `self == other`
1602    pub fn eq(self, other: Expr) -> Expr {
1603        binary_expr(self, Operator::Eq, other)
1604    }
1605
1606    /// Return `self != other`
1607    pub fn not_eq(self, other: Expr) -> Expr {
1608        binary_expr(self, Operator::NotEq, other)
1609    }
1610
1611    /// Return `self > other`
1612    pub fn gt(self, other: Expr) -> Expr {
1613        binary_expr(self, Operator::Gt, other)
1614    }
1615
1616    /// Return `self >= other`
1617    pub fn gt_eq(self, other: Expr) -> Expr {
1618        binary_expr(self, Operator::GtEq, other)
1619    }
1620
1621    /// Return `self < other`
1622    pub fn lt(self, other: Expr) -> Expr {
1623        binary_expr(self, Operator::Lt, other)
1624    }
1625
1626    /// Return `self <= other`
1627    pub fn lt_eq(self, other: Expr) -> Expr {
1628        binary_expr(self, Operator::LtEq, other)
1629    }
1630
1631    /// Return `self && other`
1632    pub fn and(self, other: Expr) -> Expr {
1633        binary_expr(self, Operator::And, other)
1634    }
1635
1636    /// Return `self || other`
1637    pub fn or(self, other: Expr) -> Expr {
1638        binary_expr(self, Operator::Or, other)
1639    }
1640
1641    /// Return `self LIKE other`
1642    pub fn like(self, other: Expr) -> Expr {
1643        Expr::Like(Like::new(
1644            false,
1645            Box::new(self),
1646            Box::new(other),
1647            None,
1648            false,
1649        ))
1650    }
1651
1652    /// Return `self NOT LIKE other`
1653    pub fn not_like(self, other: Expr) -> Expr {
1654        Expr::Like(Like::new(
1655            true,
1656            Box::new(self),
1657            Box::new(other),
1658            None,
1659            false,
1660        ))
1661    }
1662
1663    /// Return `self ILIKE other`
1664    pub fn ilike(self, other: Expr) -> Expr {
1665        Expr::Like(Like::new(
1666            false,
1667            Box::new(self),
1668            Box::new(other),
1669            None,
1670            true,
1671        ))
1672    }
1673
1674    /// Return `self NOT ILIKE other`
1675    pub fn not_ilike(self, other: Expr) -> Expr {
1676        Expr::Like(Like::new(true, Box::new(self), Box::new(other), None, true))
1677    }
1678
1679    /// Return the name to use for the specific Expr
1680    pub fn name_for_alias(&self) -> Result<String> {
1681        Ok(self.schema_name().to_string())
1682    }
1683
1684    /// Ensure `expr` has the name as `original_name` by adding an
1685    /// alias if necessary.
1686    pub fn alias_if_changed(self, original_name: String) -> Result<Expr> {
1687        let new_name = self.name_for_alias()?;
1688        if new_name == original_name {
1689            return Ok(self);
1690        }
1691
1692        Ok(self.alias(original_name))
1693    }
1694
1695    /// Return `self AS name` alias expression
1696    pub fn alias(self, name: impl Into<String>) -> Expr {
1697        Expr::Alias(Alias::new(self, None::<&str>, name.into()))
1698    }
1699
1700    /// Return `self AS name` alias expression with metadata
1701    ///
1702    /// The metadata will be attached to the Arrow Schema field when the expression
1703    /// is converted to a field via `Expr.to_field()`.
1704    ///
1705    /// # Example
1706    /// ```
1707    /// # use datafusion_expr::col;
1708    /// # use std::collections::HashMap;
1709    /// # use datafusion_common::metadata::FieldMetadata;
1710    /// let metadata = HashMap::from([("key".to_string(), "value".to_string())]);
1711    /// let metadata = FieldMetadata::from(metadata);
1712    /// let expr = col("foo").alias_with_metadata("bar", Some(metadata));
1713    /// ```
1714    pub fn alias_with_metadata(
1715        self,
1716        name: impl Into<String>,
1717        metadata: Option<FieldMetadata>,
1718    ) -> Expr {
1719        Expr::Alias(Alias::new(self, None::<&str>, name.into()).with_metadata(metadata))
1720    }
1721
1722    /// Return `self AS name` alias expression with a specific qualifier
1723    pub fn alias_qualified(
1724        self,
1725        relation: Option<impl Into<TableReference>>,
1726        name: impl Into<String>,
1727    ) -> Expr {
1728        Expr::Alias(Alias::new(self, relation, name.into()))
1729    }
1730
1731    /// Return `self AS name` alias expression with a specific qualifier and metadata
1732    ///
1733    /// The metadata will be attached to the Arrow Schema field when the expression
1734    /// is converted to a field via `Expr.to_field()`.
1735    ///
1736    /// # Example
1737    /// ```
1738    /// # use datafusion_expr::col;
1739    /// # use std::collections::HashMap;
1740    /// # use datafusion_common::metadata::FieldMetadata;
1741    /// let metadata = HashMap::from([("key".to_string(), "value".to_string())]);
1742    /// let metadata = FieldMetadata::from(metadata);
1743    /// let expr =
1744    ///     col("foo").alias_qualified_with_metadata(Some("tbl"), "bar", Some(metadata));
1745    /// ```
1746    pub fn alias_qualified_with_metadata(
1747        self,
1748        relation: Option<impl Into<TableReference>>,
1749        name: impl Into<String>,
1750        metadata: Option<FieldMetadata>,
1751    ) -> Expr {
1752        Expr::Alias(Alias::new(self, relation, name.into()).with_metadata(metadata))
1753    }
1754
1755    /// Remove an alias from an expression if one exists.
1756    ///
1757    /// If the expression is not an alias, the expression is returned unchanged.
1758    /// This method does not remove aliases from nested expressions.
1759    ///
1760    /// # Example
1761    /// ```
1762    /// # use datafusion_expr::col;
1763    /// // `foo as "bar"` is unaliased to `foo`
1764    /// let expr = col("foo").alias("bar");
1765    /// assert_eq!(expr.unalias(), col("foo"));
1766    ///
1767    /// // `foo as "bar" + baz` is not unaliased
1768    /// let expr = col("foo").alias("bar") + col("baz");
1769    /// assert_eq!(expr.clone().unalias(), expr);
1770    ///
1771    /// // `foo as "bar" as "baz" is unaliased to foo as "bar"
1772    /// let expr = col("foo").alias("bar").alias("baz");
1773    /// assert_eq!(expr.unalias(), col("foo").alias("bar"));
1774    /// ```
1775    pub fn unalias(self) -> Expr {
1776        match self {
1777            Expr::Alias(alias) => *alias.expr,
1778            _ => self,
1779        }
1780    }
1781
1782    /// Recursively removed potentially multiple aliases from an expression.
1783    ///
1784    /// This method removes nested aliases and returns [`Transformed`]
1785    /// to signal if the expression was changed.
1786    ///
1787    /// # Example
1788    /// ```
1789    /// # use datafusion_expr::col;
1790    /// // `foo as "bar"` is unaliased to `foo`
1791    /// let expr = col("foo").alias("bar");
1792    /// assert_eq!(expr.unalias_nested().data, col("foo"));
1793    ///
1794    /// // `foo as "bar" + baz` is  unaliased
1795    /// let expr = col("foo").alias("bar") + col("baz");
1796    /// assert_eq!(expr.clone().unalias_nested().data, col("foo") + col("baz"));
1797    ///
1798    /// // `foo as "bar" as "baz" is unalaised to foo
1799    /// let expr = col("foo").alias("bar").alias("baz");
1800    /// assert_eq!(expr.unalias_nested().data, col("foo"));
1801    /// ```
1802    pub fn unalias_nested(self) -> Transformed<Expr> {
1803        self.transform_down_up(
1804            |expr| {
1805                // f_down: skip subqueries.  Check in f_down to avoid recursing into them
1806                let recursion = if matches!(
1807                    expr,
1808                    Expr::Exists { .. } | Expr::ScalarSubquery(_) | Expr::InSubquery(_)
1809                ) {
1810                    // Subqueries could contain aliases so don't recurse into those
1811                    TreeNodeRecursion::Jump
1812                } else {
1813                    TreeNodeRecursion::Continue
1814                };
1815                Ok(Transformed::new(expr, false, recursion))
1816            },
1817            |expr| {
1818                // f_up: unalias on up so we can remove nested aliases like
1819                // `(x as foo) as bar`
1820                if let Expr::Alias(alias) = expr {
1821                    match alias
1822                        .metadata
1823                        .as_ref()
1824                        .map(|h| h.is_empty())
1825                        .unwrap_or(true)
1826                    {
1827                        true => Ok(Transformed::yes(*alias.expr)),
1828                        false => Ok(Transformed::no(Expr::Alias(alias))),
1829                    }
1830                } else {
1831                    Ok(Transformed::no(expr))
1832                }
1833            },
1834        )
1835        // Unreachable code: internal closure doesn't return err
1836        .unwrap()
1837    }
1838
1839    /// Return `self IN <list>` if `negated` is false, otherwise
1840    /// return `self NOT IN <list>`.a
1841    pub fn in_list(self, list: Vec<Expr>, negated: bool) -> Expr {
1842        Expr::InList(InList::new(Box::new(self), list, negated))
1843    }
1844
1845    /// Return `IsNull(Box(self))
1846    pub fn is_null(self) -> Expr {
1847        Expr::IsNull(Box::new(self))
1848    }
1849
1850    /// Return `IsNotNull(Box(self))
1851    pub fn is_not_null(self) -> Expr {
1852        Expr::IsNotNull(Box::new(self))
1853    }
1854
1855    /// Create a sort configuration from an existing expression.
1856    ///
1857    /// ```
1858    /// # use datafusion_expr::col;
1859    /// let sort_expr = col("foo").sort(true, true); // SORT ASC NULLS_FIRST
1860    /// ```
1861    pub fn sort(self, asc: bool, nulls_first: bool) -> Sort {
1862        Sort::new(self, asc, nulls_first)
1863    }
1864
1865    /// Return `IsTrue(Box(self))`
1866    pub fn is_true(self) -> Expr {
1867        Expr::IsTrue(Box::new(self))
1868    }
1869
1870    /// Return `IsNotTrue(Box(self))`
1871    pub fn is_not_true(self) -> Expr {
1872        Expr::IsNotTrue(Box::new(self))
1873    }
1874
1875    /// Return `IsFalse(Box(self))`
1876    pub fn is_false(self) -> Expr {
1877        Expr::IsFalse(Box::new(self))
1878    }
1879
1880    /// Return `IsNotFalse(Box(self))`
1881    pub fn is_not_false(self) -> Expr {
1882        Expr::IsNotFalse(Box::new(self))
1883    }
1884
1885    /// Return `IsUnknown(Box(self))`
1886    pub fn is_unknown(self) -> Expr {
1887        Expr::IsUnknown(Box::new(self))
1888    }
1889
1890    /// Return `IsNotUnknown(Box(self))`
1891    pub fn is_not_unknown(self) -> Expr {
1892        Expr::IsNotUnknown(Box::new(self))
1893    }
1894
1895    /// return `self BETWEEN low AND high`
1896    pub fn between(self, low: Expr, high: Expr) -> Expr {
1897        Expr::Between(Between::new(
1898            Box::new(self),
1899            false,
1900            Box::new(low),
1901            Box::new(high),
1902        ))
1903    }
1904
1905    /// Return `self NOT BETWEEN low AND high`
1906    pub fn not_between(self, low: Expr, high: Expr) -> Expr {
1907        Expr::Between(Between::new(
1908            Box::new(self),
1909            true,
1910            Box::new(low),
1911            Box::new(high),
1912        ))
1913    }
1914    /// Return a reference to the inner `Column` if any
1915    ///
1916    /// returns `None` if the expression is not a `Column`
1917    ///
1918    /// Note: None may be returned for expressions that are not `Column` but
1919    /// are convertible to `Column` such as `Cast` expressions.
1920    ///
1921    /// Example
1922    /// ```
1923    /// # use datafusion_common::Column;
1924    /// use datafusion_expr::{col, Expr};
1925    /// let expr = col("foo");
1926    /// assert_eq!(expr.try_as_col(), Some(&Column::from("foo")));
1927    ///
1928    /// let expr = col("foo").alias("bar");
1929    /// assert_eq!(expr.try_as_col(), None);
1930    /// ```
1931    pub fn try_as_col(&self) -> Option<&Column> {
1932        if let Expr::Column(it) = self {
1933            Some(it)
1934        } else {
1935            None
1936        }
1937    }
1938
1939    /// Returns the inner `Column` if any. This is a specialized version of
1940    /// [`Self::try_as_col`] that take Cast expressions into account when the
1941    /// expression is as on condition for joins.
1942    ///
1943    /// Called this method when you are sure that the expression is a `Column`
1944    /// or a `Cast` expression that wraps a `Column`.
1945    pub fn get_as_join_column(&self) -> Option<&Column> {
1946        match self {
1947            Expr::Column(c) => Some(c),
1948            Expr::Cast(Cast { expr, .. }) => match &**expr {
1949                Expr::Column(c) => Some(c),
1950                _ => None,
1951            },
1952            _ => None,
1953        }
1954    }
1955
1956    /// Return all references to columns in this expression.
1957    ///
1958    /// # Example
1959    /// ```
1960    /// # use std::collections::HashSet;
1961    /// # use datafusion_common::Column;
1962    /// # use datafusion_expr::col;
1963    /// // For an expression `a + (b * a)`
1964    /// let expr = col("a") + (col("b") * col("a"));
1965    /// let refs = expr.column_refs();
1966    /// // refs contains "a" and "b"
1967    /// assert_eq!(refs.len(), 2);
1968    /// assert!(refs.contains(&Column::new_unqualified("a")));
1969    /// assert!(refs.contains(&Column::new_unqualified("b")));
1970    /// ```
1971    pub fn column_refs(&self) -> HashSet<&Column> {
1972        let mut using_columns = HashSet::new();
1973        self.add_column_refs(&mut using_columns);
1974        using_columns
1975    }
1976
1977    /// Adds references to all columns in this expression to the set
1978    ///
1979    /// See [`Self::column_refs`] for details
1980    pub fn add_column_refs<'a>(&'a self, set: &mut HashSet<&'a Column>) {
1981        self.apply(|expr| {
1982            if let Expr::Column(col) = expr {
1983                set.insert(col);
1984            }
1985            Ok(TreeNodeRecursion::Continue)
1986        })
1987        .expect("traversal is infallible");
1988    }
1989
1990    /// Return all references to columns and their occurrence counts in the expression.
1991    ///
1992    /// # Example
1993    /// ```
1994    /// # use std::collections::HashMap;
1995    /// # use datafusion_common::Column;
1996    /// # use datafusion_expr::col;
1997    /// // For an expression `a + (b * a)`
1998    /// let expr = col("a") + (col("b") * col("a"));
1999    /// let mut refs = expr.column_refs_counts();
2000    /// // refs contains "a" and "b"
2001    /// assert_eq!(refs.len(), 2);
2002    /// assert_eq!(*refs.get(&Column::new_unqualified("a")).unwrap(), 2);
2003    /// assert_eq!(*refs.get(&Column::new_unqualified("b")).unwrap(), 1);
2004    /// ```
2005    pub fn column_refs_counts(&self) -> HashMap<&Column, usize> {
2006        let mut map = HashMap::new();
2007        self.add_column_ref_counts(&mut map);
2008        map
2009    }
2010
2011    /// Adds references to all columns and their occurrence counts in the expression to
2012    /// the map.
2013    ///
2014    /// See [`Self::column_refs_counts`] for details
2015    pub fn add_column_ref_counts<'a>(&'a self, map: &mut HashMap<&'a Column, usize>) {
2016        self.apply(|expr| {
2017            if let Expr::Column(col) = expr {
2018                *map.entry(col).or_default() += 1;
2019            }
2020            Ok(TreeNodeRecursion::Continue)
2021        })
2022        .expect("traversal is infallible");
2023    }
2024
2025    /// Returns true if there are any column references in this Expr
2026    pub fn any_column_refs(&self) -> bool {
2027        self.exists(|expr| Ok(matches!(expr, Expr::Column(_))))
2028            .expect("exists closure is infallible")
2029    }
2030
2031    /// Return true if the expression contains out reference(correlated) expressions.
2032    pub fn contains_outer(&self) -> bool {
2033        self.exists(|expr| Ok(matches!(expr, Expr::OuterReferenceColumn { .. })))
2034            .expect("exists closure is infallible")
2035    }
2036
2037    /// Returns true if the expression node is volatile, i.e. whether it can return
2038    /// different results when evaluated multiple times with the same input.
2039    /// Note: unlike [`Self::is_volatile`], this function does not consider inputs:
2040    /// - `rand()` returns `true`,
2041    /// - `a + rand()` returns `false`
2042    pub fn is_volatile_node(&self) -> bool {
2043        matches!(self, Expr::ScalarFunction(func) if func.func.signature().volatility == Volatility::Volatile)
2044    }
2045
2046    /// Returns true if the expression is volatile, i.e. whether it can return different
2047    /// results when evaluated multiple times with the same input.
2048    ///
2049    /// For example the function call `RANDOM()` is volatile as each call will
2050    /// return a different value.
2051    ///
2052    /// See [`Volatility`] for more information.
2053    pub fn is_volatile(&self) -> bool {
2054        self.exists(|expr| Ok(expr.is_volatile_node()))
2055            .expect("exists closure is infallible")
2056    }
2057
2058    /// Recursively find all [`Expr::Placeholder`] expressions, and
2059    /// to infer their [`DataType`] from the context of their use.
2060    ///
2061    /// For example, given an expression like `<int32> = $0` will infer `$0` to
2062    /// have type `int32`.
2063    ///
2064    /// Returns transformed expression and flag that is true if expression contains
2065    /// at least one placeholder.
2066    pub fn infer_placeholder_types(self, schema: &DFSchema) -> Result<(Expr, bool)> {
2067        let mut has_placeholder = false;
2068        self.transform(|mut expr| {
2069            match &mut expr {
2070                // Default to assuming the arguments are the same type
2071                Expr::BinaryExpr(BinaryExpr { left, op: _, right }) => {
2072                    rewrite_placeholder(left.as_mut(), right.as_ref(), schema)?;
2073                    rewrite_placeholder(right.as_mut(), left.as_ref(), schema)?;
2074                }
2075                Expr::Between(Between {
2076                    expr,
2077                    negated: _,
2078                    low,
2079                    high,
2080                }) => {
2081                    rewrite_placeholder(low.as_mut(), expr.as_ref(), schema)?;
2082                    rewrite_placeholder(high.as_mut(), expr.as_ref(), schema)?;
2083                }
2084                Expr::InList(InList {
2085                    expr,
2086                    list,
2087                    negated: _,
2088                }) => {
2089                    for item in list.iter_mut() {
2090                        rewrite_placeholder(item, expr.as_ref(), schema)?;
2091                    }
2092                }
2093                Expr::Like(Like { expr, pattern, .. })
2094                | Expr::SimilarTo(Like { expr, pattern, .. }) => {
2095                    rewrite_placeholder(pattern.as_mut(), expr.as_ref(), schema)?;
2096                }
2097                Expr::Placeholder(_) => {
2098                    has_placeholder = true;
2099                }
2100                _ => {}
2101            }
2102            Ok(Transformed::yes(expr))
2103        })
2104        .data()
2105        .map(|data| (data, has_placeholder))
2106    }
2107
2108    /// Returns true if some of this `exprs` subexpressions may not be evaluated
2109    /// and thus any side effects (like divide by zero) may not be encountered
2110    pub fn short_circuits(&self) -> bool {
2111        match self {
2112            Expr::ScalarFunction(ScalarFunction { func, .. }) => func.short_circuits(),
2113            Expr::BinaryExpr(BinaryExpr { op, .. }) => {
2114                matches!(op, Operator::And | Operator::Or)
2115            }
2116            Expr::Case { .. } => true,
2117            // Use explicit pattern match instead of a default
2118            // implementation, so that in the future if someone adds
2119            // new Expr types, they will check here as well
2120            // TODO: remove the next line after `Expr::Wildcard` is removed
2121            #[expect(deprecated)]
2122            Expr::AggregateFunction(..)
2123            | Expr::Alias(..)
2124            | Expr::Between(..)
2125            | Expr::Cast(..)
2126            | Expr::Column(..)
2127            | Expr::Exists(..)
2128            | Expr::GroupingSet(..)
2129            | Expr::InList(..)
2130            | Expr::InSubquery(..)
2131            | Expr::SetComparison(..)
2132            | Expr::IsFalse(..)
2133            | Expr::IsNotFalse(..)
2134            | Expr::IsNotNull(..)
2135            | Expr::IsNotTrue(..)
2136            | Expr::IsNotUnknown(..)
2137            | Expr::IsNull(..)
2138            | Expr::IsTrue(..)
2139            | Expr::IsUnknown(..)
2140            | Expr::Like(..)
2141            | Expr::ScalarSubquery(..)
2142            | Expr::ScalarVariable(_, _)
2143            | Expr::SimilarTo(..)
2144            | Expr::Not(..)
2145            | Expr::Negative(..)
2146            | Expr::OuterReferenceColumn(_, _)
2147            | Expr::TryCast(..)
2148            | Expr::Unnest(..)
2149            | Expr::Wildcard { .. }
2150            | Expr::WindowFunction(..)
2151            | Expr::Literal(..)
2152            | Expr::Placeholder(..) => false,
2153        }
2154    }
2155
2156    /// Returns a reference to the set of locations in the SQL query where this
2157    /// expression appears, if known. [`None`] is returned if the expression
2158    /// type doesn't support tracking locations yet.
2159    pub fn spans(&self) -> Option<&Spans> {
2160        match self {
2161            Expr::Column(col) => Some(&col.spans),
2162            _ => None,
2163        }
2164    }
2165
2166    /// Check if the Expr is literal and get the literal value if it is.
2167    pub fn as_literal(&self) -> Option<&ScalarValue> {
2168        if let Expr::Literal(lit, _) = self {
2169            Some(lit)
2170        } else {
2171            None
2172        }
2173    }
2174}
2175
2176impl Normalizeable for Expr {
2177    fn can_normalize(&self) -> bool {
2178        #[expect(clippy::match_like_matches_macro)]
2179        match self {
2180            Expr::BinaryExpr(BinaryExpr {
2181                op:
2182                    _op @ (Operator::Plus
2183                    | Operator::Multiply
2184                    | Operator::BitwiseAnd
2185                    | Operator::BitwiseOr
2186                    | Operator::BitwiseXor
2187                    | Operator::Eq
2188                    | Operator::NotEq),
2189                ..
2190            }) => true,
2191            _ => false,
2192        }
2193    }
2194}
2195
2196impl NormalizeEq for Expr {
2197    fn normalize_eq(&self, other: &Self) -> bool {
2198        match (self, other) {
2199            (
2200                Expr::BinaryExpr(BinaryExpr {
2201                    left: self_left,
2202                    op: self_op,
2203                    right: self_right,
2204                }),
2205                Expr::BinaryExpr(BinaryExpr {
2206                    left: other_left,
2207                    op: other_op,
2208                    right: other_right,
2209                }),
2210            ) => {
2211                if self_op != other_op {
2212                    return false;
2213                }
2214
2215                if matches!(
2216                    self_op,
2217                    Operator::Plus
2218                        | Operator::Multiply
2219                        | Operator::BitwiseAnd
2220                        | Operator::BitwiseOr
2221                        | Operator::BitwiseXor
2222                        | Operator::Eq
2223                        | Operator::NotEq
2224                ) {
2225                    (self_left.normalize_eq(other_left)
2226                        && self_right.normalize_eq(other_right))
2227                        || (self_left.normalize_eq(other_right)
2228                            && self_right.normalize_eq(other_left))
2229                } else {
2230                    self_left.normalize_eq(other_left)
2231                        && self_right.normalize_eq(other_right)
2232                }
2233            }
2234            (
2235                Expr::Alias(Alias {
2236                    expr: self_expr,
2237                    relation: self_relation,
2238                    name: self_name,
2239                    ..
2240                }),
2241                Expr::Alias(Alias {
2242                    expr: other_expr,
2243                    relation: other_relation,
2244                    name: other_name,
2245                    ..
2246                }),
2247            ) => {
2248                self_name == other_name
2249                    && self_relation == other_relation
2250                    && self_expr.normalize_eq(other_expr)
2251            }
2252            (
2253                Expr::Like(Like {
2254                    negated: self_negated,
2255                    expr: self_expr,
2256                    pattern: self_pattern,
2257                    escape_char: self_escape_char,
2258                    case_insensitive: self_case_insensitive,
2259                }),
2260                Expr::Like(Like {
2261                    negated: other_negated,
2262                    expr: other_expr,
2263                    pattern: other_pattern,
2264                    escape_char: other_escape_char,
2265                    case_insensitive: other_case_insensitive,
2266                }),
2267            )
2268            | (
2269                Expr::SimilarTo(Like {
2270                    negated: self_negated,
2271                    expr: self_expr,
2272                    pattern: self_pattern,
2273                    escape_char: self_escape_char,
2274                    case_insensitive: self_case_insensitive,
2275                }),
2276                Expr::SimilarTo(Like {
2277                    negated: other_negated,
2278                    expr: other_expr,
2279                    pattern: other_pattern,
2280                    escape_char: other_escape_char,
2281                    case_insensitive: other_case_insensitive,
2282                }),
2283            ) => {
2284                self_negated == other_negated
2285                    && self_escape_char == other_escape_char
2286                    && self_case_insensitive == other_case_insensitive
2287                    && self_expr.normalize_eq(other_expr)
2288                    && self_pattern.normalize_eq(other_pattern)
2289            }
2290            (Expr::Not(self_expr), Expr::Not(other_expr))
2291            | (Expr::IsNull(self_expr), Expr::IsNull(other_expr))
2292            | (Expr::IsTrue(self_expr), Expr::IsTrue(other_expr))
2293            | (Expr::IsFalse(self_expr), Expr::IsFalse(other_expr))
2294            | (Expr::IsUnknown(self_expr), Expr::IsUnknown(other_expr))
2295            | (Expr::IsNotNull(self_expr), Expr::IsNotNull(other_expr))
2296            | (Expr::IsNotTrue(self_expr), Expr::IsNotTrue(other_expr))
2297            | (Expr::IsNotFalse(self_expr), Expr::IsNotFalse(other_expr))
2298            | (Expr::IsNotUnknown(self_expr), Expr::IsNotUnknown(other_expr))
2299            | (Expr::Negative(self_expr), Expr::Negative(other_expr))
2300            | (
2301                Expr::Unnest(Unnest { expr: self_expr }),
2302                Expr::Unnest(Unnest { expr: other_expr }),
2303            ) => self_expr.normalize_eq(other_expr),
2304            (
2305                Expr::Between(Between {
2306                    expr: self_expr,
2307                    negated: self_negated,
2308                    low: self_low,
2309                    high: self_high,
2310                }),
2311                Expr::Between(Between {
2312                    expr: other_expr,
2313                    negated: other_negated,
2314                    low: other_low,
2315                    high: other_high,
2316                }),
2317            ) => {
2318                self_negated == other_negated
2319                    && self_expr.normalize_eq(other_expr)
2320                    && self_low.normalize_eq(other_low)
2321                    && self_high.normalize_eq(other_high)
2322            }
2323            (
2324                Expr::Cast(Cast {
2325                    expr: self_expr,
2326                    data_type: self_data_type,
2327                }),
2328                Expr::Cast(Cast {
2329                    expr: other_expr,
2330                    data_type: other_data_type,
2331                }),
2332            )
2333            | (
2334                Expr::TryCast(TryCast {
2335                    expr: self_expr,
2336                    data_type: self_data_type,
2337                }),
2338                Expr::TryCast(TryCast {
2339                    expr: other_expr,
2340                    data_type: other_data_type,
2341                }),
2342            ) => self_data_type == other_data_type && self_expr.normalize_eq(other_expr),
2343            (
2344                Expr::ScalarFunction(ScalarFunction {
2345                    func: self_func,
2346                    args: self_args,
2347                }),
2348                Expr::ScalarFunction(ScalarFunction {
2349                    func: other_func,
2350                    args: other_args,
2351                }),
2352            ) => {
2353                self_func.name() == other_func.name()
2354                    && self_args.len() == other_args.len()
2355                    && self_args
2356                        .iter()
2357                        .zip(other_args.iter())
2358                        .all(|(a, b)| a.normalize_eq(b))
2359            }
2360            (
2361                Expr::AggregateFunction(AggregateFunction {
2362                    func: self_func,
2363                    params:
2364                        AggregateFunctionParams {
2365                            args: self_args,
2366                            distinct: self_distinct,
2367                            filter: self_filter,
2368                            order_by: self_order_by,
2369                            null_treatment: self_null_treatment,
2370                        },
2371                }),
2372                Expr::AggregateFunction(AggregateFunction {
2373                    func: other_func,
2374                    params:
2375                        AggregateFunctionParams {
2376                            args: other_args,
2377                            distinct: other_distinct,
2378                            filter: other_filter,
2379                            order_by: other_order_by,
2380                            null_treatment: other_null_treatment,
2381                        },
2382                }),
2383            ) => {
2384                self_func.name() == other_func.name()
2385                    && self_distinct == other_distinct
2386                    && self_null_treatment == other_null_treatment
2387                    && self_args.len() == other_args.len()
2388                    && self_args
2389                        .iter()
2390                        .zip(other_args.iter())
2391                        .all(|(a, b)| a.normalize_eq(b))
2392                    && match (self_filter, other_filter) {
2393                        (Some(self_filter), Some(other_filter)) => {
2394                            self_filter.normalize_eq(other_filter)
2395                        }
2396                        (None, None) => true,
2397                        _ => false,
2398                    }
2399                    && self_order_by
2400                        .iter()
2401                        .zip(other_order_by.iter())
2402                        .all(|(a, b)| {
2403                            a.asc == b.asc
2404                                && a.nulls_first == b.nulls_first
2405                                && a.expr.normalize_eq(&b.expr)
2406                        })
2407                    && self_order_by.len() == other_order_by.len()
2408            }
2409            (Expr::WindowFunction(left), Expr::WindowFunction(other)) => {
2410                let WindowFunction {
2411                    fun: self_fun,
2412                    params:
2413                        WindowFunctionParams {
2414                            args: self_args,
2415                            window_frame: self_window_frame,
2416                            partition_by: self_partition_by,
2417                            order_by: self_order_by,
2418                            filter: self_filter,
2419                            null_treatment: self_null_treatment,
2420                            distinct: self_distinct,
2421                        },
2422                } = left.as_ref();
2423                let WindowFunction {
2424                    fun: other_fun,
2425                    params:
2426                        WindowFunctionParams {
2427                            args: other_args,
2428                            window_frame: other_window_frame,
2429                            partition_by: other_partition_by,
2430                            order_by: other_order_by,
2431                            filter: other_filter,
2432                            null_treatment: other_null_treatment,
2433                            distinct: other_distinct,
2434                        },
2435                } = other.as_ref();
2436
2437                self_fun.name() == other_fun.name()
2438                    && self_window_frame == other_window_frame
2439                    && match (self_filter, other_filter) {
2440                        (Some(a), Some(b)) => a.normalize_eq(b),
2441                        (None, None) => true,
2442                        _ => false,
2443                    }
2444                    && self_null_treatment == other_null_treatment
2445                    && self_args.len() == other_args.len()
2446                    && self_args
2447                        .iter()
2448                        .zip(other_args.iter())
2449                        .all(|(a, b)| a.normalize_eq(b))
2450                    && self_partition_by
2451                        .iter()
2452                        .zip(other_partition_by.iter())
2453                        .all(|(a, b)| a.normalize_eq(b))
2454                    && self_order_by
2455                        .iter()
2456                        .zip(other_order_by.iter())
2457                        .all(|(a, b)| {
2458                            a.asc == b.asc
2459                                && a.nulls_first == b.nulls_first
2460                                && a.expr.normalize_eq(&b.expr)
2461                        })
2462                    && self_distinct == other_distinct
2463            }
2464            (
2465                Expr::Exists(Exists {
2466                    subquery: self_subquery,
2467                    negated: self_negated,
2468                }),
2469                Expr::Exists(Exists {
2470                    subquery: other_subquery,
2471                    negated: other_negated,
2472                }),
2473            ) => {
2474                self_negated == other_negated
2475                    && self_subquery.normalize_eq(other_subquery)
2476            }
2477            (
2478                Expr::InSubquery(InSubquery {
2479                    expr: self_expr,
2480                    subquery: self_subquery,
2481                    negated: self_negated,
2482                }),
2483                Expr::InSubquery(InSubquery {
2484                    expr: other_expr,
2485                    subquery: other_subquery,
2486                    negated: other_negated,
2487                }),
2488            ) => {
2489                self_negated == other_negated
2490                    && self_expr.normalize_eq(other_expr)
2491                    && self_subquery.normalize_eq(other_subquery)
2492            }
2493            (
2494                Expr::ScalarSubquery(self_subquery),
2495                Expr::ScalarSubquery(other_subquery),
2496            ) => self_subquery.normalize_eq(other_subquery),
2497            (
2498                Expr::GroupingSet(GroupingSet::Rollup(self_exprs)),
2499                Expr::GroupingSet(GroupingSet::Rollup(other_exprs)),
2500            )
2501            | (
2502                Expr::GroupingSet(GroupingSet::Cube(self_exprs)),
2503                Expr::GroupingSet(GroupingSet::Cube(other_exprs)),
2504            ) => {
2505                self_exprs.len() == other_exprs.len()
2506                    && self_exprs
2507                        .iter()
2508                        .zip(other_exprs.iter())
2509                        .all(|(a, b)| a.normalize_eq(b))
2510            }
2511            (
2512                Expr::GroupingSet(GroupingSet::GroupingSets(self_exprs)),
2513                Expr::GroupingSet(GroupingSet::GroupingSets(other_exprs)),
2514            ) => {
2515                self_exprs.len() == other_exprs.len()
2516                    && self_exprs.iter().zip(other_exprs.iter()).all(|(a, b)| {
2517                        a.len() == b.len()
2518                            && a.iter().zip(b.iter()).all(|(x, y)| x.normalize_eq(y))
2519                    })
2520            }
2521            (
2522                Expr::InList(InList {
2523                    expr: self_expr,
2524                    list: self_list,
2525                    negated: self_negated,
2526                }),
2527                Expr::InList(InList {
2528                    expr: other_expr,
2529                    list: other_list,
2530                    negated: other_negated,
2531                }),
2532            ) => {
2533                // TODO: normalize_eq for lists, for example `a IN (c1 + c3, c3)` is equal to `a IN (c3, c1 + c3)`
2534                self_negated == other_negated
2535                    && self_expr.normalize_eq(other_expr)
2536                    && self_list.len() == other_list.len()
2537                    && self_list
2538                        .iter()
2539                        .zip(other_list.iter())
2540                        .all(|(a, b)| a.normalize_eq(b))
2541            }
2542            (
2543                Expr::Case(Case {
2544                    expr: self_expr,
2545                    when_then_expr: self_when_then_expr,
2546                    else_expr: self_else_expr,
2547                }),
2548                Expr::Case(Case {
2549                    expr: other_expr,
2550                    when_then_expr: other_when_then_expr,
2551                    else_expr: other_else_expr,
2552                }),
2553            ) => {
2554                // TODO: normalize_eq for when_then_expr
2555                // for example `CASE a WHEN 1 THEN 2 WHEN 3 THEN 4 ELSE 5 END` is equal to `CASE a WHEN 3 THEN 4 WHEN 1 THEN 2 ELSE 5 END`
2556                self_when_then_expr.len() == other_when_then_expr.len()
2557                    && self_when_then_expr
2558                        .iter()
2559                        .zip(other_when_then_expr.iter())
2560                        .all(|((self_when, self_then), (other_when, other_then))| {
2561                            self_when.normalize_eq(other_when)
2562                                && self_then.normalize_eq(other_then)
2563                        })
2564                    && match (self_expr, other_expr) {
2565                        (Some(self_expr), Some(other_expr)) => {
2566                            self_expr.normalize_eq(other_expr)
2567                        }
2568                        (None, None) => true,
2569                        (_, _) => false,
2570                    }
2571                    && match (self_else_expr, other_else_expr) {
2572                        (Some(self_else_expr), Some(other_else_expr)) => {
2573                            self_else_expr.normalize_eq(other_else_expr)
2574                        }
2575                        (None, None) => true,
2576                        (_, _) => false,
2577                    }
2578            }
2579            (_, _) => self == other,
2580        }
2581    }
2582}
2583
2584impl HashNode for Expr {
2585    /// As it is pretty easy to forget changing this method when `Expr` changes the
2586    /// implementation doesn't use wildcard patterns (`..`, `_`) to catch changes
2587    /// compile time.
2588    fn hash_node<H: Hasher>(&self, state: &mut H) {
2589        mem::discriminant(self).hash(state);
2590        match self {
2591            Expr::Alias(Alias {
2592                expr: _expr,
2593                relation,
2594                name,
2595                ..
2596            }) => {
2597                relation.hash(state);
2598                name.hash(state);
2599            }
2600            Expr::Column(column) => {
2601                column.hash(state);
2602            }
2603            Expr::ScalarVariable(field, name) => {
2604                field.hash(state);
2605                name.hash(state);
2606            }
2607            Expr::Literal(scalar_value, _) => {
2608                scalar_value.hash(state);
2609            }
2610            Expr::BinaryExpr(BinaryExpr {
2611                left: _left,
2612                op,
2613                right: _right,
2614            }) => {
2615                op.hash(state);
2616            }
2617            Expr::Like(Like {
2618                negated,
2619                expr: _expr,
2620                pattern: _pattern,
2621                escape_char,
2622                case_insensitive,
2623            })
2624            | Expr::SimilarTo(Like {
2625                negated,
2626                expr: _expr,
2627                pattern: _pattern,
2628                escape_char,
2629                case_insensitive,
2630            }) => {
2631                negated.hash(state);
2632                escape_char.hash(state);
2633                case_insensitive.hash(state);
2634            }
2635            Expr::Not(_expr)
2636            | Expr::IsNotNull(_expr)
2637            | Expr::IsNull(_expr)
2638            | Expr::IsTrue(_expr)
2639            | Expr::IsFalse(_expr)
2640            | Expr::IsUnknown(_expr)
2641            | Expr::IsNotTrue(_expr)
2642            | Expr::IsNotFalse(_expr)
2643            | Expr::IsNotUnknown(_expr)
2644            | Expr::Negative(_expr) => {}
2645            Expr::Between(Between {
2646                expr: _expr,
2647                negated,
2648                low: _low,
2649                high: _high,
2650            }) => {
2651                negated.hash(state);
2652            }
2653            Expr::Case(Case {
2654                expr: _expr,
2655                when_then_expr: _when_then_expr,
2656                else_expr: _else_expr,
2657            }) => {}
2658            Expr::Cast(Cast {
2659                expr: _expr,
2660                data_type,
2661            })
2662            | Expr::TryCast(TryCast {
2663                expr: _expr,
2664                data_type,
2665            }) => {
2666                data_type.hash(state);
2667            }
2668            Expr::ScalarFunction(ScalarFunction { func, args: _args }) => {
2669                func.hash(state);
2670            }
2671            Expr::AggregateFunction(AggregateFunction {
2672                func,
2673                params:
2674                    AggregateFunctionParams {
2675                        args: _args,
2676                        distinct,
2677                        filter: _,
2678                        order_by: _,
2679                        null_treatment,
2680                    },
2681            }) => {
2682                func.hash(state);
2683                distinct.hash(state);
2684                null_treatment.hash(state);
2685            }
2686            Expr::WindowFunction(window_fun) => {
2687                let WindowFunction {
2688                    fun,
2689                    params:
2690                        WindowFunctionParams {
2691                            args: _args,
2692                            partition_by: _,
2693                            order_by: _,
2694                            window_frame,
2695                            filter,
2696                            null_treatment,
2697                            distinct,
2698                        },
2699                } = window_fun.as_ref();
2700                fun.hash(state);
2701                window_frame.hash(state);
2702                filter.hash(state);
2703                null_treatment.hash(state);
2704                distinct.hash(state);
2705            }
2706            Expr::InList(InList {
2707                expr: _expr,
2708                list: _list,
2709                negated,
2710            }) => {
2711                negated.hash(state);
2712            }
2713            Expr::Exists(Exists { subquery, negated }) => {
2714                subquery.hash(state);
2715                negated.hash(state);
2716            }
2717            Expr::InSubquery(InSubquery {
2718                expr: _expr,
2719                subquery,
2720                negated,
2721            }) => {
2722                subquery.hash(state);
2723                negated.hash(state);
2724            }
2725            Expr::SetComparison(SetComparison {
2726                expr: _,
2727                subquery,
2728                op,
2729                quantifier,
2730            }) => {
2731                subquery.hash(state);
2732                op.hash(state);
2733                quantifier.hash(state);
2734            }
2735            Expr::ScalarSubquery(subquery) => {
2736                subquery.hash(state);
2737            }
2738            #[expect(deprecated)]
2739            Expr::Wildcard { qualifier, options } => {
2740                qualifier.hash(state);
2741                options.hash(state);
2742            }
2743            Expr::GroupingSet(grouping_set) => {
2744                mem::discriminant(grouping_set).hash(state);
2745                match grouping_set {
2746                    GroupingSet::Rollup(_exprs) | GroupingSet::Cube(_exprs) => {}
2747                    GroupingSet::GroupingSets(_exprs) => {}
2748                }
2749            }
2750            Expr::Placeholder(place_holder) => {
2751                place_holder.hash(state);
2752            }
2753            Expr::OuterReferenceColumn(field, column) => {
2754                field.hash(state);
2755                column.hash(state);
2756            }
2757            Expr::Unnest(Unnest { expr: _expr }) => {}
2758        };
2759    }
2760}
2761
2762// Modifies expr to match the DataType, metadata, and nullability of other if it is
2763// a placeholder with previously unspecified type information (i.e., most placeholders)
2764fn rewrite_placeholder(expr: &mut Expr, other: &Expr, schema: &DFSchema) -> Result<()> {
2765    if let Expr::Placeholder(Placeholder { id: _, field }) = expr
2766        && field.is_none()
2767    {
2768        let other_field = other.to_field(schema);
2769        match other_field {
2770            Err(e) => {
2771                Err(e.context(format!(
2772                    "Can not find type of {other} needed to infer type of {expr}"
2773                )))?;
2774            }
2775            Ok((_, other_field)) => {
2776                // We can't infer the nullability of the future parameter that might
2777                // be bound, so ensure this is set to true
2778                *field = Some(other_field.as_ref().clone().with_nullable(true).into());
2779            }
2780        }
2781    };
2782    Ok(())
2783}
2784
2785#[macro_export]
2786macro_rules! expr_vec_fmt {
2787    ( $ARRAY:expr ) => {{
2788        $ARRAY
2789            .iter()
2790            .map(|e| format!("{e}"))
2791            .collect::<Vec<String>>()
2792            .join(", ")
2793    }};
2794}
2795
2796struct SchemaDisplay<'a>(&'a Expr);
2797impl Display for SchemaDisplay<'_> {
2798    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2799        match self.0 {
2800            // The same as Display
2801            // TODO: remove the next line after `Expr::Wildcard` is removed
2802            #[expect(deprecated)]
2803            Expr::Column(_)
2804            | Expr::Literal(_, _)
2805            | Expr::ScalarVariable(..)
2806            | Expr::OuterReferenceColumn(..)
2807            | Expr::Placeholder(_)
2808            | Expr::Wildcard { .. } => write!(f, "{}", self.0),
2809            Expr::AggregateFunction(AggregateFunction { func, params }) => {
2810                match func.schema_name(params) {
2811                    Ok(name) => {
2812                        write!(f, "{name}")
2813                    }
2814                    Err(e) => {
2815                        write!(f, "got error from schema_name {e}")
2816                    }
2817                }
2818            }
2819            // Expr is not shown since it is aliased
2820            Expr::Alias(Alias {
2821                name,
2822                relation: Some(relation),
2823                ..
2824            }) => write!(f, "{relation}.{name}"),
2825            Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
2826            Expr::Between(Between {
2827                expr,
2828                negated,
2829                low,
2830                high,
2831            }) => {
2832                if *negated {
2833                    write!(
2834                        f,
2835                        "{} NOT BETWEEN {} AND {}",
2836                        SchemaDisplay(expr),
2837                        SchemaDisplay(low),
2838                        SchemaDisplay(high),
2839                    )
2840                } else {
2841                    write!(
2842                        f,
2843                        "{} BETWEEN {} AND {}",
2844                        SchemaDisplay(expr),
2845                        SchemaDisplay(low),
2846                        SchemaDisplay(high),
2847                    )
2848                }
2849            }
2850            Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
2851                write!(f, "{} {op} {}", SchemaDisplay(left), SchemaDisplay(right),)
2852            }
2853            Expr::Case(Case {
2854                expr,
2855                when_then_expr,
2856                else_expr,
2857            }) => {
2858                write!(f, "CASE ")?;
2859
2860                if let Some(e) = expr {
2861                    write!(f, "{} ", SchemaDisplay(e))?;
2862                }
2863
2864                for (when, then) in when_then_expr {
2865                    write!(
2866                        f,
2867                        "WHEN {} THEN {} ",
2868                        SchemaDisplay(when),
2869                        SchemaDisplay(then),
2870                    )?;
2871                }
2872
2873                if let Some(e) = else_expr {
2874                    write!(f, "ELSE {} ", SchemaDisplay(e))?;
2875                }
2876
2877                write!(f, "END")
2878            }
2879            // Cast expr is not shown to be consistent with Postgres and Spark <https://github.com/apache/datafusion/pull/3222>
2880            Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
2881                write!(f, "{}", SchemaDisplay(expr))
2882            }
2883            Expr::InList(InList {
2884                expr,
2885                list,
2886                negated,
2887            }) => {
2888                let inlist_name = schema_name_from_exprs(list)?;
2889
2890                if *negated {
2891                    write!(f, "{} NOT IN {}", SchemaDisplay(expr), inlist_name)
2892                } else {
2893                    write!(f, "{} IN {}", SchemaDisplay(expr), inlist_name)
2894                }
2895            }
2896            Expr::Exists(Exists { negated: true, .. }) => write!(f, "NOT EXISTS"),
2897            Expr::Exists(Exists { negated: false, .. }) => write!(f, "EXISTS"),
2898            Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
2899                write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2900            }
2901            Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
2902                write!(f, "GROUPING SETS (")?;
2903                for exprs in lists_of_exprs.iter() {
2904                    write!(f, "({})", schema_name_from_exprs(exprs)?)?;
2905                }
2906                write!(f, ")")
2907            }
2908            Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
2909                write!(f, "ROLLUP ({})", schema_name_from_exprs(exprs)?)
2910            }
2911            Expr::IsNull(expr) => write!(f, "{} IS NULL", SchemaDisplay(expr)),
2912            Expr::IsNotNull(expr) => {
2913                write!(f, "{} IS NOT NULL", SchemaDisplay(expr))
2914            }
2915            Expr::IsUnknown(expr) => {
2916                write!(f, "{} IS UNKNOWN", SchemaDisplay(expr))
2917            }
2918            Expr::IsNotUnknown(expr) => {
2919                write!(f, "{} IS NOT UNKNOWN", SchemaDisplay(expr))
2920            }
2921            Expr::InSubquery(InSubquery { negated: true, .. }) => {
2922                write!(f, "NOT IN")
2923            }
2924            Expr::InSubquery(InSubquery { negated: false, .. }) => write!(f, "IN"),
2925            Expr::SetComparison(SetComparison {
2926                expr,
2927                op,
2928                quantifier,
2929                ..
2930            }) => write!(f, "{} {op} {quantifier}", SchemaDisplay(expr.as_ref())),
2931            Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SchemaDisplay(expr)),
2932            Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SchemaDisplay(expr)),
2933            Expr::IsNotTrue(expr) => {
2934                write!(f, "{} IS NOT TRUE", SchemaDisplay(expr))
2935            }
2936            Expr::IsNotFalse(expr) => {
2937                write!(f, "{} IS NOT FALSE", SchemaDisplay(expr))
2938            }
2939            Expr::Like(Like {
2940                negated,
2941                expr,
2942                pattern,
2943                escape_char,
2944                case_insensitive,
2945            }) => {
2946                write!(
2947                    f,
2948                    "{} {}{} {}",
2949                    SchemaDisplay(expr),
2950                    if *negated { "NOT " } else { "" },
2951                    if *case_insensitive { "ILIKE" } else { "LIKE" },
2952                    SchemaDisplay(pattern),
2953                )?;
2954
2955                if let Some(char) = escape_char {
2956                    write!(f, " CHAR '{char}'")?;
2957                }
2958
2959                Ok(())
2960            }
2961            Expr::Negative(expr) => write!(f, "(- {})", SchemaDisplay(expr)),
2962            Expr::Not(expr) => write!(f, "NOT {}", SchemaDisplay(expr)),
2963            Expr::Unnest(Unnest { expr }) => {
2964                write!(f, "UNNEST({})", SchemaDisplay(expr))
2965            }
2966            Expr::ScalarFunction(ScalarFunction { func, args }) => {
2967                match func.schema_name(args) {
2968                    Ok(name) => {
2969                        write!(f, "{name}")
2970                    }
2971                    Err(e) => {
2972                        write!(f, "got error from schema_name {e}")
2973                    }
2974                }
2975            }
2976            Expr::ScalarSubquery(Subquery { subquery, .. }) => {
2977                write!(f, "{}", subquery.schema().field(0).name())
2978            }
2979            Expr::SimilarTo(Like {
2980                negated,
2981                expr,
2982                pattern,
2983                escape_char,
2984                ..
2985            }) => {
2986                write!(
2987                    f,
2988                    "{} {} {}",
2989                    SchemaDisplay(expr),
2990                    if *negated {
2991                        "NOT SIMILAR TO"
2992                    } else {
2993                        "SIMILAR TO"
2994                    },
2995                    SchemaDisplay(pattern),
2996                )?;
2997                if let Some(char) = escape_char {
2998                    write!(f, " CHAR '{char}'")?;
2999                }
3000
3001                Ok(())
3002            }
3003            Expr::WindowFunction(window_fun) => {
3004                let WindowFunction { fun, params } = window_fun.as_ref();
3005                match fun {
3006                    WindowFunctionDefinition::AggregateUDF(fun) => {
3007                        match fun.window_function_schema_name(params) {
3008                            Ok(name) => {
3009                                write!(f, "{name}")
3010                            }
3011                            Err(e) => {
3012                                write!(
3013                                    f,
3014                                    "got error from window_function_schema_name {e}"
3015                                )
3016                            }
3017                        }
3018                    }
3019                    _ => {
3020                        let WindowFunctionParams {
3021                            args,
3022                            partition_by,
3023                            order_by,
3024                            window_frame,
3025                            filter,
3026                            null_treatment,
3027                            distinct,
3028                        } = params;
3029
3030                        // Write function name and open parenthesis
3031                        write!(f, "{fun}(")?;
3032
3033                        // If DISTINCT, emit the keyword
3034                        if *distinct {
3035                            write!(f, "DISTINCT ")?;
3036                        }
3037
3038                        // Write the comma‑separated argument list
3039                        write!(
3040                            f,
3041                            "{}",
3042                            schema_name_from_exprs_comma_separated_without_space(args)?
3043                        )?;
3044
3045                        // **Close the argument parenthesis**
3046                        write!(f, ")")?;
3047
3048                        if let Some(null_treatment) = null_treatment {
3049                            write!(f, " {null_treatment}")?;
3050                        }
3051
3052                        if let Some(filter) = filter {
3053                            write!(f, " FILTER (WHERE {filter})")?;
3054                        }
3055
3056                        if !partition_by.is_empty() {
3057                            write!(
3058                                f,
3059                                " PARTITION BY [{}]",
3060                                schema_name_from_exprs(partition_by)?
3061                            )?;
3062                        }
3063
3064                        if !order_by.is_empty() {
3065                            write!(
3066                                f,
3067                                " ORDER BY [{}]",
3068                                schema_name_from_sorts(order_by)?
3069                            )?;
3070                        };
3071
3072                        write!(f, " {window_frame}")
3073                    }
3074                }
3075            }
3076        }
3077    }
3078}
3079
3080/// A helper struct for displaying an `Expr` as an SQL-like string.
3081struct SqlDisplay<'a>(&'a Expr);
3082
3083impl Display for SqlDisplay<'_> {
3084    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3085        match self.0 {
3086            Expr::Literal(scalar, _) => scalar.fmt(f),
3087            Expr::Alias(Alias { name, .. }) => write!(f, "{name}"),
3088            Expr::Between(Between {
3089                expr,
3090                negated,
3091                low,
3092                high,
3093            }) => {
3094                if *negated {
3095                    write!(
3096                        f,
3097                        "{} NOT BETWEEN {} AND {}",
3098                        SqlDisplay(expr),
3099                        SqlDisplay(low),
3100                        SqlDisplay(high),
3101                    )
3102                } else {
3103                    write!(
3104                        f,
3105                        "{} BETWEEN {} AND {}",
3106                        SqlDisplay(expr),
3107                        SqlDisplay(low),
3108                        SqlDisplay(high),
3109                    )
3110                }
3111            }
3112            Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
3113                write!(f, "{} {op} {}", SqlDisplay(left), SqlDisplay(right),)
3114            }
3115            Expr::Case(Case {
3116                expr,
3117                when_then_expr,
3118                else_expr,
3119            }) => {
3120                write!(f, "CASE ")?;
3121
3122                if let Some(e) = expr {
3123                    write!(f, "{} ", SqlDisplay(e))?;
3124                }
3125
3126                for (when, then) in when_then_expr {
3127                    write!(f, "WHEN {} THEN {} ", SqlDisplay(when), SqlDisplay(then),)?;
3128                }
3129
3130                if let Some(e) = else_expr {
3131                    write!(f, "ELSE {} ", SqlDisplay(e))?;
3132                }
3133
3134                write!(f, "END")
3135            }
3136            Expr::Cast(Cast { expr, .. }) | Expr::TryCast(TryCast { expr, .. }) => {
3137                write!(f, "{}", SqlDisplay(expr))
3138            }
3139            Expr::InList(InList {
3140                expr,
3141                list,
3142                negated,
3143            }) => {
3144                write!(
3145                    f,
3146                    "{}{} IN {}",
3147                    SqlDisplay(expr),
3148                    if *negated { " NOT" } else { "" },
3149                    ExprListDisplay::comma_separated(list.as_slice())
3150                )
3151            }
3152            Expr::GroupingSet(GroupingSet::Cube(exprs)) => {
3153                write!(
3154                    f,
3155                    "ROLLUP ({})",
3156                    ExprListDisplay::comma_separated(exprs.as_slice())
3157                )
3158            }
3159            Expr::GroupingSet(GroupingSet::GroupingSets(lists_of_exprs)) => {
3160                write!(f, "GROUPING SETS (")?;
3161                for exprs in lists_of_exprs.iter() {
3162                    write!(
3163                        f,
3164                        "({})",
3165                        ExprListDisplay::comma_separated(exprs.as_slice())
3166                    )?;
3167                }
3168                write!(f, ")")
3169            }
3170            Expr::GroupingSet(GroupingSet::Rollup(exprs)) => {
3171                write!(
3172                    f,
3173                    "ROLLUP ({})",
3174                    ExprListDisplay::comma_separated(exprs.as_slice())
3175                )
3176            }
3177            Expr::IsNull(expr) => write!(f, "{} IS NULL", SqlDisplay(expr)),
3178            Expr::IsNotNull(expr) => {
3179                write!(f, "{} IS NOT NULL", SqlDisplay(expr))
3180            }
3181            Expr::IsUnknown(expr) => {
3182                write!(f, "{} IS UNKNOWN", SqlDisplay(expr))
3183            }
3184            Expr::IsNotUnknown(expr) => {
3185                write!(f, "{} IS NOT UNKNOWN", SqlDisplay(expr))
3186            }
3187            Expr::IsTrue(expr) => write!(f, "{} IS TRUE", SqlDisplay(expr)),
3188            Expr::IsFalse(expr) => write!(f, "{} IS FALSE", SqlDisplay(expr)),
3189            Expr::IsNotTrue(expr) => {
3190                write!(f, "{} IS NOT TRUE", SqlDisplay(expr))
3191            }
3192            Expr::IsNotFalse(expr) => {
3193                write!(f, "{} IS NOT FALSE", SqlDisplay(expr))
3194            }
3195            Expr::Like(Like {
3196                negated,
3197                expr,
3198                pattern,
3199                escape_char,
3200                case_insensitive,
3201            }) => {
3202                write!(
3203                    f,
3204                    "{} {}{} {}",
3205                    SqlDisplay(expr),
3206                    if *negated { "NOT " } else { "" },
3207                    if *case_insensitive { "ILIKE" } else { "LIKE" },
3208                    SqlDisplay(pattern),
3209                )?;
3210
3211                if let Some(char) = escape_char {
3212                    write!(f, " CHAR '{char}'")?;
3213                }
3214
3215                Ok(())
3216            }
3217            Expr::Negative(expr) => write!(f, "(- {})", SqlDisplay(expr)),
3218            Expr::Not(expr) => write!(f, "NOT {}", SqlDisplay(expr)),
3219            Expr::Unnest(Unnest { expr }) => {
3220                write!(f, "UNNEST({})", SqlDisplay(expr))
3221            }
3222            Expr::SimilarTo(Like {
3223                negated,
3224                expr,
3225                pattern,
3226                escape_char,
3227                ..
3228            }) => {
3229                write!(
3230                    f,
3231                    "{} {} {}",
3232                    SqlDisplay(expr),
3233                    if *negated {
3234                        "NOT SIMILAR TO"
3235                    } else {
3236                        "SIMILAR TO"
3237                    },
3238                    SqlDisplay(pattern),
3239                )?;
3240                if let Some(char) = escape_char {
3241                    write!(f, " CHAR '{char}'")?;
3242                }
3243
3244                Ok(())
3245            }
3246            Expr::AggregateFunction(AggregateFunction { func, params }) => {
3247                match func.human_display(params) {
3248                    Ok(name) => {
3249                        write!(f, "{name}")
3250                    }
3251                    Err(e) => {
3252                        write!(f, "got error from schema_name {e}")
3253                    }
3254                }
3255            }
3256            _ => write!(f, "{}", self.0),
3257        }
3258    }
3259}
3260
3261/// Get schema_name for Vector of expressions
3262///
3263/// Internal usage. Please call `schema_name_from_exprs` instead
3264// TODO: Use ", " to standardize the formatting of Vec<Expr>,
3265// <https://github.com/apache/datafusion/issues/10364>
3266pub(crate) fn schema_name_from_exprs_comma_separated_without_space(
3267    exprs: &[Expr],
3268) -> Result<String, fmt::Error> {
3269    schema_name_from_exprs_inner(exprs, ",")
3270}
3271
3272/// Formats a list of `&Expr` with a custom separator using SQL display format
3273pub struct ExprListDisplay<'a> {
3274    exprs: &'a [Expr],
3275    sep: &'a str,
3276}
3277
3278impl<'a> ExprListDisplay<'a> {
3279    /// Create a new display struct with the given expressions and separator
3280    pub fn new(exprs: &'a [Expr], sep: &'a str) -> Self {
3281        Self { exprs, sep }
3282    }
3283
3284    /// Create a new display struct with comma-space separator
3285    pub fn comma_separated(exprs: &'a [Expr]) -> Self {
3286        Self::new(exprs, ", ")
3287    }
3288}
3289
3290impl Display for ExprListDisplay<'_> {
3291    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3292        let mut first = true;
3293        for expr in self.exprs {
3294            if !first {
3295                write!(f, "{}", self.sep)?;
3296            }
3297            write!(f, "{}", SqlDisplay(expr))?;
3298            first = false;
3299        }
3300        Ok(())
3301    }
3302}
3303
3304/// Get schema_name for Vector of expressions
3305pub fn schema_name_from_exprs(exprs: &[Expr]) -> Result<String, fmt::Error> {
3306    schema_name_from_exprs_inner(exprs, ", ")
3307}
3308
3309fn schema_name_from_exprs_inner(exprs: &[Expr], sep: &str) -> Result<String, fmt::Error> {
3310    let mut s = String::new();
3311    for (i, e) in exprs.iter().enumerate() {
3312        if i > 0 {
3313            write!(&mut s, "{sep}")?;
3314        }
3315        write!(&mut s, "{}", SchemaDisplay(e))?;
3316    }
3317
3318    Ok(s)
3319}
3320
3321pub fn schema_name_from_sorts(sorts: &[Sort]) -> Result<String, fmt::Error> {
3322    let mut s = String::new();
3323    for (i, e) in sorts.iter().enumerate() {
3324        if i > 0 {
3325            write!(&mut s, ", ")?;
3326        }
3327        let ordering = if e.asc { "ASC" } else { "DESC" };
3328        let nulls_ordering = if e.nulls_first {
3329            "NULLS FIRST"
3330        } else {
3331            "NULLS LAST"
3332        };
3333        write!(&mut s, "{} {} {}", e.expr, ordering, nulls_ordering)?;
3334    }
3335
3336    Ok(s)
3337}
3338
3339pub const OUTER_REFERENCE_COLUMN_PREFIX: &str = "outer_ref";
3340pub const UNNEST_COLUMN_PREFIX: &str = "UNNEST";
3341
3342/// Format expressions for display as part of a logical plan. In many cases, this will produce
3343/// similar output to `Expr.name()` except that column names will be prefixed with '#'.
3344impl Display for Expr {
3345    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
3346        match self {
3347            Expr::Alias(Alias { expr, name, .. }) => write!(f, "{expr} AS {name}"),
3348            Expr::Column(c) => write!(f, "{c}"),
3349            Expr::OuterReferenceColumn(_, c) => {
3350                write!(f, "{OUTER_REFERENCE_COLUMN_PREFIX}({c})")
3351            }
3352            Expr::ScalarVariable(_, var_names) => write!(f, "{}", var_names.join(".")),
3353            Expr::Literal(v, metadata) => {
3354                match metadata.as_ref().map(|m| m.is_empty()).unwrap_or(true) {
3355                    false => write!(f, "{v:?} {:?}", metadata.as_ref().unwrap()),
3356                    true => write!(f, "{v:?}"),
3357                }
3358            }
3359            Expr::Case(case) => {
3360                write!(f, "CASE ")?;
3361                if let Some(e) = &case.expr {
3362                    write!(f, "{e} ")?;
3363                }
3364                for (w, t) in &case.when_then_expr {
3365                    write!(f, "WHEN {w} THEN {t} ")?;
3366                }
3367                if let Some(e) = &case.else_expr {
3368                    write!(f, "ELSE {e} ")?;
3369                }
3370                write!(f, "END")
3371            }
3372            Expr::Cast(Cast { expr, data_type }) => {
3373                write!(f, "CAST({expr} AS {data_type})")
3374            }
3375            Expr::TryCast(TryCast { expr, data_type }) => {
3376                write!(f, "TRY_CAST({expr} AS {data_type})")
3377            }
3378            Expr::Not(expr) => write!(f, "NOT {expr}"),
3379            Expr::Negative(expr) => write!(f, "(- {expr})"),
3380            Expr::IsNull(expr) => write!(f, "{expr} IS NULL"),
3381            Expr::IsNotNull(expr) => write!(f, "{expr} IS NOT NULL"),
3382            Expr::IsTrue(expr) => write!(f, "{expr} IS TRUE"),
3383            Expr::IsFalse(expr) => write!(f, "{expr} IS FALSE"),
3384            Expr::IsUnknown(expr) => write!(f, "{expr} IS UNKNOWN"),
3385            Expr::IsNotTrue(expr) => write!(f, "{expr} IS NOT TRUE"),
3386            Expr::IsNotFalse(expr) => write!(f, "{expr} IS NOT FALSE"),
3387            Expr::IsNotUnknown(expr) => write!(f, "{expr} IS NOT UNKNOWN"),
3388            Expr::Exists(Exists {
3389                subquery,
3390                negated: true,
3391            }) => write!(f, "NOT EXISTS ({subquery:?})"),
3392            Expr::Exists(Exists {
3393                subquery,
3394                negated: false,
3395            }) => write!(f, "EXISTS ({subquery:?})"),
3396            Expr::InSubquery(InSubquery {
3397                expr,
3398                subquery,
3399                negated: true,
3400            }) => write!(f, "{expr} NOT IN ({subquery:?})"),
3401            Expr::InSubquery(InSubquery {
3402                expr,
3403                subquery,
3404                negated: false,
3405            }) => write!(f, "{expr} IN ({subquery:?})"),
3406            Expr::SetComparison(SetComparison {
3407                expr,
3408                subquery,
3409                op,
3410                quantifier,
3411            }) => write!(f, "{expr} {op} {quantifier} ({subquery:?})"),
3412            Expr::ScalarSubquery(subquery) => write!(f, "({subquery:?})"),
3413            Expr::BinaryExpr(expr) => write!(f, "{expr}"),
3414            Expr::ScalarFunction(fun) => {
3415                fmt_function(f, fun.name(), false, &fun.args, true)
3416            }
3417            Expr::WindowFunction(window_fun) => {
3418                let WindowFunction { fun, params } = window_fun.as_ref();
3419                match fun {
3420                    WindowFunctionDefinition::AggregateUDF(fun) => {
3421                        match fun.window_function_display_name(params) {
3422                            Ok(name) => {
3423                                write!(f, "{name}")
3424                            }
3425                            Err(e) => {
3426                                write!(
3427                                    f,
3428                                    "got error from window_function_display_name {e}"
3429                                )
3430                            }
3431                        }
3432                    }
3433                    WindowFunctionDefinition::WindowUDF(fun) => {
3434                        let WindowFunctionParams {
3435                            args,
3436                            partition_by,
3437                            order_by,
3438                            window_frame,
3439                            filter,
3440                            null_treatment,
3441                            distinct,
3442                        } = params;
3443
3444                        fmt_function(f, &fun.to_string(), *distinct, args, true)?;
3445
3446                        if let Some(nt) = null_treatment {
3447                            write!(f, "{nt}")?;
3448                        }
3449
3450                        if let Some(fe) = filter {
3451                            write!(f, " FILTER (WHERE {fe})")?;
3452                        }
3453
3454                        if !partition_by.is_empty() {
3455                            write!(f, " PARTITION BY [{}]", expr_vec_fmt!(partition_by))?;
3456                        }
3457                        if !order_by.is_empty() {
3458                            write!(f, " ORDER BY [{}]", expr_vec_fmt!(order_by))?;
3459                        }
3460                        write!(
3461                            f,
3462                            " {} BETWEEN {} AND {}",
3463                            window_frame.units,
3464                            window_frame.start_bound,
3465                            window_frame.end_bound
3466                        )
3467                    }
3468                }
3469            }
3470            Expr::AggregateFunction(AggregateFunction { func, params }) => {
3471                match func.display_name(params) {
3472                    Ok(name) => {
3473                        write!(f, "{name}")
3474                    }
3475                    Err(e) => {
3476                        write!(f, "got error from display_name {e}")
3477                    }
3478                }
3479            }
3480            Expr::Between(Between {
3481                expr,
3482                negated,
3483                low,
3484                high,
3485            }) => {
3486                if *negated {
3487                    write!(f, "{expr} NOT BETWEEN {low} AND {high}")
3488                } else {
3489                    write!(f, "{expr} BETWEEN {low} AND {high}")
3490                }
3491            }
3492            Expr::Like(Like {
3493                negated,
3494                expr,
3495                pattern,
3496                escape_char,
3497                case_insensitive,
3498            }) => {
3499                write!(f, "{expr}")?;
3500                let op_name = if *case_insensitive { "ILIKE" } else { "LIKE" };
3501                if *negated {
3502                    write!(f, " NOT")?;
3503                }
3504                if let Some(char) = escape_char {
3505                    write!(f, " {op_name} {pattern} ESCAPE '{char}'")
3506                } else {
3507                    write!(f, " {op_name} {pattern}")
3508                }
3509            }
3510            Expr::SimilarTo(Like {
3511                negated,
3512                expr,
3513                pattern,
3514                escape_char,
3515                case_insensitive: _,
3516            }) => {
3517                write!(f, "{expr}")?;
3518                if *negated {
3519                    write!(f, " NOT")?;
3520                }
3521                if let Some(char) = escape_char {
3522                    write!(f, " SIMILAR TO {pattern} ESCAPE '{char}'")
3523                } else {
3524                    write!(f, " SIMILAR TO {pattern}")
3525                }
3526            }
3527            Expr::InList(InList {
3528                expr,
3529                list,
3530                negated,
3531            }) => {
3532                if *negated {
3533                    write!(f, "{expr} NOT IN ([{}])", expr_vec_fmt!(list))
3534                } else {
3535                    write!(f, "{expr} IN ([{}])", expr_vec_fmt!(list))
3536                }
3537            }
3538            #[expect(deprecated)]
3539            Expr::Wildcard { qualifier, options } => match qualifier {
3540                Some(qualifier) => write!(f, "{qualifier}.*{options}"),
3541                None => write!(f, "*{options}"),
3542            },
3543            Expr::GroupingSet(grouping_sets) => match grouping_sets {
3544                GroupingSet::Rollup(exprs) => {
3545                    // ROLLUP (c0, c1, c2)
3546                    write!(f, "ROLLUP ({})", expr_vec_fmt!(exprs))
3547                }
3548                GroupingSet::Cube(exprs) => {
3549                    // CUBE (c0, c1, c2)
3550                    write!(f, "CUBE ({})", expr_vec_fmt!(exprs))
3551                }
3552                GroupingSet::GroupingSets(lists_of_exprs) => {
3553                    // GROUPING SETS ((c0), (c1, c2), (c3, c4))
3554                    write!(
3555                        f,
3556                        "GROUPING SETS ({})",
3557                        lists_of_exprs
3558                            .iter()
3559                            .map(|exprs| format!("({})", expr_vec_fmt!(exprs)))
3560                            .collect::<Vec<String>>()
3561                            .join(", ")
3562                    )
3563                }
3564            },
3565            Expr::Placeholder(Placeholder { id, .. }) => write!(f, "{id}"),
3566            Expr::Unnest(Unnest { expr }) => {
3567                write!(f, "{UNNEST_COLUMN_PREFIX}({expr})")
3568            }
3569        }
3570    }
3571}
3572
3573fn fmt_function(
3574    f: &mut Formatter,
3575    fun: &str,
3576    distinct: bool,
3577    args: &[Expr],
3578    display: bool,
3579) -> fmt::Result {
3580    let args: Vec<String> = match display {
3581        true => args.iter().map(|arg| format!("{arg}")).collect(),
3582        false => args.iter().map(|arg| format!("{arg:?}")).collect(),
3583    };
3584
3585    let distinct_str = match distinct {
3586        true => "DISTINCT ",
3587        false => "",
3588    };
3589    write!(f, "{}({}{})", fun, distinct_str, args.join(", "))
3590}
3591
3592/// The name of the column (field) that this `Expr` will produce in the physical plan.
3593/// The difference from [Expr::schema_name] is that top-level columns are unqualified.
3594pub fn physical_name(expr: &Expr) -> Result<String> {
3595    match expr {
3596        Expr::Column(col) => Ok(col.name.clone()),
3597        Expr::Alias(alias) => Ok(alias.name.clone()),
3598        _ => Ok(expr.schema_name().to_string()),
3599    }
3600}
3601
3602#[cfg(test)]
3603mod test {
3604    use crate::expr_fn::col;
3605    use crate::{
3606        ColumnarValue, ScalarFunctionArgs, ScalarUDF, ScalarUDFImpl, Volatility, case,
3607        lit, placeholder, qualified_wildcard, wildcard, wildcard_with_options,
3608    };
3609    use arrow::datatypes::{Field, Schema};
3610    use sqlparser::ast;
3611    use sqlparser::ast::{Ident, IdentWithAlias};
3612    use std::any::Any;
3613
3614    #[test]
3615    fn infer_placeholder_in_clause() {
3616        // SELECT * FROM employees WHERE department_id IN ($1, $2, $3);
3617        let column = col("department_id");
3618        let param_placeholders = vec![
3619            Expr::Placeholder(Placeholder {
3620                id: "$1".to_string(),
3621                field: None,
3622            }),
3623            Expr::Placeholder(Placeholder {
3624                id: "$2".to_string(),
3625                field: None,
3626            }),
3627            Expr::Placeholder(Placeholder {
3628                id: "$3".to_string(),
3629                field: None,
3630            }),
3631        ];
3632        let in_list = Expr::InList(InList {
3633            expr: Box::new(column),
3634            list: param_placeholders,
3635            negated: false,
3636        });
3637
3638        let schema = Arc::new(Schema::new(vec![
3639            Field::new("name", DataType::Utf8, true),
3640            Field::new("department_id", DataType::Int32, true),
3641        ]));
3642        let df_schema = DFSchema::try_from(schema).unwrap();
3643
3644        let (inferred_expr, contains_placeholder) =
3645            in_list.infer_placeholder_types(&df_schema).unwrap();
3646
3647        assert!(contains_placeholder);
3648
3649        match inferred_expr {
3650            Expr::InList(in_list) => {
3651                for expr in in_list.list {
3652                    match expr {
3653                        Expr::Placeholder(placeholder) => {
3654                            assert_eq!(
3655                                placeholder.field.unwrap().data_type(),
3656                                &DataType::Int32,
3657                                "Placeholder {} should infer Int32",
3658                                placeholder.id
3659                            );
3660                        }
3661                        _ => panic!("Expected Placeholder expression"),
3662                    }
3663                }
3664            }
3665            _ => panic!("Expected InList expression"),
3666        }
3667    }
3668
3669    #[test]
3670    fn infer_placeholder_like_and_similar_to() {
3671        // name LIKE $1
3672        let schema =
3673            Arc::new(Schema::new(vec![Field::new("name", DataType::Utf8, true)]));
3674        let df_schema = DFSchema::try_from(schema).unwrap();
3675
3676        let like = Like {
3677            expr: Box::new(col("name")),
3678            pattern: Box::new(Expr::Placeholder(Placeholder {
3679                id: "$1".to_string(),
3680                field: None,
3681            })),
3682            negated: false,
3683            case_insensitive: false,
3684            escape_char: None,
3685        };
3686
3687        let expr = Expr::Like(like.clone());
3688
3689        let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3690        match inferred_expr {
3691            Expr::Like(like) => match *like.pattern {
3692                Expr::Placeholder(placeholder) => {
3693                    assert_eq!(placeholder.field.unwrap().data_type(), &DataType::Utf8);
3694                }
3695                _ => panic!("Expected Placeholder"),
3696            },
3697            _ => panic!("Expected Like"),
3698        }
3699
3700        // name SIMILAR TO $1
3701        let expr = Expr::SimilarTo(like);
3702
3703        let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3704        match inferred_expr {
3705            Expr::SimilarTo(like) => match *like.pattern {
3706                Expr::Placeholder(placeholder) => {
3707                    assert_eq!(
3708                        placeholder.field.unwrap().data_type(),
3709                        &DataType::Utf8,
3710                        "Placeholder {} should infer Utf8",
3711                        placeholder.id
3712                    );
3713                }
3714                _ => panic!("Expected Placeholder expression"),
3715            },
3716            _ => panic!("Expected SimilarTo expression"),
3717        }
3718    }
3719
3720    #[test]
3721    fn infer_placeholder_with_metadata() {
3722        // name == $1, where name is a non-nullable string
3723        let schema = Arc::new(Schema::new(vec![
3724            Field::new("name", DataType::Utf8, false).with_metadata(
3725                [("some_key".to_string(), "some_value".to_string())].into(),
3726            ),
3727        ]));
3728        let df_schema = DFSchema::try_from(schema).unwrap();
3729
3730        let expr = binary_expr(col("name"), Operator::Eq, placeholder("$1"));
3731
3732        let (inferred_expr, _) = expr.infer_placeholder_types(&df_schema).unwrap();
3733        match inferred_expr {
3734            Expr::BinaryExpr(BinaryExpr { right, .. }) => match *right {
3735                Expr::Placeholder(placeholder) => {
3736                    assert_eq!(
3737                        placeholder.field.as_ref().unwrap().data_type(),
3738                        &DataType::Utf8
3739                    );
3740                    assert_eq!(
3741                        placeholder.field.as_ref().unwrap().metadata(),
3742                        df_schema.field(0).metadata()
3743                    );
3744                    // Inferred placeholder should still be nullable
3745                    assert!(placeholder.field.as_ref().unwrap().is_nullable());
3746                }
3747                _ => panic!("Expected Placeholder"),
3748            },
3749            _ => panic!("Expected BinaryExpr"),
3750        }
3751    }
3752
3753    #[test]
3754    fn format_case_when() -> Result<()> {
3755        let expr = case(col("a"))
3756            .when(lit(1), lit(true))
3757            .when(lit(0), lit(false))
3758            .otherwise(lit(ScalarValue::Null))?;
3759        let expected = "CASE a WHEN Int32(1) THEN Boolean(true) WHEN Int32(0) THEN Boolean(false) ELSE NULL END";
3760        assert_eq!(expected, format!("{expr}"));
3761        Ok(())
3762    }
3763
3764    #[test]
3765    fn format_cast() -> Result<()> {
3766        let expr = Expr::Cast(Cast {
3767            expr: Box::new(Expr::Literal(ScalarValue::Float32(Some(1.23)), None)),
3768            data_type: DataType::Utf8,
3769        });
3770        let expected_canonical = "CAST(Float32(1.23) AS Utf8)";
3771        assert_eq!(expected_canonical, format!("{expr}"));
3772        // Note that CAST intentionally has a name that is different from its `Display`
3773        // representation. CAST does not change the name of expressions.
3774        assert_eq!("Float32(1.23)", expr.schema_name().to_string());
3775        Ok(())
3776    }
3777
3778    #[test]
3779    fn test_partial_ord() {
3780        // Test validates that partial ord is defined for Expr, not
3781        // intended to exhaustively test all possibilities
3782        let exp1 = col("a") + lit(1);
3783        let exp2 = col("a") + lit(2);
3784        let exp3 = !(col("a") + lit(2));
3785
3786        assert!(exp1 < exp2);
3787        assert!(exp3 > exp2);
3788        assert!(exp1 < exp3)
3789    }
3790
3791    #[test]
3792    fn test_collect_expr() -> Result<()> {
3793        // single column
3794        {
3795            let expr = &Expr::Cast(Cast::new(Box::new(col("a")), DataType::Float64));
3796            let columns = expr.column_refs();
3797            assert_eq!(1, columns.len());
3798            assert!(columns.contains(&Column::from_name("a")));
3799        }
3800
3801        // multiple columns
3802        {
3803            let expr = col("a") + col("b") + lit(1);
3804            let columns = expr.column_refs();
3805            assert_eq!(2, columns.len());
3806            assert!(columns.contains(&Column::from_name("a")));
3807            assert!(columns.contains(&Column::from_name("b")));
3808        }
3809
3810        Ok(())
3811    }
3812
3813    #[test]
3814    fn test_logical_ops() {
3815        assert_eq!(
3816            format!("{}", lit(1u32).eq(lit(2u32))),
3817            "UInt32(1) = UInt32(2)"
3818        );
3819        assert_eq!(
3820            format!("{}", lit(1u32).not_eq(lit(2u32))),
3821            "UInt32(1) != UInt32(2)"
3822        );
3823        assert_eq!(
3824            format!("{}", lit(1u32).gt(lit(2u32))),
3825            "UInt32(1) > UInt32(2)"
3826        );
3827        assert_eq!(
3828            format!("{}", lit(1u32).gt_eq(lit(2u32))),
3829            "UInt32(1) >= UInt32(2)"
3830        );
3831        assert_eq!(
3832            format!("{}", lit(1u32).lt(lit(2u32))),
3833            "UInt32(1) < UInt32(2)"
3834        );
3835        assert_eq!(
3836            format!("{}", lit(1u32).lt_eq(lit(2u32))),
3837            "UInt32(1) <= UInt32(2)"
3838        );
3839        assert_eq!(
3840            format!("{}", lit(1u32).and(lit(2u32))),
3841            "UInt32(1) AND UInt32(2)"
3842        );
3843        assert_eq!(
3844            format!("{}", lit(1u32).or(lit(2u32))),
3845            "UInt32(1) OR UInt32(2)"
3846        );
3847    }
3848
3849    #[test]
3850    fn test_is_volatile_scalar_func() {
3851        // UDF
3852        #[derive(Debug, PartialEq, Eq, Hash)]
3853        struct TestScalarUDF {
3854            signature: Signature,
3855        }
3856        impl ScalarUDFImpl for TestScalarUDF {
3857            fn as_any(&self) -> &dyn Any {
3858                self
3859            }
3860            fn name(&self) -> &str {
3861                "TestScalarUDF"
3862            }
3863
3864            fn signature(&self) -> &Signature {
3865                &self.signature
3866            }
3867
3868            fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
3869                Ok(DataType::Utf8)
3870            }
3871
3872            fn invoke_with_args(
3873                &self,
3874                _args: ScalarFunctionArgs,
3875            ) -> Result<ColumnarValue> {
3876                Ok(ColumnarValue::Scalar(ScalarValue::from("a")))
3877            }
3878        }
3879        let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3880            signature: Signature::uniform(1, vec![DataType::Float32], Volatility::Stable),
3881        }));
3882        assert_ne!(udf.signature().volatility, Volatility::Volatile);
3883
3884        let udf = Arc::new(ScalarUDF::from(TestScalarUDF {
3885            signature: Signature::uniform(
3886                1,
3887                vec![DataType::Float32],
3888                Volatility::Volatile,
3889            ),
3890        }));
3891        assert_eq!(udf.signature().volatility, Volatility::Volatile);
3892    }
3893
3894    use super::*;
3895    use crate::logical_plan::{EmptyRelation, LogicalPlan};
3896
3897    #[test]
3898    fn test_display_wildcard() {
3899        assert_eq!(format!("{}", wildcard()), "*");
3900        assert_eq!(format!("{}", qualified_wildcard("t1")), "t1.*");
3901        assert_eq!(
3902            format!(
3903                "{}",
3904                wildcard_with_options(wildcard_options(
3905                    Some(IlikeSelectItem {
3906                        pattern: "c1".to_string()
3907                    }),
3908                    None,
3909                    None,
3910                    None,
3911                    None
3912                ))
3913            ),
3914            "* ILIKE 'c1'"
3915        );
3916        assert_eq!(
3917            format!(
3918                "{}",
3919                wildcard_with_options(wildcard_options(
3920                    None,
3921                    Some(ExcludeSelectItem::Multiple(vec![
3922                        Ident::from("c1"),
3923                        Ident::from("c2")
3924                    ])),
3925                    None,
3926                    None,
3927                    None
3928                ))
3929            ),
3930            "* EXCLUDE (c1, c2)"
3931        );
3932        assert_eq!(
3933            format!(
3934                "{}",
3935                wildcard_with_options(wildcard_options(
3936                    None,
3937                    None,
3938                    Some(ExceptSelectItem {
3939                        first_element: Ident::from("c1"),
3940                        additional_elements: vec![Ident::from("c2")]
3941                    }),
3942                    None,
3943                    None
3944                ))
3945            ),
3946            "* EXCEPT (c1, c2)"
3947        );
3948        assert_eq!(
3949            format!(
3950                "{}",
3951                wildcard_with_options(wildcard_options(
3952                    None,
3953                    None,
3954                    None,
3955                    Some(PlannedReplaceSelectItem {
3956                        items: vec![ReplaceSelectElement {
3957                            expr: ast::Expr::Identifier(Ident::from("c1")),
3958                            column_name: Ident::from("a1"),
3959                            as_keyword: false
3960                        }],
3961                        planned_expressions: vec![]
3962                    }),
3963                    None
3964                ))
3965            ),
3966            "* REPLACE (c1 a1)"
3967        );
3968        assert_eq!(
3969            format!(
3970                "{}",
3971                wildcard_with_options(wildcard_options(
3972                    None,
3973                    None,
3974                    None,
3975                    None,
3976                    Some(RenameSelectItem::Multiple(vec![IdentWithAlias {
3977                        ident: Ident::from("c1"),
3978                        alias: Ident::from("a1")
3979                    }]))
3980                ))
3981            ),
3982            "* RENAME (c1 AS a1)"
3983        )
3984    }
3985
3986    #[test]
3987    fn test_display_set_comparison() {
3988        let subquery = Subquery {
3989            subquery: Arc::new(LogicalPlan::EmptyRelation(EmptyRelation {
3990                produce_one_row: false,
3991                schema: Arc::new(DFSchema::empty()),
3992            })),
3993            outer_ref_columns: vec![],
3994            spans: Spans::new(),
3995        };
3996
3997        let expr = Expr::SetComparison(SetComparison::new(
3998            Box::new(Expr::Column(Column::from_name("a"))),
3999            subquery,
4000            Operator::Gt,
4001            SetQuantifier::Any,
4002        ));
4003
4004        assert_eq!(format!("{expr}"), "a > ANY (<subquery>)");
4005        assert_eq!(format!("{}", expr.human_display()), "a > ANY (<subquery>)");
4006    }
4007
4008    #[test]
4009    fn test_schema_display_alias_with_relation() {
4010        assert_eq!(
4011            format!(
4012                "{}",
4013                SchemaDisplay(
4014                    &lit(1).alias_qualified("table_name".into(), "column_name")
4015                )
4016            ),
4017            "table_name.column_name"
4018        );
4019    }
4020
4021    #[test]
4022    fn test_schema_display_alias_without_relation() {
4023        assert_eq!(
4024            format!(
4025                "{}",
4026                SchemaDisplay(&lit(1).alias_qualified(None::<&str>, "column_name"))
4027            ),
4028            "column_name"
4029        );
4030    }
4031
4032    fn wildcard_options(
4033        opt_ilike: Option<IlikeSelectItem>,
4034        opt_exclude: Option<ExcludeSelectItem>,
4035        opt_except: Option<ExceptSelectItem>,
4036        opt_replace: Option<PlannedReplaceSelectItem>,
4037        opt_rename: Option<RenameSelectItem>,
4038    ) -> WildcardOptions {
4039        WildcardOptions {
4040            ilike: opt_ilike,
4041            exclude: opt_exclude,
4042            except: opt_except,
4043            replace: opt_replace,
4044            rename: opt_rename,
4045        }
4046    }
4047
4048    #[test]
4049    fn test_size_of_expr() {
4050        // because Expr is such a widely used struct in DataFusion
4051        // it is important to keep its size as small as possible
4052        //
4053        // If this test fails when you change `Expr`, please try
4054        // `Box`ing the fields to make `Expr` smaller
4055        // See https://github.com/apache/datafusion/issues/16199 for details
4056        assert_eq!(size_of::<Expr>(), 112);
4057        assert_eq!(size_of::<ScalarValue>(), 64);
4058        assert_eq!(size_of::<DataType>(), 24); // 3 ptrs
4059        assert_eq!(size_of::<Vec<Expr>>(), 24);
4060        assert_eq!(size_of::<Arc<Expr>>(), 8);
4061    }
4062
4063    #[test]
4064    fn test_accept_exprs() {
4065        fn accept_exprs<E: AsRef<Expr>>(_: &[E]) {}
4066
4067        let expr = || -> Expr { lit(1) };
4068
4069        // Call accept_exprs with owned expressions
4070        let owned_exprs = vec![expr(), expr()];
4071        accept_exprs(&owned_exprs);
4072
4073        // Call accept_exprs with expressions from expr tree
4074        let udf = Expr::ScalarFunction(ScalarFunction {
4075            func: Arc::new(ScalarUDF::new_from_impl(TestUDF {})),
4076            args: vec![expr(), expr()],
4077        });
4078        let Expr::ScalarFunction(scalar) = &udf else {
4079            unreachable!()
4080        };
4081        accept_exprs(&scalar.args);
4082
4083        // Call accept_exprs with expressions collected from expr tree, without cloning
4084        let mut collected_refs: Vec<&Expr> = scalar.args.iter().collect();
4085        collected_refs.extend(&owned_exprs);
4086        accept_exprs(&collected_refs);
4087
4088        // test helpers
4089        #[derive(Debug, PartialEq, Eq, Hash)]
4090        struct TestUDF {}
4091        impl ScalarUDFImpl for TestUDF {
4092            fn as_any(&self) -> &dyn Any {
4093                unimplemented!()
4094            }
4095
4096            fn name(&self) -> &str {
4097                unimplemented!()
4098            }
4099
4100            fn signature(&self) -> &Signature {
4101                unimplemented!()
4102            }
4103
4104            fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
4105                unimplemented!()
4106            }
4107
4108            fn invoke_with_args(
4109                &self,
4110                _args: ScalarFunctionArgs,
4111            ) -> Result<ColumnarValue> {
4112                unimplemented!()
4113            }
4114        }
4115    }
4116}