datafusion_sql/unparser/
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
18use datafusion_expr::expr::{AggregateFunctionParams, Unnest, WindowFunctionParams};
19use sqlparser::ast::Value::SingleQuotedString;
20use sqlparser::ast::{
21    self, Array, BinaryOperator, Expr as AstExpr, Function, Ident, Interval, ObjectName,
22    Subscript, TimezoneInfo, UnaryOperator,
23};
24use std::sync::Arc;
25use std::vec;
26
27use super::dialect::IntervalStyle;
28use super::Unparser;
29use arrow::array::{
30    types::{
31        ArrowTemporalType, Time32MillisecondType, Time32SecondType,
32        Time64MicrosecondType, Time64NanosecondType, TimestampMicrosecondType,
33        TimestampMillisecondType, TimestampNanosecondType, TimestampSecondType,
34    },
35    ArrayRef, Date32Array, Date64Array, PrimitiveArray,
36};
37use arrow::datatypes::{DataType, Decimal128Type, Decimal256Type, DecimalType};
38use arrow::util::display::array_value_to_string;
39use datafusion_common::{
40    internal_datafusion_err, internal_err, not_impl_err, plan_err, Column, Result,
41    ScalarValue,
42};
43use datafusion_expr::{
44    expr::{Alias, Exists, InList, ScalarFunction, Sort, WindowFunction},
45    Between, BinaryExpr, Case, Cast, Expr, GroupingSet, Like, Operator, TryCast,
46};
47use sqlparser::ast::helpers::attached_token::AttachedToken;
48use sqlparser::tokenizer::Span;
49
50/// Convert a DataFusion [`Expr`] to [`ast::Expr`]
51///
52/// This function is the opposite of [`SqlToRel::sql_to_expr`] and can be used
53/// to, among other things, convert [`Expr`]s to SQL strings. Such strings could
54/// be used to pass filters or other expressions to another SQL engine.
55///
56/// # Errors
57///
58/// Throws an error if [`Expr`] can not be represented by an [`ast::Expr`]
59///
60/// # See Also
61///
62/// * [`Unparser`] for more control over the conversion to SQL
63/// * [`plan_to_sql`] for converting a [`LogicalPlan`] to SQL
64///
65/// # Example
66/// ```
67/// use datafusion_expr::{col, lit};
68/// use datafusion_sql::unparser::expr_to_sql;
69/// let expr = col("a").gt(lit(4)); // form an expression `a > 4`
70/// let sql = expr_to_sql(&expr).unwrap(); // convert to ast::Expr
71/// // use the Display impl to convert to SQL text
72/// assert_eq!(sql.to_string(), "(a > 4)")
73/// ```
74///
75/// [`SqlToRel::sql_to_expr`]: crate::planner::SqlToRel::sql_to_expr
76/// [`plan_to_sql`]: crate::unparser::plan_to_sql
77/// [`LogicalPlan`]: datafusion_expr::logical_plan::LogicalPlan
78pub fn expr_to_sql(expr: &Expr) -> Result<ast::Expr> {
79    let unparser = Unparser::default();
80    unparser.expr_to_sql(expr)
81}
82
83const LOWEST: &BinaryOperator = &BinaryOperator::Or;
84// Closest precedence we have to IS operator is BitwiseAnd (any other) in PG docs
85// (https://www.postgresql.org/docs/7.2/sql-precedence.html)
86const IS: &BinaryOperator = &BinaryOperator::BitwiseAnd;
87
88impl Unparser<'_> {
89    pub fn expr_to_sql(&self, expr: &Expr) -> Result<ast::Expr> {
90        let mut root_expr = self.expr_to_sql_inner(expr)?;
91        if self.pretty {
92            root_expr = self.remove_unnecessary_nesting(root_expr, LOWEST, LOWEST);
93        }
94        Ok(root_expr)
95    }
96
97    fn expr_to_sql_inner(&self, expr: &Expr) -> Result<ast::Expr> {
98        match expr {
99            Expr::InList(InList {
100                expr,
101                list,
102                negated,
103            }) => {
104                let list_expr = list
105                    .iter()
106                    .map(|e| self.expr_to_sql_inner(e))
107                    .collect::<Result<Vec<_>>>()?;
108                Ok(ast::Expr::InList {
109                    expr: Box::new(self.expr_to_sql_inner(expr)?),
110                    list: list_expr,
111                    negated: *negated,
112                })
113            }
114            Expr::ScalarFunction(ScalarFunction { func, args }) => {
115                let func_name = func.name();
116
117                if let Some(expr) = self
118                    .dialect
119                    .scalar_function_to_sql_overrides(self, func_name, args)?
120                {
121                    return Ok(expr);
122                }
123
124                self.scalar_function_to_sql(func_name, args)
125            }
126            Expr::Between(Between {
127                expr,
128                negated,
129                low,
130                high,
131            }) => {
132                let sql_parser_expr = self.expr_to_sql_inner(expr)?;
133                let sql_low = self.expr_to_sql_inner(low)?;
134                let sql_high = self.expr_to_sql_inner(high)?;
135                Ok(ast::Expr::Nested(Box::new(self.between_op_to_sql(
136                    sql_parser_expr,
137                    *negated,
138                    sql_low,
139                    sql_high,
140                ))))
141            }
142            Expr::Column(col) => self.col_to_sql(col),
143            Expr::BinaryExpr(BinaryExpr { left, op, right }) => {
144                let l = self.expr_to_sql_inner(left.as_ref())?;
145                let r = self.expr_to_sql_inner(right.as_ref())?;
146                let op = self.op_to_sql(op)?;
147
148                Ok(ast::Expr::Nested(Box::new(self.binary_op_to_sql(l, r, op))))
149            }
150            Expr::Case(Case {
151                expr,
152                when_then_expr,
153                else_expr,
154            }) => {
155                let conditions = when_then_expr
156                    .iter()
157                    .map(|(w, _)| self.expr_to_sql_inner(w))
158                    .collect::<Result<Vec<_>>>()?;
159                let results = when_then_expr
160                    .iter()
161                    .map(|(_, t)| self.expr_to_sql_inner(t))
162                    .collect::<Result<Vec<_>>>()?;
163                let operand = match expr.as_ref() {
164                    Some(e) => match self.expr_to_sql_inner(e) {
165                        Ok(sql_expr) => Some(Box::new(sql_expr)),
166                        Err(_) => None,
167                    },
168                    None => None,
169                };
170                let else_result = match else_expr.as_ref() {
171                    Some(e) => match self.expr_to_sql_inner(e) {
172                        Ok(sql_expr) => Some(Box::new(sql_expr)),
173                        Err(_) => None,
174                    },
175                    None => None,
176                };
177
178                Ok(ast::Expr::Case {
179                    operand,
180                    conditions,
181                    results,
182                    else_result,
183                })
184            }
185            Expr::Cast(Cast { expr, data_type }) => {
186                Ok(self.cast_to_sql(expr, data_type)?)
187            }
188            Expr::Literal(value) => Ok(self.scalar_to_sql(value)?),
189            Expr::Alias(Alias { expr, name: _, .. }) => self.expr_to_sql_inner(expr),
190            Expr::WindowFunction(WindowFunction {
191                fun,
192                params:
193                    WindowFunctionParams {
194                        args,
195                        partition_by,
196                        order_by,
197                        window_frame,
198                        ..
199                    },
200            }) => {
201                let func_name = fun.name();
202
203                let args = self.function_args_to_sql(args)?;
204
205                let units = match window_frame.units {
206                    datafusion_expr::window_frame::WindowFrameUnits::Rows => {
207                        ast::WindowFrameUnits::Rows
208                    }
209                    datafusion_expr::window_frame::WindowFrameUnits::Range => {
210                        ast::WindowFrameUnits::Range
211                    }
212                    datafusion_expr::window_frame::WindowFrameUnits::Groups => {
213                        ast::WindowFrameUnits::Groups
214                    }
215                };
216
217                let order_by = order_by
218                    .iter()
219                    .map(|sort_expr| self.sort_to_sql(sort_expr))
220                    .collect::<Result<Vec<_>>>()?;
221
222                let start_bound = self.convert_bound(&window_frame.start_bound)?;
223                let end_bound = self.convert_bound(&window_frame.end_bound)?;
224
225                let window_frame = if self.dialect.window_func_support_window_frame(
226                    func_name,
227                    &start_bound,
228                    &end_bound,
229                ) {
230                    Some(ast::WindowFrame {
231                        units,
232                        start_bound,
233                        end_bound: Some(end_bound),
234                    })
235                } else {
236                    None
237                };
238
239                let over = Some(ast::WindowType::WindowSpec(ast::WindowSpec {
240                    window_name: None,
241                    partition_by: partition_by
242                        .iter()
243                        .map(|e| self.expr_to_sql_inner(e))
244                        .collect::<Result<Vec<_>>>()?,
245                    order_by,
246                    window_frame,
247                }));
248
249                Ok(ast::Expr::Function(Function {
250                    name: ObjectName(vec![Ident {
251                        value: func_name.to_string(),
252                        quote_style: None,
253                        span: Span::empty(),
254                    }]),
255                    args: ast::FunctionArguments::List(ast::FunctionArgumentList {
256                        duplicate_treatment: None,
257                        args,
258                        clauses: vec![],
259                    }),
260                    filter: None,
261                    null_treatment: None,
262                    over,
263                    within_group: vec![],
264                    parameters: ast::FunctionArguments::None,
265                    uses_odbc_syntax: false,
266                }))
267            }
268            Expr::SimilarTo(Like {
269                negated,
270                expr,
271                pattern,
272                escape_char,
273                case_insensitive: _,
274            })
275            | Expr::Like(Like {
276                negated,
277                expr,
278                pattern,
279                escape_char,
280                case_insensitive: _,
281            }) => Ok(ast::Expr::Like {
282                negated: *negated,
283                expr: Box::new(self.expr_to_sql_inner(expr)?),
284                pattern: Box::new(self.expr_to_sql_inner(pattern)?),
285                escape_char: escape_char.map(|c| c.to_string()),
286                any: false,
287            }),
288            Expr::AggregateFunction(agg) => {
289                let func_name = agg.func.name();
290                let AggregateFunctionParams {
291                    distinct,
292                    args,
293                    filter,
294                    ..
295                } = &agg.params;
296
297                let args = self.function_args_to_sql(args)?;
298                let filter = match filter {
299                    Some(filter) => Some(Box::new(self.expr_to_sql_inner(filter)?)),
300                    None => None,
301                };
302                Ok(ast::Expr::Function(Function {
303                    name: ObjectName(vec![Ident {
304                        value: func_name.to_string(),
305                        quote_style: None,
306                        span: Span::empty(),
307                    }]),
308                    args: ast::FunctionArguments::List(ast::FunctionArgumentList {
309                        duplicate_treatment: distinct
310                            .then_some(ast::DuplicateTreatment::Distinct),
311                        args,
312                        clauses: vec![],
313                    }),
314                    filter,
315                    null_treatment: None,
316                    over: None,
317                    within_group: vec![],
318                    parameters: ast::FunctionArguments::None,
319                    uses_odbc_syntax: false,
320                }))
321            }
322            Expr::ScalarSubquery(subq) => {
323                let sub_statement = self.plan_to_sql(subq.subquery.as_ref())?;
324                let sub_query = if let ast::Statement::Query(inner_query) = sub_statement
325                {
326                    inner_query
327                } else {
328                    return plan_err!(
329                        "Subquery must be a Query, but found {sub_statement:?}"
330                    );
331                };
332                Ok(ast::Expr::Subquery(sub_query))
333            }
334            Expr::InSubquery(insubq) => {
335                let inexpr = Box::new(self.expr_to_sql_inner(insubq.expr.as_ref())?);
336                let sub_statement =
337                    self.plan_to_sql(insubq.subquery.subquery.as_ref())?;
338                let sub_query = if let ast::Statement::Query(inner_query) = sub_statement
339                {
340                    inner_query
341                } else {
342                    return plan_err!(
343                        "Subquery must be a Query, but found {sub_statement:?}"
344                    );
345                };
346                Ok(ast::Expr::InSubquery {
347                    expr: inexpr,
348                    subquery: sub_query,
349                    negated: insubq.negated,
350                })
351            }
352            Expr::Exists(Exists { subquery, negated }) => {
353                let sub_statement = self.plan_to_sql(subquery.subquery.as_ref())?;
354                let sub_query = if let ast::Statement::Query(inner_query) = sub_statement
355                {
356                    inner_query
357                } else {
358                    return plan_err!(
359                        "Subquery must be a Query, but found {sub_statement:?}"
360                    );
361                };
362                Ok(ast::Expr::Exists {
363                    subquery: sub_query,
364                    negated: *negated,
365                })
366            }
367            Expr::IsNull(expr) => {
368                Ok(ast::Expr::IsNull(Box::new(self.expr_to_sql_inner(expr)?)))
369            }
370            Expr::IsNotNull(expr) => Ok(ast::Expr::IsNotNull(Box::new(
371                self.expr_to_sql_inner(expr)?,
372            ))),
373            Expr::IsTrue(expr) => {
374                Ok(ast::Expr::IsTrue(Box::new(self.expr_to_sql_inner(expr)?)))
375            }
376            Expr::IsNotTrue(expr) => Ok(ast::Expr::IsNotTrue(Box::new(
377                self.expr_to_sql_inner(expr)?,
378            ))),
379            Expr::IsFalse(expr) => {
380                Ok(ast::Expr::IsFalse(Box::new(self.expr_to_sql_inner(expr)?)))
381            }
382            Expr::IsNotFalse(expr) => Ok(ast::Expr::IsNotFalse(Box::new(
383                self.expr_to_sql_inner(expr)?,
384            ))),
385            Expr::IsUnknown(expr) => Ok(ast::Expr::IsUnknown(Box::new(
386                self.expr_to_sql_inner(expr)?,
387            ))),
388            Expr::IsNotUnknown(expr) => Ok(ast::Expr::IsNotUnknown(Box::new(
389                self.expr_to_sql_inner(expr)?,
390            ))),
391            Expr::Not(expr) => {
392                let sql_parser_expr = self.expr_to_sql_inner(expr)?;
393                Ok(AstExpr::UnaryOp {
394                    op: UnaryOperator::Not,
395                    expr: Box::new(sql_parser_expr),
396                })
397            }
398            Expr::Negative(expr) => {
399                let sql_parser_expr = self.expr_to_sql_inner(expr)?;
400                Ok(AstExpr::UnaryOp {
401                    op: UnaryOperator::Minus,
402                    expr: Box::new(sql_parser_expr),
403                })
404            }
405            Expr::ScalarVariable(_, ids) => {
406                if ids.is_empty() {
407                    return internal_err!("Not a valid ScalarVariable");
408                }
409
410                Ok(if ids.len() == 1 {
411                    ast::Expr::Identifier(
412                        self.new_ident_without_quote_style(ids[0].to_string()),
413                    )
414                } else {
415                    ast::Expr::CompoundIdentifier(
416                        ids.iter()
417                            .map(|i| self.new_ident_without_quote_style(i.to_string()))
418                            .collect(),
419                    )
420                })
421            }
422            Expr::TryCast(TryCast { expr, data_type }) => {
423                let inner_expr = self.expr_to_sql_inner(expr)?;
424                Ok(ast::Expr::Cast {
425                    kind: ast::CastKind::TryCast,
426                    expr: Box::new(inner_expr),
427                    data_type: self.arrow_dtype_to_ast_dtype(data_type)?,
428                    format: None,
429                })
430            }
431            // TODO: unparsing wildcard addition options
432            #[expect(deprecated)]
433            Expr::Wildcard { qualifier, .. } => {
434                let attached_token = AttachedToken::empty();
435                if let Some(qualifier) = qualifier {
436                    let idents: Vec<Ident> =
437                        qualifier.to_vec().into_iter().map(Ident::new).collect();
438                    Ok(ast::Expr::QualifiedWildcard(
439                        ObjectName(idents),
440                        attached_token,
441                    ))
442                } else {
443                    Ok(ast::Expr::Wildcard(attached_token))
444                }
445            }
446            Expr::GroupingSet(grouping_set) => match grouping_set {
447                GroupingSet::GroupingSets(grouping_sets) => {
448                    let expr_ast_sets = grouping_sets
449                        .iter()
450                        .map(|set| {
451                            set.iter()
452                                .map(|e| self.expr_to_sql_inner(e))
453                                .collect::<Result<Vec<_>>>()
454                        })
455                        .collect::<Result<Vec<_>>>()?;
456
457                    Ok(ast::Expr::GroupingSets(expr_ast_sets))
458                }
459                GroupingSet::Cube(cube) => {
460                    let expr_ast_sets = cube
461                        .iter()
462                        .map(|e| {
463                            let sql = self.expr_to_sql_inner(e)?;
464                            Ok(vec![sql])
465                        })
466                        .collect::<Result<Vec<_>>>()?;
467                    Ok(ast::Expr::Cube(expr_ast_sets))
468                }
469                GroupingSet::Rollup(rollup) => {
470                    let expr_ast_sets: Vec<Vec<AstExpr>> = rollup
471                        .iter()
472                        .map(|e| {
473                            let sql = self.expr_to_sql_inner(e)?;
474                            Ok(vec![sql])
475                        })
476                        .collect::<Result<Vec<_>>>()?;
477                    Ok(ast::Expr::Rollup(expr_ast_sets))
478                }
479            },
480            Expr::Placeholder(p) => {
481                Ok(ast::Expr::Value(ast::Value::Placeholder(p.id.to_string())))
482            }
483            Expr::OuterReferenceColumn(_, col) => self.col_to_sql(col),
484            Expr::Unnest(unnest) => self.unnest_to_sql(unnest),
485        }
486    }
487
488    pub fn scalar_function_to_sql(
489        &self,
490        func_name: &str,
491        args: &[Expr],
492    ) -> Result<ast::Expr> {
493        match func_name {
494            "make_array" => self.make_array_to_sql(args),
495            "array_element" => self.array_element_to_sql(args),
496            "named_struct" => self.named_struct_to_sql(args),
497            "get_field" => self.get_field_to_sql(args),
498            "map" => self.map_to_sql(args),
499            // TODO: support for the construct and access functions of the `map` type
500            _ => self.scalar_function_to_sql_internal(func_name, args),
501        }
502    }
503
504    fn scalar_function_to_sql_internal(
505        &self,
506        func_name: &str,
507        args: &[Expr],
508    ) -> Result<ast::Expr> {
509        let args = self.function_args_to_sql(args)?;
510        Ok(ast::Expr::Function(Function {
511            name: ObjectName(vec![Ident {
512                value: func_name.to_string(),
513                quote_style: None,
514                span: Span::empty(),
515            }]),
516            args: ast::FunctionArguments::List(ast::FunctionArgumentList {
517                duplicate_treatment: None,
518                args,
519                clauses: vec![],
520            }),
521            filter: None,
522            null_treatment: None,
523            over: None,
524            within_group: vec![],
525            parameters: ast::FunctionArguments::None,
526            uses_odbc_syntax: false,
527        }))
528    }
529
530    fn make_array_to_sql(&self, args: &[Expr]) -> Result<ast::Expr> {
531        let args = args
532            .iter()
533            .map(|e| self.expr_to_sql(e))
534            .collect::<Result<Vec<_>>>()?;
535        Ok(ast::Expr::Array(Array {
536            elem: args,
537            named: false,
538        }))
539    }
540
541    fn scalar_value_list_to_sql(&self, array: &ArrayRef) -> Result<ast::Expr> {
542        let mut elem = Vec::new();
543        for i in 0..array.len() {
544            let value = ScalarValue::try_from_array(&array, i)?;
545            elem.push(self.scalar_to_sql(&value)?);
546        }
547
548        Ok(ast::Expr::Array(Array { elem, named: false }))
549    }
550
551    fn array_element_to_sql(&self, args: &[Expr]) -> Result<ast::Expr> {
552        if args.len() != 2 {
553            return internal_err!("array_element must have exactly 2 arguments");
554        }
555        let array = self.expr_to_sql(&args[0])?;
556        let index = self.expr_to_sql(&args[1])?;
557        Ok(ast::Expr::CompoundFieldAccess {
558            root: Box::new(array),
559            access_chain: vec![ast::AccessExpr::Subscript(Subscript::Index { index })],
560        })
561    }
562
563    fn named_struct_to_sql(&self, args: &[Expr]) -> Result<ast::Expr> {
564        if args.len() % 2 != 0 {
565            return internal_err!("named_struct must have an even number of arguments");
566        }
567
568        let args = args
569            .chunks_exact(2)
570            .map(|chunk| {
571                let key = match &chunk[0] {
572                    Expr::Literal(ScalarValue::Utf8(Some(s))) => self.new_ident_quoted_if_needs(s.to_string()),
573                    _ => return internal_err!("named_struct expects even arguments to be strings, but received: {:?}", &chunk[0])
574                };
575
576                Ok(ast::DictionaryField {
577                    key,
578                    value: Box::new(self.expr_to_sql(&chunk[1])?),
579                })
580            })
581            .collect::<Result<Vec<_>>>()?;
582
583        Ok(ast::Expr::Dictionary(args))
584    }
585
586    fn get_field_to_sql(&self, args: &[Expr]) -> Result<ast::Expr> {
587        if args.len() != 2 {
588            return internal_err!("get_field must have exactly 2 arguments");
589        }
590
591        let mut id = match &args[0] {
592            Expr::Column(col) => match self.col_to_sql(col)? {
593                ast::Expr::Identifier(ident) => vec![ident],
594                ast::Expr::CompoundIdentifier(idents) => idents,
595                other => return internal_err!("expected col_to_sql to return an Identifier or CompoundIdentifier, but received: {:?}", other),
596            },
597            _ => return internal_err!("get_field expects first argument to be column, but received: {:?}", &args[0]),
598        };
599
600        let field = match &args[1] {
601            Expr::Literal(lit) => self.new_ident_quoted_if_needs(lit.to_string()),
602            _ => {
603                return internal_err!(
604                "get_field expects second argument to be a string, but received: {:?}",
605                &args[0]
606            )
607            }
608        };
609        id.push(field);
610
611        Ok(ast::Expr::CompoundIdentifier(id))
612    }
613
614    fn map_to_sql(&self, args: &[Expr]) -> Result<ast::Expr> {
615        if args.len() != 2 {
616            return internal_err!("map must have exactly 2 arguments");
617        }
618
619        let ast::Expr::Array(Array { elem: keys, .. }) = self.expr_to_sql(&args[0])?
620        else {
621            return internal_err!(
622                "map expects first argument to be an array, but received: {:?}",
623                &args[0]
624            );
625        };
626
627        let ast::Expr::Array(Array { elem: values, .. }) = self.expr_to_sql(&args[1])?
628        else {
629            return internal_err!(
630                "map expects second argument to be an array, but received: {:?}",
631                &args[1]
632            );
633        };
634
635        let entries = keys
636            .into_iter()
637            .zip(values)
638            .map(|(key, value)| ast::MapEntry {
639                key: Box::new(key),
640                value: Box::new(value),
641            })
642            .collect();
643
644        Ok(ast::Expr::Map(ast::Map { entries }))
645    }
646
647    pub fn sort_to_sql(&self, sort: &Sort) -> Result<ast::OrderByExpr> {
648        let Sort {
649            expr,
650            asc,
651            nulls_first,
652        } = sort;
653        let sql_parser_expr = self.expr_to_sql(expr)?;
654
655        let nulls_first = if self.dialect.supports_nulls_first_in_sort() {
656            Some(*nulls_first)
657        } else {
658            None
659        };
660
661        Ok(ast::OrderByExpr {
662            expr: sql_parser_expr,
663            asc: Some(*asc),
664            nulls_first,
665            with_fill: None,
666        })
667    }
668
669    fn ast_type_for_date64_in_cast(&self) -> ast::DataType {
670        if self.dialect.use_timestamp_for_date64() {
671            ast::DataType::Timestamp(None, TimezoneInfo::None)
672        } else {
673            ast::DataType::Datetime(None)
674        }
675    }
676
677    fn col_to_sql(&self, col: &Column) -> Result<ast::Expr> {
678        if let Some(table_ref) = &col.relation {
679            let mut id = if self.dialect.full_qualified_col() {
680                table_ref.to_vec()
681            } else {
682                vec![table_ref.table().to_string()]
683            };
684            id.push(col.name.to_string());
685            return Ok(ast::Expr::CompoundIdentifier(
686                id.iter()
687                    .map(|i| self.new_ident_quoted_if_needs(i.to_string()))
688                    .collect(),
689            ));
690        }
691        Ok(ast::Expr::Identifier(
692            self.new_ident_quoted_if_needs(col.name.to_string()),
693        ))
694    }
695
696    fn convert_bound(
697        &self,
698        bound: &datafusion_expr::window_frame::WindowFrameBound,
699    ) -> Result<ast::WindowFrameBound> {
700        match bound {
701            datafusion_expr::window_frame::WindowFrameBound::Preceding(val) => {
702                Ok(ast::WindowFrameBound::Preceding({
703                    let val = self.scalar_to_sql(val)?;
704                    if let ast::Expr::Value(ast::Value::Null) = &val {
705                        None
706                    } else {
707                        Some(Box::new(val))
708                    }
709                }))
710            }
711            datafusion_expr::window_frame::WindowFrameBound::Following(val) => {
712                Ok(ast::WindowFrameBound::Following({
713                    let val = self.scalar_to_sql(val)?;
714                    if let ast::Expr::Value(ast::Value::Null) = &val {
715                        None
716                    } else {
717                        Some(Box::new(val))
718                    }
719                }))
720            }
721            datafusion_expr::window_frame::WindowFrameBound::CurrentRow => {
722                Ok(ast::WindowFrameBound::CurrentRow)
723            }
724        }
725    }
726
727    pub(crate) fn function_args_to_sql(
728        &self,
729        args: &[Expr],
730    ) -> Result<Vec<ast::FunctionArg>> {
731        args.iter()
732            .map(|e| {
733                #[expect(deprecated)]
734                if matches!(
735                    e,
736                    Expr::Wildcard {
737                        qualifier: None,
738                        ..
739                    }
740                ) {
741                    Ok(ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Wildcard))
742                } else {
743                    self.expr_to_sql(e)
744                        .map(|e| ast::FunctionArg::Unnamed(ast::FunctionArgExpr::Expr(e)))
745                }
746            })
747            .collect::<Result<Vec<_>>>()
748    }
749
750    /// This function can create an identifier with or without quotes based on the dialect rules
751    pub(super) fn new_ident_quoted_if_needs(&self, ident: String) -> Ident {
752        let quote_style = self.dialect.identifier_quote_style(&ident);
753        Ident {
754            value: ident,
755            quote_style,
756            span: Span::empty(),
757        }
758    }
759
760    pub(super) fn new_ident_without_quote_style(&self, str: String) -> Ident {
761        Ident {
762            value: str,
763            quote_style: None,
764            span: Span::empty(),
765        }
766    }
767
768    pub(super) fn binary_op_to_sql(
769        &self,
770        lhs: ast::Expr,
771        rhs: ast::Expr,
772        op: BinaryOperator,
773    ) -> ast::Expr {
774        ast::Expr::BinaryOp {
775            left: Box::new(lhs),
776            op,
777            right: Box::new(rhs),
778        }
779    }
780
781    /// Given an expression of the form `((a + b) * (c * d))`,
782    /// the parenthesis is redundant if the precedence of the nested expression is already higher
783    /// than the surrounding operators' precedence. The above expression would become
784    /// `(a + b) * c * d`.
785    ///
786    /// Also note that when fetching the precedence of a nested expression, we ignore other nested
787    /// expressions, so precedence of expr `(a * (b + c))` equals `*` and not `+`.
788    fn remove_unnecessary_nesting(
789        &self,
790        expr: ast::Expr,
791        left_op: &BinaryOperator,
792        right_op: &BinaryOperator,
793    ) -> ast::Expr {
794        match expr {
795            ast::Expr::Nested(nested) => {
796                let surrounding_precedence = self
797                    .sql_op_precedence(left_op)
798                    .max(self.sql_op_precedence(right_op));
799
800                let inner_precedence = self.inner_precedence(&nested);
801
802                let not_associative =
803                    matches!(left_op, BinaryOperator::Minus | BinaryOperator::Divide);
804
805                if inner_precedence == surrounding_precedence && not_associative {
806                    ast::Expr::Nested(Box::new(
807                        self.remove_unnecessary_nesting(*nested, LOWEST, LOWEST),
808                    ))
809                } else if inner_precedence >= surrounding_precedence {
810                    self.remove_unnecessary_nesting(*nested, left_op, right_op)
811                } else {
812                    ast::Expr::Nested(Box::new(
813                        self.remove_unnecessary_nesting(*nested, LOWEST, LOWEST),
814                    ))
815                }
816            }
817            ast::Expr::BinaryOp { left, op, right } => ast::Expr::BinaryOp {
818                left: Box::new(self.remove_unnecessary_nesting(*left, left_op, &op)),
819                right: Box::new(self.remove_unnecessary_nesting(*right, &op, right_op)),
820                op,
821            },
822            ast::Expr::IsTrue(expr) => ast::Expr::IsTrue(Box::new(
823                self.remove_unnecessary_nesting(*expr, left_op, IS),
824            )),
825            ast::Expr::IsNotTrue(expr) => ast::Expr::IsNotTrue(Box::new(
826                self.remove_unnecessary_nesting(*expr, left_op, IS),
827            )),
828            ast::Expr::IsFalse(expr) => ast::Expr::IsFalse(Box::new(
829                self.remove_unnecessary_nesting(*expr, left_op, IS),
830            )),
831            ast::Expr::IsNotFalse(expr) => ast::Expr::IsNotFalse(Box::new(
832                self.remove_unnecessary_nesting(*expr, left_op, IS),
833            )),
834            ast::Expr::IsNull(expr) => ast::Expr::IsNull(Box::new(
835                self.remove_unnecessary_nesting(*expr, left_op, IS),
836            )),
837            ast::Expr::IsNotNull(expr) => ast::Expr::IsNotNull(Box::new(
838                self.remove_unnecessary_nesting(*expr, left_op, IS),
839            )),
840            ast::Expr::IsUnknown(expr) => ast::Expr::IsUnknown(Box::new(
841                self.remove_unnecessary_nesting(*expr, left_op, IS),
842            )),
843            ast::Expr::IsNotUnknown(expr) => ast::Expr::IsNotUnknown(Box::new(
844                self.remove_unnecessary_nesting(*expr, left_op, IS),
845            )),
846            _ => expr,
847        }
848    }
849
850    fn inner_precedence(&self, expr: &ast::Expr) -> u8 {
851        match expr {
852            ast::Expr::Nested(_) | ast::Expr::Identifier(_) | ast::Expr::Value(_) => 100,
853            ast::Expr::BinaryOp { op, .. } => self.sql_op_precedence(op),
854            // Closest precedence we currently have to Between is PGLikeMatch
855            // (https://www.postgresql.org/docs/7.2/sql-precedence.html)
856            ast::Expr::Between { .. } => {
857                self.sql_op_precedence(&BinaryOperator::PGLikeMatch)
858            }
859            _ => 0,
860        }
861    }
862
863    pub(super) fn between_op_to_sql(
864        &self,
865        expr: ast::Expr,
866        negated: bool,
867        low: ast::Expr,
868        high: ast::Expr,
869    ) -> ast::Expr {
870        ast::Expr::Between {
871            expr: Box::new(expr),
872            negated,
873            low: Box::new(low),
874            high: Box::new(high),
875        }
876    }
877
878    fn sql_op_precedence(&self, op: &BinaryOperator) -> u8 {
879        match self.sql_to_op(op) {
880            Ok(op) => op.precedence(),
881            Err(_) => 0,
882        }
883    }
884
885    fn sql_to_op(&self, op: &BinaryOperator) -> Result<Operator> {
886        match op {
887            BinaryOperator::Eq => Ok(Operator::Eq),
888            BinaryOperator::NotEq => Ok(Operator::NotEq),
889            BinaryOperator::Lt => Ok(Operator::Lt),
890            BinaryOperator::LtEq => Ok(Operator::LtEq),
891            BinaryOperator::Gt => Ok(Operator::Gt),
892            BinaryOperator::GtEq => Ok(Operator::GtEq),
893            BinaryOperator::Plus => Ok(Operator::Plus),
894            BinaryOperator::Minus => Ok(Operator::Minus),
895            BinaryOperator::Multiply => Ok(Operator::Multiply),
896            BinaryOperator::Divide => Ok(Operator::Divide),
897            BinaryOperator::Modulo => Ok(Operator::Modulo),
898            BinaryOperator::And => Ok(Operator::And),
899            BinaryOperator::Or => Ok(Operator::Or),
900            BinaryOperator::PGRegexMatch => Ok(Operator::RegexMatch),
901            BinaryOperator::PGRegexIMatch => Ok(Operator::RegexIMatch),
902            BinaryOperator::PGRegexNotMatch => Ok(Operator::RegexNotMatch),
903            BinaryOperator::PGRegexNotIMatch => Ok(Operator::RegexNotIMatch),
904            BinaryOperator::PGILikeMatch => Ok(Operator::ILikeMatch),
905            BinaryOperator::PGNotLikeMatch => Ok(Operator::NotLikeMatch),
906            BinaryOperator::PGLikeMatch => Ok(Operator::LikeMatch),
907            BinaryOperator::PGNotILikeMatch => Ok(Operator::NotILikeMatch),
908            BinaryOperator::BitwiseAnd => Ok(Operator::BitwiseAnd),
909            BinaryOperator::BitwiseOr => Ok(Operator::BitwiseOr),
910            BinaryOperator::BitwiseXor => Ok(Operator::BitwiseXor),
911            BinaryOperator::PGBitwiseShiftRight => Ok(Operator::BitwiseShiftRight),
912            BinaryOperator::PGBitwiseShiftLeft => Ok(Operator::BitwiseShiftLeft),
913            BinaryOperator::StringConcat => Ok(Operator::StringConcat),
914            BinaryOperator::AtArrow => Ok(Operator::AtArrow),
915            BinaryOperator::ArrowAt => Ok(Operator::ArrowAt),
916            _ => not_impl_err!("unsupported operation: {op:?}"),
917        }
918    }
919
920    fn op_to_sql(&self, op: &Operator) -> Result<BinaryOperator> {
921        match op {
922            Operator::Eq => Ok(BinaryOperator::Eq),
923            Operator::NotEq => Ok(BinaryOperator::NotEq),
924            Operator::Lt => Ok(BinaryOperator::Lt),
925            Operator::LtEq => Ok(BinaryOperator::LtEq),
926            Operator::Gt => Ok(BinaryOperator::Gt),
927            Operator::GtEq => Ok(BinaryOperator::GtEq),
928            Operator::Plus => Ok(BinaryOperator::Plus),
929            Operator::Minus => Ok(BinaryOperator::Minus),
930            Operator::Multiply => Ok(BinaryOperator::Multiply),
931            Operator::Divide => Ok(self.dialect.division_operator()),
932            Operator::Modulo => Ok(BinaryOperator::Modulo),
933            Operator::And => Ok(BinaryOperator::And),
934            Operator::Or => Ok(BinaryOperator::Or),
935            Operator::IsDistinctFrom => not_impl_err!("unsupported operation: {op:?}"),
936            Operator::IsNotDistinctFrom => not_impl_err!("unsupported operation: {op:?}"),
937            Operator::RegexMatch => Ok(BinaryOperator::PGRegexMatch),
938            Operator::RegexIMatch => Ok(BinaryOperator::PGRegexIMatch),
939            Operator::RegexNotMatch => Ok(BinaryOperator::PGRegexNotMatch),
940            Operator::RegexNotIMatch => Ok(BinaryOperator::PGRegexNotIMatch),
941            Operator::ILikeMatch => Ok(BinaryOperator::PGILikeMatch),
942            Operator::NotLikeMatch => Ok(BinaryOperator::PGNotLikeMatch),
943            Operator::LikeMatch => Ok(BinaryOperator::PGLikeMatch),
944            Operator::NotILikeMatch => Ok(BinaryOperator::PGNotILikeMatch),
945            Operator::BitwiseAnd => Ok(BinaryOperator::BitwiseAnd),
946            Operator::BitwiseOr => Ok(BinaryOperator::BitwiseOr),
947            Operator::BitwiseXor => Ok(BinaryOperator::BitwiseXor),
948            Operator::BitwiseShiftRight => Ok(BinaryOperator::PGBitwiseShiftRight),
949            Operator::BitwiseShiftLeft => Ok(BinaryOperator::PGBitwiseShiftLeft),
950            Operator::StringConcat => Ok(BinaryOperator::StringConcat),
951            Operator::AtArrow => not_impl_err!("unsupported operation: {op:?}"),
952            Operator::ArrowAt => not_impl_err!("unsupported operation: {op:?}"),
953        }
954    }
955
956    fn handle_timestamp<T: ArrowTemporalType>(
957        &self,
958        v: &ScalarValue,
959        tz: &Option<Arc<str>>,
960    ) -> Result<ast::Expr>
961    where
962        i64: From<T::Native>,
963    {
964        let ts = if let Some(tz) = tz {
965            v.to_array()?
966                .as_any()
967                .downcast_ref::<PrimitiveArray<T>>()
968                .ok_or(internal_datafusion_err!(
969                    "Failed to downcast type {v:?} to arrow array"
970                ))?
971                .value_as_datetime_with_tz(0, tz.parse()?)
972                .ok_or(internal_datafusion_err!(
973                    "Unable to convert {v:?} to DateTime"
974                ))?
975                .to_string()
976        } else {
977            v.to_array()?
978                .as_any()
979                .downcast_ref::<PrimitiveArray<T>>()
980                .ok_or(internal_datafusion_err!(
981                    "Failed to downcast type {v:?} to arrow array"
982                ))?
983                .value_as_datetime(0)
984                .ok_or(internal_datafusion_err!(
985                    "Unable to convert {v:?} to DateTime"
986                ))?
987                .to_string()
988        };
989
990        let time_unit = match T::DATA_TYPE {
991            DataType::Timestamp(unit, _) => unit,
992            _ => {
993                return Err(internal_datafusion_err!(
994                    "Expected Timestamp, got {:?}",
995                    T::DATA_TYPE
996                ))
997            }
998        };
999
1000        Ok(ast::Expr::Cast {
1001            kind: ast::CastKind::Cast,
1002            expr: Box::new(ast::Expr::Value(SingleQuotedString(ts))),
1003            data_type: self.dialect.timestamp_cast_dtype(&time_unit, &None),
1004            format: None,
1005        })
1006    }
1007
1008    fn handle_time<T: ArrowTemporalType>(&self, v: &ScalarValue) -> Result<ast::Expr>
1009    where
1010        i64: From<T::Native>,
1011    {
1012        let time = v
1013            .to_array()?
1014            .as_any()
1015            .downcast_ref::<PrimitiveArray<T>>()
1016            .ok_or(internal_datafusion_err!(
1017                "Failed to downcast type {v:?} to arrow array"
1018            ))?
1019            .value_as_time(0)
1020            .ok_or(internal_datafusion_err!("Unable to convert {v:?} to Time"))?
1021            .to_string();
1022        Ok(ast::Expr::Cast {
1023            kind: ast::CastKind::Cast,
1024            expr: Box::new(ast::Expr::Value(SingleQuotedString(time))),
1025            data_type: ast::DataType::Time(None, TimezoneInfo::None),
1026            format: None,
1027        })
1028    }
1029
1030    // Explicit type cast on ast::Expr::Value is not needed by underlying engine for certain types
1031    // For example: CAST(Utf8("binary_value") AS Binary) and  CAST(Utf8("dictionary_value") AS Dictionary)
1032    fn cast_to_sql(&self, expr: &Expr, data_type: &DataType) -> Result<ast::Expr> {
1033        let inner_expr = self.expr_to_sql_inner(expr)?;
1034        match inner_expr {
1035            ast::Expr::Value(_) => match data_type {
1036                DataType::Dictionary(_, _) | DataType::Binary | DataType::BinaryView => {
1037                    Ok(inner_expr)
1038                }
1039                _ => Ok(ast::Expr::Cast {
1040                    kind: ast::CastKind::Cast,
1041                    expr: Box::new(inner_expr),
1042                    data_type: self.arrow_dtype_to_ast_dtype(data_type)?,
1043                    format: None,
1044                }),
1045            },
1046            _ => Ok(ast::Expr::Cast {
1047                kind: ast::CastKind::Cast,
1048                expr: Box::new(inner_expr),
1049                data_type: self.arrow_dtype_to_ast_dtype(data_type)?,
1050                format: None,
1051            }),
1052        }
1053    }
1054
1055    /// DataFusion ScalarValues sometimes require a ast::Expr to construct.
1056    /// For example ScalarValue::Date32(d) corresponds to the ast::Expr CAST('datestr' as DATE)
1057    fn scalar_to_sql(&self, v: &ScalarValue) -> Result<ast::Expr> {
1058        match v {
1059            ScalarValue::Null => Ok(ast::Expr::Value(ast::Value::Null)),
1060            ScalarValue::Boolean(Some(b)) => {
1061                Ok(ast::Expr::Value(ast::Value::Boolean(b.to_owned())))
1062            }
1063            ScalarValue::Boolean(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1064            ScalarValue::Float16(Some(f)) => {
1065                Ok(ast::Expr::Value(ast::Value::Number(f.to_string(), false)))
1066            }
1067            ScalarValue::Float16(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1068            ScalarValue::Float32(Some(f)) => {
1069                let f_val = match f.fract() {
1070                    0.0 => format!("{:.1}", f),
1071                    _ => format!("{}", f),
1072                };
1073                Ok(ast::Expr::Value(ast::Value::Number(f_val, false)))
1074            }
1075            ScalarValue::Float32(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1076            ScalarValue::Float64(Some(f)) => {
1077                let f_val = match f.fract() {
1078                    0.0 => format!("{:.1}", f),
1079                    _ => format!("{}", f),
1080                };
1081                Ok(ast::Expr::Value(ast::Value::Number(f_val, false)))
1082            }
1083            ScalarValue::Float64(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1084            ScalarValue::Decimal128(Some(value), precision, scale) => {
1085                Ok(ast::Expr::Value(ast::Value::Number(
1086                    Decimal128Type::format_decimal(*value, *precision, *scale),
1087                    false,
1088                )))
1089            }
1090            ScalarValue::Decimal128(None, ..) => Ok(ast::Expr::Value(ast::Value::Null)),
1091            ScalarValue::Decimal256(Some(value), precision, scale) => {
1092                Ok(ast::Expr::Value(ast::Value::Number(
1093                    Decimal256Type::format_decimal(*value, *precision, *scale),
1094                    false,
1095                )))
1096            }
1097            ScalarValue::Decimal256(None, ..) => Ok(ast::Expr::Value(ast::Value::Null)),
1098            ScalarValue::Int8(Some(i)) => {
1099                Ok(ast::Expr::Value(ast::Value::Number(i.to_string(), false)))
1100            }
1101            ScalarValue::Int8(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1102            ScalarValue::Int16(Some(i)) => {
1103                Ok(ast::Expr::Value(ast::Value::Number(i.to_string(), false)))
1104            }
1105            ScalarValue::Int16(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1106            ScalarValue::Int32(Some(i)) => {
1107                Ok(ast::Expr::Value(ast::Value::Number(i.to_string(), false)))
1108            }
1109            ScalarValue::Int32(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1110            ScalarValue::Int64(Some(i)) => {
1111                Ok(ast::Expr::Value(ast::Value::Number(i.to_string(), false)))
1112            }
1113            ScalarValue::Int64(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1114            ScalarValue::UInt8(Some(ui)) => {
1115                Ok(ast::Expr::Value(ast::Value::Number(ui.to_string(), false)))
1116            }
1117            ScalarValue::UInt8(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1118            ScalarValue::UInt16(Some(ui)) => {
1119                Ok(ast::Expr::Value(ast::Value::Number(ui.to_string(), false)))
1120            }
1121            ScalarValue::UInt16(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1122            ScalarValue::UInt32(Some(ui)) => {
1123                Ok(ast::Expr::Value(ast::Value::Number(ui.to_string(), false)))
1124            }
1125            ScalarValue::UInt32(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1126            ScalarValue::UInt64(Some(ui)) => {
1127                Ok(ast::Expr::Value(ast::Value::Number(ui.to_string(), false)))
1128            }
1129            ScalarValue::UInt64(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1130            ScalarValue::Utf8(Some(str)) => {
1131                Ok(ast::Expr::Value(SingleQuotedString(str.to_string())))
1132            }
1133            ScalarValue::Utf8(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1134            ScalarValue::Utf8View(Some(str)) => {
1135                Ok(ast::Expr::Value(SingleQuotedString(str.to_string())))
1136            }
1137            ScalarValue::Utf8View(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1138            ScalarValue::LargeUtf8(Some(str)) => {
1139                Ok(ast::Expr::Value(SingleQuotedString(str.to_string())))
1140            }
1141            ScalarValue::LargeUtf8(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1142            ScalarValue::Binary(Some(_)) => not_impl_err!("Unsupported scalar: {v:?}"),
1143            ScalarValue::Binary(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1144            ScalarValue::BinaryView(Some(_)) => {
1145                not_impl_err!("Unsupported scalar: {v:?}")
1146            }
1147            ScalarValue::BinaryView(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1148            ScalarValue::FixedSizeBinary(..) => {
1149                not_impl_err!("Unsupported scalar: {v:?}")
1150            }
1151            ScalarValue::LargeBinary(Some(_)) => {
1152                not_impl_err!("Unsupported scalar: {v:?}")
1153            }
1154            ScalarValue::LargeBinary(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1155            ScalarValue::FixedSizeList(a) => self.scalar_value_list_to_sql(a.values()),
1156            ScalarValue::List(a) => self.scalar_value_list_to_sql(a.values()),
1157            ScalarValue::LargeList(a) => self.scalar_value_list_to_sql(a.values()),
1158            ScalarValue::Date32(Some(_)) => {
1159                let date = v
1160                    .to_array()?
1161                    .as_any()
1162                    .downcast_ref::<Date32Array>()
1163                    .ok_or(internal_datafusion_err!(
1164                        "Unable to downcast to Date32 from Date32 scalar"
1165                    ))?
1166                    .value_as_date(0)
1167                    .ok_or(internal_datafusion_err!(
1168                        "Unable to convert Date32 to NaiveDate"
1169                    ))?;
1170
1171                Ok(ast::Expr::Cast {
1172                    kind: ast::CastKind::Cast,
1173                    expr: Box::new(ast::Expr::Value(SingleQuotedString(
1174                        date.to_string(),
1175                    ))),
1176                    data_type: ast::DataType::Date,
1177                    format: None,
1178                })
1179            }
1180            ScalarValue::Date32(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1181            ScalarValue::Date64(Some(_)) => {
1182                let datetime = v
1183                    .to_array()?
1184                    .as_any()
1185                    .downcast_ref::<Date64Array>()
1186                    .ok_or(internal_datafusion_err!(
1187                        "Unable to downcast to Date64 from Date64 scalar"
1188                    ))?
1189                    .value_as_datetime(0)
1190                    .ok_or(internal_datafusion_err!(
1191                        "Unable to convert Date64 to NaiveDateTime"
1192                    ))?;
1193
1194                Ok(ast::Expr::Cast {
1195                    kind: ast::CastKind::Cast,
1196                    expr: Box::new(ast::Expr::Value(SingleQuotedString(
1197                        datetime.to_string(),
1198                    ))),
1199                    data_type: self.ast_type_for_date64_in_cast(),
1200                    format: None,
1201                })
1202            }
1203            ScalarValue::Date64(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1204            ScalarValue::Time32Second(Some(_t)) => {
1205                self.handle_time::<Time32SecondType>(v)
1206            }
1207            ScalarValue::Time32Second(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1208            ScalarValue::Time32Millisecond(Some(_t)) => {
1209                self.handle_time::<Time32MillisecondType>(v)
1210            }
1211            ScalarValue::Time32Millisecond(None) => {
1212                Ok(ast::Expr::Value(ast::Value::Null))
1213            }
1214            ScalarValue::Time64Microsecond(Some(_t)) => {
1215                self.handle_time::<Time64MicrosecondType>(v)
1216            }
1217            ScalarValue::Time64Microsecond(None) => {
1218                Ok(ast::Expr::Value(ast::Value::Null))
1219            }
1220            ScalarValue::Time64Nanosecond(Some(_t)) => {
1221                self.handle_time::<Time64NanosecondType>(v)
1222            }
1223            ScalarValue::Time64Nanosecond(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1224            ScalarValue::TimestampSecond(Some(_ts), tz) => {
1225                self.handle_timestamp::<TimestampSecondType>(v, tz)
1226            }
1227            ScalarValue::TimestampSecond(None, _) => {
1228                Ok(ast::Expr::Value(ast::Value::Null))
1229            }
1230            ScalarValue::TimestampMillisecond(Some(_ts), tz) => {
1231                self.handle_timestamp::<TimestampMillisecondType>(v, tz)
1232            }
1233            ScalarValue::TimestampMillisecond(None, _) => {
1234                Ok(ast::Expr::Value(ast::Value::Null))
1235            }
1236            ScalarValue::TimestampMicrosecond(Some(_ts), tz) => {
1237                self.handle_timestamp::<TimestampMicrosecondType>(v, tz)
1238            }
1239            ScalarValue::TimestampMicrosecond(None, _) => {
1240                Ok(ast::Expr::Value(ast::Value::Null))
1241            }
1242            ScalarValue::TimestampNanosecond(Some(_ts), tz) => {
1243                self.handle_timestamp::<TimestampNanosecondType>(v, tz)
1244            }
1245            ScalarValue::TimestampNanosecond(None, _) => {
1246                Ok(ast::Expr::Value(ast::Value::Null))
1247            }
1248            ScalarValue::IntervalYearMonth(Some(_))
1249            | ScalarValue::IntervalDayTime(Some(_))
1250            | ScalarValue::IntervalMonthDayNano(Some(_)) => {
1251                self.interval_scalar_to_sql(v)
1252            }
1253            ScalarValue::IntervalYearMonth(None) => {
1254                Ok(ast::Expr::Value(ast::Value::Null))
1255            }
1256            ScalarValue::IntervalDayTime(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1257            ScalarValue::IntervalMonthDayNano(None) => {
1258                Ok(ast::Expr::Value(ast::Value::Null))
1259            }
1260            ScalarValue::DurationSecond(Some(_d)) => {
1261                not_impl_err!("Unsupported scalar: {v:?}")
1262            }
1263            ScalarValue::DurationSecond(None) => Ok(ast::Expr::Value(ast::Value::Null)),
1264            ScalarValue::DurationMillisecond(Some(_d)) => {
1265                not_impl_err!("Unsupported scalar: {v:?}")
1266            }
1267            ScalarValue::DurationMillisecond(None) => {
1268                Ok(ast::Expr::Value(ast::Value::Null))
1269            }
1270            ScalarValue::DurationMicrosecond(Some(_d)) => {
1271                not_impl_err!("Unsupported scalar: {v:?}")
1272            }
1273            ScalarValue::DurationMicrosecond(None) => {
1274                Ok(ast::Expr::Value(ast::Value::Null))
1275            }
1276            ScalarValue::DurationNanosecond(Some(_d)) => {
1277                not_impl_err!("Unsupported scalar: {v:?}")
1278            }
1279            ScalarValue::DurationNanosecond(None) => {
1280                Ok(ast::Expr::Value(ast::Value::Null))
1281            }
1282            ScalarValue::Struct(_) => not_impl_err!("Unsupported scalar: {v:?}"),
1283            ScalarValue::Map(_) => not_impl_err!("Unsupported scalar: {v:?}"),
1284            ScalarValue::Union(..) => not_impl_err!("Unsupported scalar: {v:?}"),
1285            ScalarValue::Dictionary(_k, v) => self.scalar_to_sql(v),
1286        }
1287    }
1288
1289    /// MySQL requires INTERVAL sql to be in the format: INTERVAL 1 YEAR + INTERVAL 1 MONTH + INTERVAL 1 DAY etc
1290    /// `<https://dev.mysql.com/doc/refman/8.4/en/expressions.html#temporal-intervals>`
1291    /// Interval sequence can't be wrapped in brackets - (INTERVAL 1 YEAR + INTERVAL 1 MONTH ...) so we need to generate
1292    /// a single INTERVAL expression so it works correct for interval subtraction cases
1293    /// MySQL supports the DAY_MICROSECOND unit type (format is DAYS HOURS:MINUTES:SECONDS.MICROSECONDS), but it is not supported by sqlparser
1294    /// so we calculate the best single interval to represent the provided duration
1295    fn interval_to_mysql_expr(
1296        &self,
1297        months: i32,
1298        days: i32,
1299        microseconds: i64,
1300    ) -> Result<ast::Expr> {
1301        // MONTH only
1302        if months != 0 && days == 0 && microseconds == 0 {
1303            let interval = Interval {
1304                value: Box::new(ast::Expr::Value(ast::Value::Number(
1305                    months.to_string(),
1306                    false,
1307                ))),
1308                leading_field: Some(ast::DateTimeField::Month),
1309                leading_precision: None,
1310                last_field: None,
1311                fractional_seconds_precision: None,
1312            };
1313            return Ok(ast::Expr::Interval(interval));
1314        } else if months != 0 {
1315            return not_impl_err!("Unsupported Interval scalar with both Month and DayTime for IntervalStyle::MySQL");
1316        }
1317
1318        // DAY only
1319        if microseconds == 0 {
1320            let interval = Interval {
1321                value: Box::new(ast::Expr::Value(ast::Value::Number(
1322                    days.to_string(),
1323                    false,
1324                ))),
1325                leading_field: Some(ast::DateTimeField::Day),
1326                leading_precision: None,
1327                last_field: None,
1328                fractional_seconds_precision: None,
1329            };
1330            return Ok(ast::Expr::Interval(interval));
1331        }
1332
1333        // Calculate the best single interval to represent the provided days and microseconds
1334
1335        let microseconds = microseconds + (days as i64 * 24 * 60 * 60 * 1_000_000);
1336
1337        if microseconds % 1_000_000 != 0 {
1338            let interval = Interval {
1339                value: Box::new(ast::Expr::Value(ast::Value::Number(
1340                    microseconds.to_string(),
1341                    false,
1342                ))),
1343                leading_field: Some(ast::DateTimeField::Microsecond),
1344                leading_precision: None,
1345                last_field: None,
1346                fractional_seconds_precision: None,
1347            };
1348            return Ok(ast::Expr::Interval(interval));
1349        }
1350
1351        let secs = microseconds / 1_000_000;
1352
1353        if secs % 60 != 0 {
1354            let interval = Interval {
1355                value: Box::new(ast::Expr::Value(ast::Value::Number(
1356                    secs.to_string(),
1357                    false,
1358                ))),
1359                leading_field: Some(ast::DateTimeField::Second),
1360                leading_precision: None,
1361                last_field: None,
1362                fractional_seconds_precision: None,
1363            };
1364            return Ok(ast::Expr::Interval(interval));
1365        }
1366
1367        let mins = secs / 60;
1368
1369        if mins % 60 != 0 {
1370            let interval = Interval {
1371                value: Box::new(ast::Expr::Value(ast::Value::Number(
1372                    mins.to_string(),
1373                    false,
1374                ))),
1375                leading_field: Some(ast::DateTimeField::Minute),
1376                leading_precision: None,
1377                last_field: None,
1378                fractional_seconds_precision: None,
1379            };
1380            return Ok(ast::Expr::Interval(interval));
1381        }
1382
1383        let hours = mins / 60;
1384
1385        if hours % 24 != 0 {
1386            let interval = Interval {
1387                value: Box::new(ast::Expr::Value(ast::Value::Number(
1388                    hours.to_string(),
1389                    false,
1390                ))),
1391                leading_field: Some(ast::DateTimeField::Hour),
1392                leading_precision: None,
1393                last_field: None,
1394                fractional_seconds_precision: None,
1395            };
1396            return Ok(ast::Expr::Interval(interval));
1397        }
1398
1399        let days = hours / 24;
1400
1401        let interval = Interval {
1402            value: Box::new(ast::Expr::Value(ast::Value::Number(
1403                days.to_string(),
1404                false,
1405            ))),
1406            leading_field: Some(ast::DateTimeField::Day),
1407            leading_precision: None,
1408            last_field: None,
1409            fractional_seconds_precision: None,
1410        };
1411        Ok(ast::Expr::Interval(interval))
1412    }
1413
1414    fn interval_scalar_to_sql(&self, v: &ScalarValue) -> Result<ast::Expr> {
1415        match self.dialect.interval_style() {
1416            IntervalStyle::PostgresVerbose => {
1417                let wrap_array = v.to_array()?;
1418                let Some(result) = array_value_to_string(&wrap_array, 0).ok() else {
1419                    return internal_err!(
1420                        "Unable to convert interval scalar value to string"
1421                    );
1422                };
1423                let interval = Interval {
1424                    value: Box::new(ast::Expr::Value(SingleQuotedString(
1425                        result.to_uppercase(),
1426                    ))),
1427                    leading_field: None,
1428                    leading_precision: None,
1429                    last_field: None,
1430                    fractional_seconds_precision: None,
1431                };
1432                Ok(ast::Expr::Interval(interval))
1433            }
1434            // If the interval standard is SQLStandard, implement a simple unparse logic
1435            IntervalStyle::SQLStandard => match v {
1436                ScalarValue::IntervalYearMonth(Some(v)) => {
1437                    let interval = Interval {
1438                        value: Box::new(ast::Expr::Value(SingleQuotedString(
1439                            v.to_string(),
1440                        ))),
1441                        leading_field: Some(ast::DateTimeField::Month),
1442                        leading_precision: None,
1443                        last_field: None,
1444                        fractional_seconds_precision: None,
1445                    };
1446                    Ok(ast::Expr::Interval(interval))
1447                }
1448                ScalarValue::IntervalDayTime(Some(v)) => {
1449                    let days = v.days;
1450                    let secs = v.milliseconds / 1_000;
1451                    let mins = secs / 60;
1452                    let hours = mins / 60;
1453
1454                    let secs = secs - (mins * 60);
1455                    let mins = mins - (hours * 60);
1456
1457                    let millis = v.milliseconds % 1_000;
1458                    let interval = Interval {
1459                        value: Box::new(ast::Expr::Value(SingleQuotedString(format!(
1460                            "{days} {hours}:{mins}:{secs}.{millis:3}"
1461                        )))),
1462                        leading_field: Some(ast::DateTimeField::Day),
1463                        leading_precision: None,
1464                        last_field: Some(ast::DateTimeField::Second),
1465                        fractional_seconds_precision: None,
1466                    };
1467                    Ok(ast::Expr::Interval(interval))
1468                }
1469                ScalarValue::IntervalMonthDayNano(Some(v)) => {
1470                    if v.months >= 0 && v.days == 0 && v.nanoseconds == 0 {
1471                        let interval = Interval {
1472                            value: Box::new(ast::Expr::Value(SingleQuotedString(
1473                                v.months.to_string(),
1474                            ))),
1475                            leading_field: Some(ast::DateTimeField::Month),
1476                            leading_precision: None,
1477                            last_field: None,
1478                            fractional_seconds_precision: None,
1479                        };
1480                        Ok(ast::Expr::Interval(interval))
1481                    } else if v.months == 0 && v.nanoseconds % 1_000_000 == 0 {
1482                        let days = v.days;
1483                        let secs = v.nanoseconds / 1_000_000_000;
1484                        let mins = secs / 60;
1485                        let hours = mins / 60;
1486
1487                        let secs = secs - (mins * 60);
1488                        let mins = mins - (hours * 60);
1489
1490                        let millis = (v.nanoseconds % 1_000_000_000) / 1_000_000;
1491
1492                        let interval = Interval {
1493                            value: Box::new(ast::Expr::Value(SingleQuotedString(
1494                                format!("{days} {hours}:{mins}:{secs}.{millis:03}"),
1495                            ))),
1496                            leading_field: Some(ast::DateTimeField::Day),
1497                            leading_precision: None,
1498                            last_field: Some(ast::DateTimeField::Second),
1499                            fractional_seconds_precision: None,
1500                        };
1501                        Ok(ast::Expr::Interval(interval))
1502                    } else {
1503                        not_impl_err!("Unsupported IntervalMonthDayNano scalar with both Month and DayTime for IntervalStyle::SQLStandard")
1504                    }
1505                }
1506                _ => not_impl_err!(
1507                    "Unsupported ScalarValue for Interval conversion: {v:?}"
1508                ),
1509            },
1510            IntervalStyle::MySQL => match v {
1511                ScalarValue::IntervalYearMonth(Some(v)) => {
1512                    self.interval_to_mysql_expr(*v, 0, 0)
1513                }
1514                ScalarValue::IntervalDayTime(Some(v)) => {
1515                    self.interval_to_mysql_expr(0, v.days, v.milliseconds as i64 * 1_000)
1516                }
1517                ScalarValue::IntervalMonthDayNano(Some(v)) => {
1518                    if v.nanoseconds % 1_000 != 0 {
1519                        return not_impl_err!(
1520                            "Unsupported IntervalMonthDayNano scalar with nanoseconds precision for IntervalStyle::MySQL"
1521                        );
1522                    }
1523                    self.interval_to_mysql_expr(v.months, v.days, v.nanoseconds / 1_000)
1524                }
1525                _ => not_impl_err!(
1526                    "Unsupported ScalarValue for Interval conversion: {v:?}"
1527                ),
1528            },
1529        }
1530    }
1531
1532    /// Converts an UNNEST operation to an AST expression by wrapping it as a function call,
1533    /// since there is no direct representation for UNNEST in the AST.
1534    fn unnest_to_sql(&self, unnest: &Unnest) -> Result<ast::Expr> {
1535        let args = self.function_args_to_sql(std::slice::from_ref(&unnest.expr))?;
1536
1537        Ok(ast::Expr::Function(Function {
1538            name: ObjectName(vec![Ident {
1539                value: "UNNEST".to_string(),
1540                quote_style: None,
1541                span: Span::empty(),
1542            }]),
1543            args: ast::FunctionArguments::List(ast::FunctionArgumentList {
1544                duplicate_treatment: None,
1545                args,
1546                clauses: vec![],
1547            }),
1548            filter: None,
1549            null_treatment: None,
1550            over: None,
1551            within_group: vec![],
1552            parameters: ast::FunctionArguments::None,
1553            uses_odbc_syntax: false,
1554        }))
1555    }
1556
1557    fn arrow_dtype_to_ast_dtype(&self, data_type: &DataType) -> Result<ast::DataType> {
1558        match data_type {
1559            DataType::Null => {
1560                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1561            }
1562            DataType::Boolean => Ok(ast::DataType::Bool),
1563            DataType::Int8 => Ok(ast::DataType::TinyInt(None)),
1564            DataType::Int16 => Ok(ast::DataType::SmallInt(None)),
1565            DataType::Int32 => Ok(self.dialect.int32_cast_dtype()),
1566            DataType::Int64 => Ok(self.dialect.int64_cast_dtype()),
1567            DataType::UInt8 => Ok(ast::DataType::UnsignedTinyInt(None)),
1568            DataType::UInt16 => Ok(ast::DataType::UnsignedSmallInt(None)),
1569            DataType::UInt32 => Ok(ast::DataType::UnsignedInteger(None)),
1570            DataType::UInt64 => Ok(ast::DataType::UnsignedBigInt(None)),
1571            DataType::Float16 => {
1572                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1573            }
1574            DataType::Float32 => Ok(ast::DataType::Float(None)),
1575            DataType::Float64 => Ok(self.dialect.float64_ast_dtype()),
1576            DataType::Timestamp(time_unit, tz) => {
1577                Ok(self.dialect.timestamp_cast_dtype(time_unit, tz))
1578            }
1579            DataType::Date32 => Ok(self.dialect.date32_cast_dtype()),
1580            DataType::Date64 => Ok(self.ast_type_for_date64_in_cast()),
1581            DataType::Time32(_) => {
1582                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1583            }
1584            DataType::Time64(_) => {
1585                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1586            }
1587            DataType::Duration(_) => {
1588                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1589            }
1590            DataType::Interval(_) => Ok(ast::DataType::Interval),
1591            DataType::Binary => {
1592                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1593            }
1594            DataType::FixedSizeBinary(_) => {
1595                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1596            }
1597            DataType::LargeBinary => {
1598                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1599            }
1600            DataType::BinaryView => {
1601                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1602            }
1603            DataType::Utf8 => Ok(self.dialect.utf8_cast_dtype()),
1604            DataType::LargeUtf8 => Ok(self.dialect.large_utf8_cast_dtype()),
1605            DataType::Utf8View => Ok(self.dialect.utf8_cast_dtype()),
1606            DataType::List(_) => {
1607                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1608            }
1609            DataType::FixedSizeList(_, _) => {
1610                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1611            }
1612            DataType::LargeList(_) => {
1613                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1614            }
1615            DataType::ListView(_) => {
1616                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1617            }
1618            DataType::LargeListView(_) => {
1619                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1620            }
1621            DataType::Struct(_) => {
1622                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1623            }
1624            DataType::Union(_, _) => {
1625                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1626            }
1627            DataType::Dictionary(_, val) => self.arrow_dtype_to_ast_dtype(val),
1628            DataType::Decimal128(precision, scale)
1629            | DataType::Decimal256(precision, scale) => {
1630                let mut new_precision = *precision as u64;
1631                let mut new_scale = *scale as u64;
1632                if *scale < 0 {
1633                    new_precision = (*precision as i16 - *scale as i16) as u64;
1634                    new_scale = 0
1635                }
1636
1637                Ok(ast::DataType::Decimal(
1638                    ast::ExactNumberInfo::PrecisionAndScale(new_precision, new_scale),
1639                ))
1640            }
1641            DataType::Map(_, _) => {
1642                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1643            }
1644            DataType::RunEndEncoded(_, _) => {
1645                not_impl_err!("Unsupported DataType: conversion: {data_type:?}")
1646            }
1647        }
1648    }
1649}
1650
1651#[cfg(test)]
1652mod tests {
1653    use std::ops::{Add, Sub};
1654    use std::{any::Any, sync::Arc, vec};
1655
1656    use arrow::array::{LargeListArray, ListArray};
1657    use arrow::datatypes::{DataType::Int8, Field, Int32Type, Schema, TimeUnit};
1658    use ast::ObjectName;
1659    use datafusion_common::{Spans, TableReference};
1660    use datafusion_expr::expr::WildcardOptions;
1661    use datafusion_expr::{
1662        case, cast, col, cube, exists, grouping_set, interval_datetime_lit,
1663        interval_year_month_lit, lit, not, not_exists, out_ref_col, placeholder, rollup,
1664        table_scan, try_cast, when, wildcard, ScalarUDF, ScalarUDFImpl, Signature,
1665        Volatility, WindowFrame, WindowFunctionDefinition,
1666    };
1667    use datafusion_expr::{interval_month_day_nano_lit, ExprFunctionExt};
1668    use datafusion_functions::expr_fn::{get_field, named_struct};
1669    use datafusion_functions_aggregate::count::count_udaf;
1670    use datafusion_functions_aggregate::expr_fn::sum;
1671    use datafusion_functions_nested::expr_fn::{array_element, make_array};
1672    use datafusion_functions_nested::map::map;
1673    use datafusion_functions_window::rank::rank_udwf;
1674    use datafusion_functions_window::row_number::row_number_udwf;
1675    use sqlparser::ast::ExactNumberInfo;
1676
1677    use crate::unparser::dialect::{
1678        CharacterLengthStyle, CustomDialect, CustomDialectBuilder, DateFieldExtractStyle,
1679        Dialect, DuckDBDialect, PostgreSqlDialect, ScalarFnToSqlHandler,
1680    };
1681
1682    use super::*;
1683
1684    /// Mocked UDF
1685    #[derive(Debug)]
1686    struct DummyUDF {
1687        signature: Signature,
1688    }
1689
1690    impl DummyUDF {
1691        fn new() -> Self {
1692            Self {
1693                signature: Signature::variadic_any(Volatility::Immutable),
1694            }
1695        }
1696    }
1697
1698    impl ScalarUDFImpl for DummyUDF {
1699        fn as_any(&self) -> &dyn Any {
1700            self
1701        }
1702
1703        fn name(&self) -> &str {
1704            "dummy_udf"
1705        }
1706
1707        fn signature(&self) -> &Signature {
1708            &self.signature
1709        }
1710
1711        fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
1712            Ok(DataType::Int32)
1713        }
1714    }
1715    // See sql::tests for E2E tests.
1716
1717    #[test]
1718    fn expr_to_sql_ok() -> Result<()> {
1719        let dummy_schema = Schema::new(vec![Field::new("a", DataType::Int32, false)]);
1720        #[expect(deprecated)]
1721        let dummy_logical_plan = table_scan(Some("t"), &dummy_schema, None)?
1722            .project(vec![Expr::Wildcard {
1723                qualifier: None,
1724                options: Box::new(WildcardOptions::default()),
1725            }])?
1726            .filter(col("a").eq(lit(1)))?
1727            .build()?;
1728
1729        let tests: Vec<(Expr, &str)> = vec![
1730            ((col("a") + col("b")).gt(lit(4)), r#"((a + b) > 4)"#),
1731            (
1732                Expr::Column(Column {
1733                    relation: Some(TableReference::partial("a", "b")),
1734                    name: "c".to_string(),
1735                    spans: Spans::new(),
1736                })
1737                .gt(lit(4)),
1738                r#"(b.c > 4)"#,
1739            ),
1740            (
1741                case(col("a"))
1742                    .when(lit(1), lit(true))
1743                    .when(lit(0), lit(false))
1744                    .otherwise(lit(ScalarValue::Null))?,
1745                r#"CASE a WHEN 1 THEN true WHEN 0 THEN false ELSE NULL END"#,
1746            ),
1747            (
1748                when(col("a").is_null(), lit(true)).otherwise(lit(false))?,
1749                r#"CASE WHEN a IS NULL THEN true ELSE false END"#,
1750            ),
1751            (
1752                when(col("a").is_not_null(), lit(true)).otherwise(lit(false))?,
1753                r#"CASE WHEN a IS NOT NULL THEN true ELSE false END"#,
1754            ),
1755            (
1756                Expr::Cast(Cast {
1757                    expr: Box::new(col("a")),
1758                    data_type: DataType::Date64,
1759                }),
1760                r#"CAST(a AS DATETIME)"#,
1761            ),
1762            (
1763                Expr::Cast(Cast {
1764                    expr: Box::new(col("a")),
1765                    data_type: DataType::Timestamp(
1766                        TimeUnit::Nanosecond,
1767                        Some("+08:00".into()),
1768                    ),
1769                }),
1770                r#"CAST(a AS TIMESTAMP WITH TIME ZONE)"#,
1771            ),
1772            (
1773                Expr::Cast(Cast {
1774                    expr: Box::new(col("a")),
1775                    data_type: DataType::Timestamp(TimeUnit::Millisecond, None),
1776                }),
1777                r#"CAST(a AS TIMESTAMP)"#,
1778            ),
1779            (
1780                Expr::Cast(Cast {
1781                    expr: Box::new(col("a")),
1782                    data_type: DataType::UInt32,
1783                }),
1784                r#"CAST(a AS INTEGER UNSIGNED)"#,
1785            ),
1786            (
1787                col("a").in_list(vec![lit(1), lit(2), lit(3)], false),
1788                r#"a IN (1, 2, 3)"#,
1789            ),
1790            (
1791                col("a").in_list(vec![lit(1), lit(2), lit(3)], true),
1792                r#"a NOT IN (1, 2, 3)"#,
1793            ),
1794            (
1795                ScalarUDF::new_from_impl(DummyUDF::new()).call(vec![col("a"), col("b")]),
1796                r#"dummy_udf(a, b)"#,
1797            ),
1798            (
1799                ScalarUDF::new_from_impl(DummyUDF::new())
1800                    .call(vec![col("a"), col("b")])
1801                    .is_null(),
1802                r#"dummy_udf(a, b) IS NULL"#,
1803            ),
1804            (
1805                ScalarUDF::new_from_impl(DummyUDF::new())
1806                    .call(vec![col("a"), col("b")])
1807                    .is_not_null(),
1808                r#"dummy_udf(a, b) IS NOT NULL"#,
1809            ),
1810            (
1811                Expr::Like(Like {
1812                    negated: true,
1813                    expr: Box::new(col("a")),
1814                    pattern: Box::new(lit("foo")),
1815                    escape_char: Some('o'),
1816                    case_insensitive: true,
1817                }),
1818                r#"a NOT LIKE 'foo' ESCAPE 'o'"#,
1819            ),
1820            (
1821                Expr::SimilarTo(Like {
1822                    negated: false,
1823                    expr: Box::new(col("a")),
1824                    pattern: Box::new(lit("foo")),
1825                    escape_char: Some('o'),
1826                    case_insensitive: true,
1827                }),
1828                r#"a LIKE 'foo' ESCAPE 'o'"#,
1829            ),
1830            (
1831                Expr::Literal(ScalarValue::Date64(Some(0))),
1832                r#"CAST('1970-01-01 00:00:00' AS DATETIME)"#,
1833            ),
1834            (
1835                Expr::Literal(ScalarValue::Date64(Some(10000))),
1836                r#"CAST('1970-01-01 00:00:10' AS DATETIME)"#,
1837            ),
1838            (
1839                Expr::Literal(ScalarValue::Date64(Some(-10000))),
1840                r#"CAST('1969-12-31 23:59:50' AS DATETIME)"#,
1841            ),
1842            (
1843                Expr::Literal(ScalarValue::Date32(Some(0))),
1844                r#"CAST('1970-01-01' AS DATE)"#,
1845            ),
1846            (
1847                Expr::Literal(ScalarValue::Date32(Some(10))),
1848                r#"CAST('1970-01-11' AS DATE)"#,
1849            ),
1850            (
1851                Expr::Literal(ScalarValue::Date32(Some(-1))),
1852                r#"CAST('1969-12-31' AS DATE)"#,
1853            ),
1854            (
1855                Expr::Literal(ScalarValue::TimestampSecond(Some(10001), None)),
1856                r#"CAST('1970-01-01 02:46:41' AS TIMESTAMP)"#,
1857            ),
1858            (
1859                Expr::Literal(ScalarValue::TimestampSecond(
1860                    Some(10001),
1861                    Some("+08:00".into()),
1862                )),
1863                r#"CAST('1970-01-01 10:46:41 +08:00' AS TIMESTAMP)"#,
1864            ),
1865            (
1866                Expr::Literal(ScalarValue::TimestampMillisecond(Some(10001), None)),
1867                r#"CAST('1970-01-01 00:00:10.001' AS TIMESTAMP)"#,
1868            ),
1869            (
1870                Expr::Literal(ScalarValue::TimestampMillisecond(
1871                    Some(10001),
1872                    Some("+08:00".into()),
1873                )),
1874                r#"CAST('1970-01-01 08:00:10.001 +08:00' AS TIMESTAMP)"#,
1875            ),
1876            (
1877                Expr::Literal(ScalarValue::TimestampMicrosecond(Some(10001), None)),
1878                r#"CAST('1970-01-01 00:00:00.010001' AS TIMESTAMP)"#,
1879            ),
1880            (
1881                Expr::Literal(ScalarValue::TimestampMicrosecond(
1882                    Some(10001),
1883                    Some("+08:00".into()),
1884                )),
1885                r#"CAST('1970-01-01 08:00:00.010001 +08:00' AS TIMESTAMP)"#,
1886            ),
1887            (
1888                Expr::Literal(ScalarValue::TimestampNanosecond(Some(10001), None)),
1889                r#"CAST('1970-01-01 00:00:00.000010001' AS TIMESTAMP)"#,
1890            ),
1891            (
1892                Expr::Literal(ScalarValue::TimestampNanosecond(
1893                    Some(10001),
1894                    Some("+08:00".into()),
1895                )),
1896                r#"CAST('1970-01-01 08:00:00.000010001 +08:00' AS TIMESTAMP)"#,
1897            ),
1898            (
1899                Expr::Literal(ScalarValue::Time32Second(Some(10001))),
1900                r#"CAST('02:46:41' AS TIME)"#,
1901            ),
1902            (
1903                Expr::Literal(ScalarValue::Time32Millisecond(Some(10001))),
1904                r#"CAST('00:00:10.001' AS TIME)"#,
1905            ),
1906            (
1907                Expr::Literal(ScalarValue::Time64Microsecond(Some(10001))),
1908                r#"CAST('00:00:00.010001' AS TIME)"#,
1909            ),
1910            (
1911                Expr::Literal(ScalarValue::Time64Nanosecond(Some(10001))),
1912                r#"CAST('00:00:00.000010001' AS TIME)"#,
1913            ),
1914            (sum(col("a")), r#"sum(a)"#),
1915            (
1916                count_udaf()
1917                    .call(vec![wildcard()])
1918                    .distinct()
1919                    .build()
1920                    .unwrap(),
1921                "count(DISTINCT *)",
1922            ),
1923            (
1924                count_udaf()
1925                    .call(vec![wildcard()])
1926                    .filter(lit(true))
1927                    .build()
1928                    .unwrap(),
1929                "count(*) FILTER (WHERE true)",
1930            ),
1931            (
1932                Expr::WindowFunction(WindowFunction {
1933                    fun: WindowFunctionDefinition::WindowUDF(row_number_udwf()),
1934                    params: WindowFunctionParams {
1935                        args: vec![col("col")],
1936                        partition_by: vec![],
1937                        order_by: vec![],
1938                        window_frame: WindowFrame::new(None),
1939                        null_treatment: None,
1940                    },
1941                }),
1942                r#"row_number(col) OVER (ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)"#,
1943            ),
1944            (
1945                Expr::WindowFunction(WindowFunction {
1946                    fun: WindowFunctionDefinition::AggregateUDF(count_udaf()),
1947                    params: WindowFunctionParams {
1948                        args: vec![wildcard()],
1949                        partition_by: vec![],
1950                        order_by: vec![Sort::new(col("a"), false, true)],
1951                        window_frame: WindowFrame::new_bounds(
1952                            datafusion_expr::WindowFrameUnits::Range,
1953                            datafusion_expr::WindowFrameBound::Preceding(
1954                                ScalarValue::UInt32(Some(6)),
1955                            ),
1956                            datafusion_expr::WindowFrameBound::Following(
1957                                ScalarValue::UInt32(Some(2)),
1958                            ),
1959                        ),
1960                        null_treatment: None,
1961                    },
1962                }),
1963                r#"count(*) OVER (ORDER BY a DESC NULLS FIRST RANGE BETWEEN 6 PRECEDING AND 2 FOLLOWING)"#,
1964            ),
1965            (col("a").is_not_null(), r#"a IS NOT NULL"#),
1966            (col("a").is_null(), r#"a IS NULL"#),
1967            (
1968                (col("a") + col("b")).gt(lit(4)).is_true(),
1969                r#"((a + b) > 4) IS TRUE"#,
1970            ),
1971            (
1972                (col("a") + col("b")).gt(lit(4)).is_not_true(),
1973                r#"((a + b) > 4) IS NOT TRUE"#,
1974            ),
1975            (
1976                (col("a") + col("b")).gt(lit(4)).is_false(),
1977                r#"((a + b) > 4) IS FALSE"#,
1978            ),
1979            (
1980                (col("a") + col("b")).gt(lit(4)).is_not_false(),
1981                r#"((a + b) > 4) IS NOT FALSE"#,
1982            ),
1983            (
1984                (col("a") + col("b")).gt(lit(4)).is_unknown(),
1985                r#"((a + b) > 4) IS UNKNOWN"#,
1986            ),
1987            (
1988                (col("a") + col("b")).gt(lit(4)).is_not_unknown(),
1989                r#"((a + b) > 4) IS NOT UNKNOWN"#,
1990            ),
1991            (not(col("a")), r#"NOT a"#),
1992            (
1993                Expr::between(col("a"), lit(1), lit(7)),
1994                r#"(a BETWEEN 1 AND 7)"#,
1995            ),
1996            (Expr::Negative(Box::new(col("a"))), r#"-a"#),
1997            (
1998                exists(Arc::new(dummy_logical_plan.clone())),
1999                r#"EXISTS (SELECT * FROM t WHERE (t.a = 1))"#,
2000            ),
2001            (
2002                not_exists(Arc::new(dummy_logical_plan)),
2003                r#"NOT EXISTS (SELECT * FROM t WHERE (t.a = 1))"#,
2004            ),
2005            (
2006                try_cast(col("a"), DataType::Date64),
2007                r#"TRY_CAST(a AS DATETIME)"#,
2008            ),
2009            (
2010                try_cast(col("a"), DataType::UInt32),
2011                r#"TRY_CAST(a AS INTEGER UNSIGNED)"#,
2012            ),
2013            (
2014                Expr::ScalarVariable(Int8, vec![String::from("@a")]),
2015                r#"@a"#,
2016            ),
2017            (
2018                Expr::ScalarVariable(
2019                    Int8,
2020                    vec![String::from("@root"), String::from("foo")],
2021                ),
2022                r#"@root.foo"#,
2023            ),
2024            (col("x").eq(placeholder("$1")), r#"(x = $1)"#),
2025            (
2026                out_ref_col(DataType::Int32, "t.a").gt(lit(1)),
2027                r#"(t.a > 1)"#,
2028            ),
2029            (
2030                grouping_set(vec![vec![col("a"), col("b")], vec![col("a")]]),
2031                r#"GROUPING SETS ((a, b), (a))"#,
2032            ),
2033            (cube(vec![col("a"), col("b")]), r#"CUBE (a, b)"#),
2034            (rollup(vec![col("a"), col("b")]), r#"ROLLUP (a, b)"#),
2035            (col("table").eq(lit(1)), r#"("table" = 1)"#),
2036            (
2037                col("123_need_quoted").eq(lit(1)),
2038                r#"("123_need_quoted" = 1)"#,
2039            ),
2040            (col("need-quoted").eq(lit(1)), r#"("need-quoted" = 1)"#),
2041            (col("need quoted").eq(lit(1)), r#"("need quoted" = 1)"#),
2042            // See test_interval_scalar_to_expr for interval literals
2043            (
2044                (col("a") + col("b")).gt(Expr::Literal(ScalarValue::Decimal128(
2045                    Some(100123),
2046                    28,
2047                    3,
2048                ))),
2049                r#"((a + b) > 100.123)"#,
2050            ),
2051            (
2052                (col("a") + col("b")).gt(Expr::Literal(ScalarValue::Decimal256(
2053                    Some(100123.into()),
2054                    28,
2055                    3,
2056                ))),
2057                r#"((a + b) > 100.123)"#,
2058            ),
2059            (
2060                Expr::Cast(Cast {
2061                    expr: Box::new(col("a")),
2062                    data_type: DataType::Decimal128(10, -2),
2063                }),
2064                r#"CAST(a AS DECIMAL(12,0))"#,
2065            ),
2066            (
2067                Expr::Unnest(Unnest {
2068                    expr: Box::new(Expr::Column(Column {
2069                        relation: Some(TableReference::partial("schema", "table")),
2070                        name: "array_col".to_string(),
2071                        spans: Spans::new(),
2072                    })),
2073                }),
2074                r#"UNNEST("table".array_col)"#,
2075            ),
2076            (make_array(vec![lit(1), lit(2), lit(3)]), "[1, 2, 3]"),
2077            (array_element(col("array_col"), lit(1)), "array_col[1]"),
2078            (
2079                array_element(make_array(vec![lit(1), lit(2), lit(3)]), lit(1)),
2080                "[1, 2, 3][1]",
2081            ),
2082            (
2083                named_struct(vec![lit("a"), lit("1"), lit("b"), lit(2)]),
2084                "{a: '1', b: 2}",
2085            ),
2086            (get_field(col("a.b"), "c"), "a.b.c"),
2087            (
2088                map(vec![lit("a"), lit("b")], vec![lit(1), lit(2)]),
2089                "MAP {'a': 1, 'b': 2}",
2090            ),
2091            (
2092                Expr::Literal(ScalarValue::Dictionary(
2093                    Box::new(DataType::Int32),
2094                    Box::new(ScalarValue::Utf8(Some("foo".into()))),
2095                )),
2096                "'foo'",
2097            ),
2098            (
2099                Expr::Literal(ScalarValue::List(Arc::new(
2100                    ListArray::from_iter_primitive::<Int32Type, _, _>(vec![Some(vec![
2101                        Some(1),
2102                        Some(2),
2103                        Some(3),
2104                    ])]),
2105                ))),
2106                "[1, 2, 3]",
2107            ),
2108            (
2109                Expr::Literal(ScalarValue::LargeList(Arc::new(
2110                    LargeListArray::from_iter_primitive::<Int32Type, _, _>(vec![Some(
2111                        vec![Some(1), Some(2), Some(3)],
2112                    )]),
2113                ))),
2114                "[1, 2, 3]",
2115            ),
2116        ];
2117
2118        for (expr, expected) in tests {
2119            let ast = expr_to_sql(&expr)?;
2120
2121            let actual = format!("{}", ast);
2122
2123            assert_eq!(actual, expected);
2124        }
2125
2126        Ok(())
2127    }
2128
2129    #[test]
2130    fn custom_dialect_with_identifier_quote_style() -> Result<()> {
2131        let dialect = CustomDialectBuilder::new()
2132            .with_identifier_quote_style('\'')
2133            .build();
2134        let unparser = Unparser::new(&dialect);
2135
2136        let expr = col("a").gt(lit(4));
2137        let ast = unparser.expr_to_sql(&expr)?;
2138
2139        let actual = format!("{}", ast);
2140
2141        let expected = r#"('a' > 4)"#;
2142        assert_eq!(actual, expected);
2143
2144        Ok(())
2145    }
2146
2147    #[test]
2148    fn custom_dialect_without_identifier_quote_style() -> Result<()> {
2149        let dialect = CustomDialect::default();
2150        let unparser = Unparser::new(&dialect);
2151
2152        let expr = col("a").gt(lit(4));
2153        let ast = unparser.expr_to_sql(&expr)?;
2154
2155        let actual = format!("{}", ast);
2156
2157        let expected = r#"(a > 4)"#;
2158        assert_eq!(actual, expected);
2159
2160        Ok(())
2161    }
2162
2163    #[test]
2164    fn custom_dialect_use_timestamp_for_date64() -> Result<()> {
2165        for (use_timestamp_for_date64, identifier) in
2166            [(false, "DATETIME"), (true, "TIMESTAMP")]
2167        {
2168            let dialect = CustomDialectBuilder::new()
2169                .with_use_timestamp_for_date64(use_timestamp_for_date64)
2170                .build();
2171            let unparser = Unparser::new(&dialect);
2172
2173            let expr = Expr::Cast(Cast {
2174                expr: Box::new(col("a")),
2175                data_type: DataType::Date64,
2176            });
2177            let ast = unparser.expr_to_sql(&expr)?;
2178
2179            let actual = format!("{}", ast);
2180
2181            let expected = format!(r#"CAST(a AS {identifier})"#);
2182            assert_eq!(actual, expected);
2183        }
2184        Ok(())
2185    }
2186
2187    #[test]
2188    fn custom_dialect_float64_ast_dtype() -> Result<()> {
2189        for (float64_ast_dtype, identifier) in [
2190            (ast::DataType::Double(ExactNumberInfo::None), "DOUBLE"),
2191            (ast::DataType::DoublePrecision, "DOUBLE PRECISION"),
2192        ] {
2193            let dialect = CustomDialectBuilder::new()
2194                .with_float64_ast_dtype(float64_ast_dtype)
2195                .build();
2196            let unparser = Unparser::new(&dialect);
2197
2198            let expr = Expr::Cast(Cast {
2199                expr: Box::new(col("a")),
2200                data_type: DataType::Float64,
2201            });
2202            let ast = unparser.expr_to_sql(&expr)?;
2203
2204            let actual = format!("{}", ast);
2205
2206            let expected = format!(r#"CAST(a AS {identifier})"#);
2207            assert_eq!(actual, expected);
2208        }
2209        Ok(())
2210    }
2211
2212    #[test]
2213    fn customer_dialect_support_nulls_first_in_ort() -> Result<()> {
2214        let tests: Vec<(Sort, &str, bool)> = vec![
2215            (col("a").sort(true, true), r#"a ASC NULLS FIRST"#, true),
2216            (col("a").sort(true, true), r#"a ASC"#, false),
2217        ];
2218
2219        for (expr, expected, supports_nulls_first_in_sort) in tests {
2220            let dialect = CustomDialectBuilder::new()
2221                .with_supports_nulls_first_in_sort(supports_nulls_first_in_sort)
2222                .build();
2223            let unparser = Unparser::new(&dialect);
2224            let ast = unparser.sort_to_sql(&expr)?;
2225
2226            let actual = format!("{}", ast);
2227
2228            assert_eq!(actual, expected);
2229        }
2230
2231        Ok(())
2232    }
2233
2234    #[test]
2235    fn test_character_length_scalar_to_expr() {
2236        let tests = [
2237            (CharacterLengthStyle::Length, "length(x)"),
2238            (CharacterLengthStyle::CharacterLength, "character_length(x)"),
2239        ];
2240
2241        for (style, expected) in tests {
2242            let dialect = CustomDialectBuilder::new()
2243                .with_character_length_style(style)
2244                .build();
2245            let unparser = Unparser::new(&dialect);
2246
2247            let expr = ScalarUDF::new_from_impl(
2248                datafusion_functions::unicode::character_length::CharacterLengthFunc::new(
2249                ),
2250            )
2251            .call(vec![col("x")]);
2252
2253            let ast = unparser.expr_to_sql(&expr).expect("to be unparsed");
2254
2255            let actual = format!("{ast}");
2256
2257            assert_eq!(actual, expected);
2258        }
2259    }
2260
2261    #[test]
2262    fn test_interval_scalar_to_expr() {
2263        let tests = [
2264            (
2265                interval_month_day_nano_lit("1 MONTH"),
2266                IntervalStyle::SQLStandard,
2267                "INTERVAL '1' MONTH",
2268            ),
2269            (
2270                interval_month_day_nano_lit("1.5 DAY"),
2271                IntervalStyle::SQLStandard,
2272                "INTERVAL '1 12:0:0.000' DAY TO SECOND",
2273            ),
2274            (
2275                interval_month_day_nano_lit("-1.5 DAY"),
2276                IntervalStyle::SQLStandard,
2277                "INTERVAL '-1 -12:0:0.000' DAY TO SECOND",
2278            ),
2279            (
2280                interval_month_day_nano_lit("1.51234 DAY"),
2281                IntervalStyle::SQLStandard,
2282                "INTERVAL '1 12:17:46.176' DAY TO SECOND",
2283            ),
2284            (
2285                interval_datetime_lit("1.51234 DAY"),
2286                IntervalStyle::SQLStandard,
2287                "INTERVAL '1 12:17:46.176' DAY TO SECOND",
2288            ),
2289            (
2290                interval_year_month_lit("1 YEAR"),
2291                IntervalStyle::SQLStandard,
2292                "INTERVAL '12' MONTH",
2293            ),
2294            (
2295                interval_month_day_nano_lit(
2296                    "1 YEAR 1 MONTH 1 DAY 3 HOUR 10 MINUTE 20 SECOND",
2297                ),
2298                IntervalStyle::PostgresVerbose,
2299                r#"INTERVAL '13 MONS 1 DAYS 3 HOURS 10 MINS 20.000000000 SECS'"#,
2300            ),
2301            (
2302                interval_month_day_nano_lit("1.5 MONTH"),
2303                IntervalStyle::PostgresVerbose,
2304                r#"INTERVAL '1 MONS 15 DAYS'"#,
2305            ),
2306            (
2307                interval_month_day_nano_lit("-3 MONTH"),
2308                IntervalStyle::PostgresVerbose,
2309                r#"INTERVAL '-3 MONS'"#,
2310            ),
2311            (
2312                interval_month_day_nano_lit("1 MONTH")
2313                    .add(interval_month_day_nano_lit("1 DAY")),
2314                IntervalStyle::PostgresVerbose,
2315                r#"(INTERVAL '1 MONS' + INTERVAL '1 DAYS')"#,
2316            ),
2317            (
2318                interval_month_day_nano_lit("1 MONTH")
2319                    .sub(interval_month_day_nano_lit("1 DAY")),
2320                IntervalStyle::PostgresVerbose,
2321                r#"(INTERVAL '1 MONS' - INTERVAL '1 DAYS')"#,
2322            ),
2323            (
2324                interval_datetime_lit("10 DAY 1 HOUR 10 MINUTE 20 SECOND"),
2325                IntervalStyle::PostgresVerbose,
2326                r#"INTERVAL '10 DAYS 1 HOURS 10 MINS 20.000 SECS'"#,
2327            ),
2328            (
2329                interval_datetime_lit("10 DAY 1.5 HOUR 10 MINUTE 20 SECOND"),
2330                IntervalStyle::PostgresVerbose,
2331                r#"INTERVAL '10 DAYS 1 HOURS 40 MINS 20.000 SECS'"#,
2332            ),
2333            (
2334                interval_year_month_lit("1 YEAR 1 MONTH"),
2335                IntervalStyle::PostgresVerbose,
2336                r#"INTERVAL '1 YEARS 1 MONS'"#,
2337            ),
2338            (
2339                interval_year_month_lit("1.5 YEAR 1 MONTH"),
2340                IntervalStyle::PostgresVerbose,
2341                r#"INTERVAL '1 YEARS 7 MONS'"#,
2342            ),
2343            (
2344                interval_year_month_lit("1 YEAR 1 MONTH"),
2345                IntervalStyle::MySQL,
2346                r#"INTERVAL 13 MONTH"#,
2347            ),
2348            (
2349                interval_month_day_nano_lit("1 YEAR -1 MONTH"),
2350                IntervalStyle::MySQL,
2351                r#"INTERVAL 11 MONTH"#,
2352            ),
2353            (
2354                interval_month_day_nano_lit("15 DAY"),
2355                IntervalStyle::MySQL,
2356                r#"INTERVAL 15 DAY"#,
2357            ),
2358            (
2359                interval_month_day_nano_lit("-40 HOURS"),
2360                IntervalStyle::MySQL,
2361                r#"INTERVAL -40 HOUR"#,
2362            ),
2363            (
2364                interval_datetime_lit("-1.5 DAY 1 HOUR"),
2365                IntervalStyle::MySQL,
2366                "INTERVAL -35 HOUR",
2367            ),
2368            (
2369                interval_datetime_lit("1000000 DAY 1.5 HOUR 10 MINUTE 20 SECOND"),
2370                IntervalStyle::MySQL,
2371                r#"INTERVAL 86400006020 SECOND"#,
2372            ),
2373            (
2374                interval_year_month_lit("0 DAY 0 HOUR"),
2375                IntervalStyle::MySQL,
2376                r#"INTERVAL 0 DAY"#,
2377            ),
2378            (
2379                interval_month_day_nano_lit("-1296000000 SECOND"),
2380                IntervalStyle::MySQL,
2381                r#"INTERVAL -15000 DAY"#,
2382            ),
2383        ];
2384
2385        for (value, style, expected) in tests {
2386            let dialect = CustomDialectBuilder::new()
2387                .with_interval_style(style)
2388                .build();
2389            let unparser = Unparser::new(&dialect);
2390
2391            let ast = unparser.expr_to_sql(&value).expect("to be unparsed");
2392
2393            let actual = format!("{ast}");
2394
2395            assert_eq!(actual, expected);
2396        }
2397    }
2398
2399    #[test]
2400    fn test_float_scalar_to_expr() {
2401        let tests = [
2402            (Expr::Literal(ScalarValue::Float64(Some(3f64))), "3.0"),
2403            (Expr::Literal(ScalarValue::Float64(Some(3.1f64))), "3.1"),
2404            (Expr::Literal(ScalarValue::Float32(Some(-2f32))), "-2.0"),
2405            (
2406                Expr::Literal(ScalarValue::Float32(Some(-2.989f32))),
2407                "-2.989",
2408            ),
2409        ];
2410        for (value, expected) in tests {
2411            let dialect = CustomDialectBuilder::new().build();
2412            let unparser = Unparser::new(&dialect);
2413
2414            let ast = unparser.expr_to_sql(&value).expect("to be unparsed");
2415            let actual = format!("{ast}");
2416
2417            assert_eq!(actual, expected);
2418        }
2419    }
2420
2421    #[test]
2422    fn test_cast_value_to_binary_expr() {
2423        let tests = [
2424            (
2425                Expr::Cast(Cast {
2426                    expr: Box::new(Expr::Literal(ScalarValue::Utf8(Some(
2427                        "blah".to_string(),
2428                    )))),
2429                    data_type: DataType::Binary,
2430                }),
2431                "'blah'",
2432            ),
2433            (
2434                Expr::Cast(Cast {
2435                    expr: Box::new(Expr::Literal(ScalarValue::Utf8(Some(
2436                        "blah".to_string(),
2437                    )))),
2438                    data_type: DataType::BinaryView,
2439                }),
2440                "'blah'",
2441            ),
2442        ];
2443        for (value, expected) in tests {
2444            let dialect = CustomDialectBuilder::new().build();
2445            let unparser = Unparser::new(&dialect);
2446
2447            let ast = unparser.expr_to_sql(&value).expect("to be unparsed");
2448            let actual = format!("{ast}");
2449
2450            assert_eq!(actual, expected);
2451        }
2452    }
2453
2454    #[test]
2455    fn custom_dialect_use_char_for_utf8_cast() -> Result<()> {
2456        let default_dialect = CustomDialectBuilder::default().build();
2457        let mysql_custom_dialect = CustomDialectBuilder::new()
2458            .with_utf8_cast_dtype(ast::DataType::Char(None))
2459            .with_large_utf8_cast_dtype(ast::DataType::Char(None))
2460            .build();
2461
2462        for (dialect, data_type, identifier) in [
2463            (&default_dialect, DataType::Utf8, "VARCHAR"),
2464            (&default_dialect, DataType::LargeUtf8, "TEXT"),
2465            (&mysql_custom_dialect, DataType::Utf8, "CHAR"),
2466            (&mysql_custom_dialect, DataType::LargeUtf8, "CHAR"),
2467        ] {
2468            let unparser = Unparser::new(dialect);
2469
2470            let expr = Expr::Cast(Cast {
2471                expr: Box::new(col("a")),
2472                data_type,
2473            });
2474            let ast = unparser.expr_to_sql(&expr)?;
2475
2476            let actual = format!("{}", ast);
2477            let expected = format!(r#"CAST(a AS {identifier})"#);
2478
2479            assert_eq!(actual, expected);
2480        }
2481        Ok(())
2482    }
2483
2484    #[test]
2485    fn custom_dialect_with_date_field_extract_style() -> Result<()> {
2486        for (extract_style, unit, expected) in [
2487            (
2488                DateFieldExtractStyle::DatePart,
2489                "YEAR",
2490                "date_part('YEAR', x)",
2491            ),
2492            (
2493                DateFieldExtractStyle::Extract,
2494                "YEAR",
2495                "EXTRACT(YEAR FROM x)",
2496            ),
2497            (DateFieldExtractStyle::Strftime, "YEAR", "strftime('%Y', x)"),
2498            (
2499                DateFieldExtractStyle::DatePart,
2500                "MONTH",
2501                "date_part('MONTH', x)",
2502            ),
2503            (
2504                DateFieldExtractStyle::Extract,
2505                "MONTH",
2506                "EXTRACT(MONTH FROM x)",
2507            ),
2508            (
2509                DateFieldExtractStyle::Strftime,
2510                "MONTH",
2511                "strftime('%m', x)",
2512            ),
2513            (
2514                DateFieldExtractStyle::DatePart,
2515                "DAY",
2516                "date_part('DAY', x)",
2517            ),
2518            (DateFieldExtractStyle::Strftime, "DAY", "strftime('%d', x)"),
2519            (DateFieldExtractStyle::Extract, "DAY", "EXTRACT(DAY FROM x)"),
2520        ] {
2521            let dialect = CustomDialectBuilder::new()
2522                .with_date_field_extract_style(extract_style)
2523                .build();
2524
2525            let unparser = Unparser::new(&dialect);
2526            let expr = ScalarUDF::new_from_impl(
2527                datafusion_functions::datetime::date_part::DatePartFunc::new(),
2528            )
2529            .call(vec![Expr::Literal(ScalarValue::new_utf8(unit)), col("x")]);
2530
2531            let ast = unparser.expr_to_sql(&expr)?;
2532            let actual = format!("{}", ast);
2533
2534            assert_eq!(actual, expected);
2535        }
2536        Ok(())
2537    }
2538
2539    #[test]
2540    fn custom_dialect_with_int64_cast_dtype() -> Result<()> {
2541        let default_dialect = CustomDialectBuilder::new().build();
2542        let mysql_dialect = CustomDialectBuilder::new()
2543            .with_int64_cast_dtype(ast::DataType::Custom(
2544                ObjectName(vec![Ident::new("SIGNED")]),
2545                vec![],
2546            ))
2547            .build();
2548
2549        for (dialect, identifier) in
2550            [(default_dialect, "BIGINT"), (mysql_dialect, "SIGNED")]
2551        {
2552            let unparser = Unparser::new(&dialect);
2553            let expr = Expr::Cast(Cast {
2554                expr: Box::new(col("a")),
2555                data_type: DataType::Int64,
2556            });
2557            let ast = unparser.expr_to_sql(&expr)?;
2558
2559            let actual = format!("{}", ast);
2560            let expected = format!(r#"CAST(a AS {identifier})"#);
2561
2562            assert_eq!(actual, expected);
2563        }
2564        Ok(())
2565    }
2566
2567    #[test]
2568    fn custom_dialect_with_int32_cast_dtype() -> Result<()> {
2569        let default_dialect = CustomDialectBuilder::new().build();
2570        let mysql_dialect = CustomDialectBuilder::new()
2571            .with_int32_cast_dtype(ast::DataType::Custom(
2572                ObjectName(vec![Ident::new("SIGNED")]),
2573                vec![],
2574            ))
2575            .build();
2576
2577        for (dialect, identifier) in
2578            [(default_dialect, "INTEGER"), (mysql_dialect, "SIGNED")]
2579        {
2580            let unparser = Unparser::new(&dialect);
2581            let expr = Expr::Cast(Cast {
2582                expr: Box::new(col("a")),
2583                data_type: DataType::Int32,
2584            });
2585            let ast = unparser.expr_to_sql(&expr)?;
2586
2587            let actual = format!("{}", ast);
2588            let expected = format!(r#"CAST(a AS {identifier})"#);
2589
2590            assert_eq!(actual, expected);
2591        }
2592        Ok(())
2593    }
2594
2595    #[test]
2596    fn custom_dialect_with_timestamp_cast_dtype() -> Result<()> {
2597        let default_dialect = CustomDialectBuilder::new().build();
2598        let mysql_dialect = CustomDialectBuilder::new()
2599            .with_timestamp_cast_dtype(
2600                ast::DataType::Datetime(None),
2601                ast::DataType::Datetime(None),
2602            )
2603            .build();
2604
2605        let timestamp = DataType::Timestamp(TimeUnit::Nanosecond, None);
2606        let timestamp_with_tz =
2607            DataType::Timestamp(TimeUnit::Nanosecond, Some("+08:00".into()));
2608
2609        for (dialect, data_type, identifier) in [
2610            (&default_dialect, &timestamp, "TIMESTAMP"),
2611            (
2612                &default_dialect,
2613                &timestamp_with_tz,
2614                "TIMESTAMP WITH TIME ZONE",
2615            ),
2616            (&mysql_dialect, &timestamp, "DATETIME"),
2617            (&mysql_dialect, &timestamp_with_tz, "DATETIME"),
2618        ] {
2619            let unparser = Unparser::new(dialect);
2620            let expr = Expr::Cast(Cast {
2621                expr: Box::new(col("a")),
2622                data_type: data_type.clone(),
2623            });
2624            let ast = unparser.expr_to_sql(&expr)?;
2625
2626            let actual = format!("{}", ast);
2627            let expected = format!(r#"CAST(a AS {identifier})"#);
2628
2629            assert_eq!(actual, expected);
2630        }
2631        Ok(())
2632    }
2633
2634    #[test]
2635    fn custom_dialect_with_timestamp_cast_dtype_scalar_expr() -> Result<()> {
2636        let default_dialect = CustomDialectBuilder::new().build();
2637        let mysql_dialect = CustomDialectBuilder::new()
2638            .with_timestamp_cast_dtype(
2639                ast::DataType::Datetime(None),
2640                ast::DataType::Datetime(None),
2641            )
2642            .build();
2643
2644        for (dialect, identifier) in [
2645            (&default_dialect, "TIMESTAMP"),
2646            (&mysql_dialect, "DATETIME"),
2647        ] {
2648            let unparser = Unparser::new(dialect);
2649            let expr = Expr::Literal(ScalarValue::TimestampMillisecond(
2650                Some(1738285549123),
2651                None,
2652            ));
2653            let ast = unparser.expr_to_sql(&expr)?;
2654
2655            let actual = format!("{}", ast);
2656            let expected = format!(r#"CAST('2025-01-31 01:05:49.123' AS {identifier})"#);
2657
2658            assert_eq!(actual, expected);
2659        }
2660        Ok(())
2661    }
2662
2663    #[test]
2664    fn custom_dialect_date32_ast_dtype() -> Result<()> {
2665        let default_dialect = CustomDialectBuilder::default().build();
2666        let sqlite_custom_dialect = CustomDialectBuilder::new()
2667            .with_date32_cast_dtype(ast::DataType::Text)
2668            .build();
2669
2670        for (dialect, data_type, identifier) in [
2671            (&default_dialect, DataType::Date32, "DATE"),
2672            (&sqlite_custom_dialect, DataType::Date32, "TEXT"),
2673        ] {
2674            let unparser = Unparser::new(dialect);
2675
2676            let expr = Expr::Cast(Cast {
2677                expr: Box::new(col("a")),
2678                data_type,
2679            });
2680            let ast = unparser.expr_to_sql(&expr)?;
2681
2682            let actual = format!("{}", ast);
2683            let expected = format!(r#"CAST(a AS {identifier})"#);
2684
2685            assert_eq!(actual, expected);
2686        }
2687        Ok(())
2688    }
2689
2690    #[test]
2691    fn custom_dialect_division_operator() -> Result<()> {
2692        let default_dialect = CustomDialectBuilder::new().build();
2693        let duckdb_dialect = CustomDialectBuilder::new()
2694            .with_division_operator(BinaryOperator::DuckIntegerDivide)
2695            .build();
2696
2697        for (dialect, expected) in
2698            [(default_dialect, "(a / b)"), (duckdb_dialect, "(a // b)")]
2699        {
2700            let unparser = Unparser::new(&dialect);
2701            let expr = Expr::BinaryExpr(BinaryExpr {
2702                left: Box::new(col("a")),
2703                op: Operator::Divide,
2704                right: Box::new(col("b")),
2705            });
2706            let ast = unparser.expr_to_sql(&expr)?;
2707
2708            let actual = format!("{}", ast);
2709            let expected = expected.to_string();
2710
2711            assert_eq!(actual, expected);
2712        }
2713        Ok(())
2714    }
2715
2716    #[test]
2717    fn test_cast_value_to_dict_expr() {
2718        let tests = [(
2719            Expr::Cast(Cast {
2720                expr: Box::new(Expr::Literal(ScalarValue::Utf8(Some(
2721                    "variation".to_string(),
2722                )))),
2723                data_type: DataType::Dictionary(Box::new(Int8), Box::new(DataType::Utf8)),
2724            }),
2725            "'variation'",
2726        )];
2727        for (value, expected) in tests {
2728            let dialect = CustomDialectBuilder::new().build();
2729            let unparser = Unparser::new(&dialect);
2730
2731            let ast = unparser.expr_to_sql(&value).expect("to be unparsed");
2732            let actual = format!("{ast}");
2733
2734            assert_eq!(actual, expected);
2735        }
2736    }
2737
2738    #[test]
2739    fn test_round_scalar_fn_to_expr() -> Result<()> {
2740        let default_dialect: Arc<dyn Dialect> = Arc::new(
2741            CustomDialectBuilder::new()
2742                .with_identifier_quote_style('"')
2743                .build(),
2744        );
2745        let postgres_dialect: Arc<dyn Dialect> = Arc::new(PostgreSqlDialect {});
2746
2747        for (dialect, identifier) in
2748            [(default_dialect, "DOUBLE"), (postgres_dialect, "NUMERIC")]
2749        {
2750            let unparser = Unparser::new(dialect.as_ref());
2751            let expr = Expr::ScalarFunction(ScalarFunction {
2752                func: Arc::new(ScalarUDF::from(
2753                    datafusion_functions::math::round::RoundFunc::new(),
2754                )),
2755                args: vec![
2756                    Expr::Cast(Cast {
2757                        expr: Box::new(col("a")),
2758                        data_type: DataType::Float64,
2759                    }),
2760                    Expr::Literal(ScalarValue::Int64(Some(2))),
2761                ],
2762            });
2763            let ast = unparser.expr_to_sql(&expr)?;
2764
2765            let actual = format!("{}", ast);
2766            let expected = format!(r#"round(CAST("a" AS {identifier}), 2)"#);
2767
2768            assert_eq!(actual, expected);
2769        }
2770        Ok(())
2771    }
2772
2773    #[test]
2774    fn test_window_func_support_window_frame() -> Result<()> {
2775        let default_dialect: Arc<dyn Dialect> =
2776            Arc::new(CustomDialectBuilder::new().build());
2777
2778        let test_dialect: Arc<dyn Dialect> = Arc::new(
2779            CustomDialectBuilder::new()
2780                .with_window_func_support_window_frame(false)
2781                .build(),
2782        );
2783
2784        for (dialect, expected) in [
2785            (
2786                default_dialect,
2787                "rank() OVER (ORDER BY a ASC NULLS FIRST ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)",
2788            ),
2789            (test_dialect, "rank() OVER (ORDER BY a ASC NULLS FIRST)"),
2790        ] {
2791            let unparser = Unparser::new(dialect.as_ref());
2792            let func = WindowFunctionDefinition::WindowUDF(rank_udwf());
2793            let mut window_func = WindowFunction::new(func, vec![]);
2794            window_func.params.order_by = vec![Sort::new(col("a"), true, true)];
2795            let expr = Expr::WindowFunction(window_func);
2796            let ast = unparser.expr_to_sql(&expr)?;
2797
2798            let actual = ast.to_string();
2799            let expected = expected.to_string();
2800
2801            assert_eq!(actual, expected);
2802        }
2803        Ok(())
2804    }
2805
2806    #[test]
2807    fn test_dictionary_to_sql() -> Result<()> {
2808        let dialect = CustomDialectBuilder::new().build();
2809
2810        let unparser = Unparser::new(&dialect);
2811
2812        let ast_dtype = unparser.arrow_dtype_to_ast_dtype(&DataType::Dictionary(
2813            Box::new(DataType::Int32),
2814            Box::new(DataType::Utf8),
2815        ))?;
2816
2817        assert_eq!(ast_dtype, ast::DataType::Varchar(None));
2818
2819        Ok(())
2820    }
2821
2822    #[test]
2823    fn test_utf8_view_to_sql() -> Result<()> {
2824        let dialect = CustomDialectBuilder::new()
2825            .with_utf8_cast_dtype(ast::DataType::Char(None))
2826            .build();
2827        let unparser = Unparser::new(&dialect);
2828
2829        let ast_dtype = unparser.arrow_dtype_to_ast_dtype(&DataType::Utf8View)?;
2830
2831        assert_eq!(ast_dtype, ast::DataType::Char(None));
2832
2833        let expr = cast(col("a"), DataType::Utf8View);
2834        let ast = unparser.expr_to_sql(&expr)?;
2835
2836        let actual = format!("{}", ast);
2837        let expected = r#"CAST(a AS CHAR)"#.to_string();
2838
2839        assert_eq!(actual, expected);
2840
2841        let expr = col("a").eq(lit(ScalarValue::Utf8View(Some("hello".to_string()))));
2842        let ast = unparser.expr_to_sql(&expr)?;
2843
2844        let actual = format!("{}", ast);
2845        let expected = r#"(a = 'hello')"#.to_string();
2846
2847        assert_eq!(actual, expected);
2848
2849        let expr = col("a").is_not_null();
2850
2851        let ast = unparser.expr_to_sql(&expr)?;
2852        let actual = format!("{}", ast);
2853        let expected = r#"a IS NOT NULL"#.to_string();
2854
2855        assert_eq!(actual, expected);
2856
2857        let expr = col("a").is_null();
2858
2859        let ast = unparser.expr_to_sql(&expr)?;
2860        let actual = format!("{}", ast);
2861        let expected = r#"a IS NULL"#.to_string();
2862
2863        assert_eq!(actual, expected);
2864
2865        Ok(())
2866    }
2867
2868    #[test]
2869    fn test_custom_scalar_overrides_duckdb() -> Result<()> {
2870        let duckdb_default = DuckDBDialect::new();
2871        let duckdb_extended = DuckDBDialect::new().with_custom_scalar_overrides(vec![(
2872            "dummy_udf",
2873            Box::new(|unparser: &Unparser, args: &[Expr]| {
2874                unparser.scalar_function_to_sql("smart_udf", args).map(Some)
2875            }) as ScalarFnToSqlHandler,
2876        )]);
2877
2878        for (dialect, expected) in [
2879            (duckdb_default, r#"dummy_udf("a", "b")"#),
2880            (duckdb_extended, r#"smart_udf("a", "b")"#),
2881        ] {
2882            let unparser = Unparser::new(&dialect);
2883            let expr =
2884                ScalarUDF::new_from_impl(DummyUDF::new()).call(vec![col("a"), col("b")]);
2885            let actual = format!("{}", unparser.expr_to_sql(&expr)?);
2886            assert_eq!(actual, expected);
2887        }
2888
2889        Ok(())
2890    }
2891}