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