Skip to main content

datafusion_expr/
expr.rs

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