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