1use 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
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 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 #[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 _ => 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 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 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 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 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 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 fn interval_to_mysql_expr(
1296 &self,
1297 months: i32,
1298 days: i32,
1299 microseconds: i64,
1300 ) -> Result<ast::Expr> {
1301 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 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 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 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 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 #[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 #[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 (
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, ×tamp, "TIMESTAMP"),
2611 (
2612 &default_dialect,
2613 ×tamp_with_tz,
2614 "TIMESTAMP WITH TIME ZONE",
2615 ),
2616 (&mysql_dialect, ×tamp, "DATETIME"),
2617 (&mysql_dialect, ×tamp_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}