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