1use super::{DialectImpl, DialectType};
13use crate::error::Result;
14use crate::expressions::{
15 AggFunc, Alias, BinaryOp, Case, Cast, CeilFunc, Column, DataType, Expression, Function,
16 Identifier, Interval, IntervalUnit, IntervalUnitSpec, IsNull, JSONPath, JSONPathKey,
17 JSONPathRoot, JSONPathSubscript, JsonExtractFunc, Literal, Null, Paren, Struct, Subquery,
18 SubstringFunc, UnaryFunc, UnaryOp, Unhex, VarArgFunc, WindowFunction,
19};
20#[cfg(feature = "generate")]
21use crate::generator::GeneratorConfig;
22use crate::tokens::TokenizerConfig;
23
24fn normalize_json_path(path: Expression) -> Expression {
28 match &path {
29 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
31 let Literal::String(s) = lit.as_ref() else {
32 unreachable!()
33 };
34 if s.starts_with('$') || s.starts_with('/') || s.contains("[#") {
37 return path;
38 }
39 Expression::JSONPath(Box::new(JSONPath {
41 expressions: vec![
42 Expression::JSONPathRoot(JSONPathRoot),
43 Expression::JSONPathKey(Box::new(JSONPathKey {
44 this: Box::new(Expression::Literal(Box::new(Literal::String(s.clone())))),
45 })),
46 ],
47 escape: None,
48 }))
49 }
50 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
52 let Literal::Number(n) = lit.as_ref() else {
53 unreachable!()
54 };
55 Expression::JSONPath(Box::new(JSONPath {
57 expressions: vec![
58 Expression::JSONPathRoot(JSONPathRoot),
59 Expression::JSONPathSubscript(Box::new(JSONPathSubscript {
60 this: Box::new(Expression::Literal(Box::new(Literal::Number(n.clone())))),
61 })),
62 ],
63 escape: None,
64 }))
65 }
66 _ => path,
68 }
69}
70
71fn wrap_if_json_arrow(expr: Expression) -> Expression {
75 match &expr {
76 Expression::JsonExtract(f) if f.arrow_syntax => Expression::Paren(Box::new(Paren {
77 this: expr,
78 trailing_comments: Vec::new(),
79 })),
80 Expression::JsonExtractScalar(f) if f.arrow_syntax => Expression::Paren(Box::new(Paren {
81 this: expr,
82 trailing_comments: Vec::new(),
83 })),
84 _ => expr,
85 }
86}
87
88pub struct DuckDBDialect;
90
91impl DialectImpl for DuckDBDialect {
92 fn dialect_type(&self) -> DialectType {
93 DialectType::DuckDB
94 }
95
96 fn tokenizer_config(&self) -> TokenizerConfig {
97 let mut config = TokenizerConfig::default();
98 config.identifiers.insert('"', '"');
100 config.nested_comments = true;
102 config.numbers_can_be_underscore_separated = true;
104 config
105 }
106
107 #[cfg(feature = "generate")]
108
109 fn generator_config(&self) -> GeneratorConfig {
110 use crate::generator::IdentifierQuoteStyle;
111 GeneratorConfig {
112 identifier_quote: '"',
113 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
114 dialect: Some(DialectType::DuckDB),
115 parameter_token: "$",
117 named_placeholder_token: "$",
118 join_hints: false,
119 table_hints: false,
120 query_hints: false,
121 limit_fetch_style: crate::generator::LimitFetchStyle::Limit,
122 struct_delimiter: ("(", ")"),
123 rename_table_with_db: false,
124 nvl2_supported: false,
125 semi_anti_join_with_side: false,
126 tablesample_keywords: "TABLESAMPLE",
127 tablesample_seed_keyword: "REPEATABLE",
128 last_day_supports_date_part: false,
129 json_key_value_pair_sep: ",",
130 ignore_nulls_in_func: true,
131 json_path_bracketed_key_supported: false,
132 supports_create_table_like: false,
133 multi_arg_distinct: false,
134 quantified_no_paren_space: false,
135 can_implement_array_any: true,
136 supports_to_number: false,
137 supports_window_exclude: true,
138 copy_has_into_keyword: false,
139 star_except: "EXCLUDE",
140 pad_fill_pattern_is_required: true,
141 array_concat_is_var_len: false,
142 array_size_dim_required: None,
143 normalize_extract_date_parts: true,
144 supports_like_quantifiers: false,
145 try_supported: true,
147 struct_curly_brace_notation: true,
149 array_bracket_only: true,
151 ..Default::default()
152 }
153 }
154
155 #[cfg(feature = "transpile")]
156
157 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
158 match expr {
159 Expression::DataType(dt) => self.transform_data_type(dt),
161
162 Expression::BitwiseXor(op) => Ok(Expression::Function(Box::new(
165 crate::expressions::Function::new("XOR", vec![op.left, op.right]),
166 ))),
167
168 Expression::ArrayFunc(mut f) => {
171 f.bracket_notation = true;
172 Ok(Expression::ArrayFunc(f))
173 }
174
175 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
177 original_name: None,
178 expressions: vec![f.this, f.expression],
179 inferred_type: None,
180 }))),
181
182 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
184 original_name: None,
185 expressions: vec![f.this, f.expression],
186 inferred_type: None,
187 }))),
188
189 Expression::Coalesce(mut f) => {
191 f.original_name = None;
192 Ok(Expression::Coalesce(f))
193 }
194
195 Expression::GroupConcat(f) => Ok(Expression::ListAgg(Box::new(
197 crate::expressions::ListAggFunc {
198 this: f.this,
199 separator: f.separator,
200 on_overflow: None,
201 order_by: f.order_by,
202 distinct: f.distinct,
203 filter: f.filter,
204 inferred_type: None,
205 },
206 ))),
207
208 Expression::ListAgg(f) => Ok(Expression::ListAgg(f)),
210
211 Expression::StringAgg(f) => Ok(Expression::ListAgg(Box::new(
213 crate::expressions::ListAggFunc {
214 this: f.this,
215 separator: f.separator,
216 on_overflow: None,
217 order_by: f.order_by,
218 distinct: f.distinct,
219 filter: f.filter,
220 inferred_type: None,
221 },
222 ))),
223
224 Expression::TryCast(c) => Ok(Expression::TryCast(c)),
226
227 Expression::SafeCast(c) => Ok(Expression::TryCast(c)),
229
230 Expression::ILike(op) => Ok(Expression::ILike(op)),
232
233 Expression::Explode(f) => Ok(Expression::Unnest(Box::new(
235 crate::expressions::UnnestFunc {
236 this: f.this,
237 expressions: Vec::new(),
238 with_ordinality: false,
239 alias: None,
240 offset_alias: None,
241 inferred_type: None,
242 },
243 ))),
244
245 Expression::Unnest(f) => Ok(Expression::Unnest(f)),
247
248 Expression::DateAdd(f) => {
250 let interval_expr = if matches!(&f.interval, Expression::Interval(_)) {
252 f.interval
253 } else {
254 Expression::Interval(Box::new(Interval {
255 this: Some(f.interval),
256 unit: Some(IntervalUnitSpec::Simple {
257 unit: f.unit,
258 use_plural: false,
259 }),
260 }))
261 };
262 Ok(Expression::Add(Box::new(BinaryOp {
263 left: f.this,
264 right: interval_expr,
265 left_comments: Vec::new(),
266 operator_comments: Vec::new(),
267 trailing_comments: Vec::new(),
268 inferred_type: None,
269 })))
270 }
271
272 Expression::DateSub(f) => {
274 let interval_expr = if matches!(&f.interval, Expression::Interval(_)) {
276 f.interval
277 } else {
278 Expression::Interval(Box::new(Interval {
279 this: Some(f.interval),
280 unit: Some(IntervalUnitSpec::Simple {
281 unit: f.unit,
282 use_plural: false,
283 }),
284 }))
285 };
286 Ok(Expression::Sub(Box::new(BinaryOp {
287 left: f.this,
288 right: interval_expr,
289 left_comments: Vec::new(),
290 operator_comments: Vec::new(),
291 trailing_comments: Vec::new(),
292 inferred_type: None,
293 })))
294 }
295
296 Expression::GenerateSeries(mut f) => {
298 if f.start.is_none() && f.end.is_some() {
300 f.start = Some(Box::new(Expression::number(0)));
301 }
302 Ok(Expression::GenerateSeries(f))
303 }
304
305 Expression::ArrayAppend(f) => Ok(Expression::Function(Box::new(Function::new(
308 "LIST_APPEND".to_string(),
309 vec![f.this, f.expression],
310 )))),
311
312 Expression::ArrayPrepend(f) => Ok(Expression::Function(Box::new(Function::new(
314 "LIST_PREPEND".to_string(),
315 vec![f.expression, f.this],
316 )))),
317
318 Expression::ArrayUniqueAgg(f) => {
320 let col = f.this;
321 let filter_expr = Expression::Not(Box::new(UnaryOp {
323 this: Expression::IsNull(Box::new(IsNull {
324 this: col.clone(),
325 not: false,
326 postfix_form: false,
327 })),
328 inferred_type: None,
329 }));
330 Ok(Expression::ArrayAgg(Box::new(AggFunc {
331 this: col,
332 distinct: true,
333 filter: Some(filter_expr),
334 order_by: Vec::new(),
335 name: Some("LIST".to_string()),
336 ignore_nulls: None,
337 having_max: None,
338 limit: None,
339 inferred_type: None,
340 })))
341 }
342
343 Expression::Split(f) => Ok(Expression::Function(Box::new(Function::new(
345 "STR_SPLIT".to_string(),
346 vec![f.this, f.delimiter],
347 )))),
348
349 Expression::Random(_) => Ok(Expression::Random(crate::expressions::Random)),
351
352 Expression::Rand(r) => {
355 if r.seed.is_some() {
356 Ok(Expression::Rand(r))
357 } else {
358 Ok(Expression::Random(crate::expressions::Random))
359 }
360 }
361
362 Expression::LogicalAnd(f) => Ok(Expression::Function(Box::new(Function::new(
365 "BOOL_AND".to_string(),
366 vec![Expression::Cast(Box::new(crate::expressions::Cast {
367 this: f.this,
368 to: crate::expressions::DataType::Boolean,
369 trailing_comments: Vec::new(),
370 double_colon_syntax: false,
371 format: None,
372 default: None,
373 inferred_type: None,
374 }))],
375 )))),
376
377 Expression::LogicalOr(f) => Ok(Expression::Function(Box::new(Function::new(
379 "BOOL_OR".to_string(),
380 vec![Expression::Cast(Box::new(crate::expressions::Cast {
381 this: f.this,
382 to: crate::expressions::DataType::Boolean,
383 trailing_comments: Vec::new(),
384 double_colon_syntax: false,
385 format: None,
386 default: None,
387 inferred_type: None,
388 }))],
389 )))),
390
391 Expression::ApproxDistinct(f) => Ok(Expression::Function(Box::new(Function::new(
394 "APPROX_COUNT_DISTINCT".to_string(),
395 vec![f.this],
396 )))),
397
398 Expression::VarPop(f) => Ok(Expression::Function(Box::new(Function::new(
401 "VAR_POP".to_string(),
402 vec![f.this],
403 )))),
404
405 Expression::DayOfMonth(f) => Ok(Expression::Function(Box::new(Function::new(
408 "DAYOFMONTH".to_string(),
409 vec![f.this],
410 )))),
411
412 Expression::DayOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
414 "DAYOFWEEK".to_string(),
415 vec![f.this],
416 )))),
417
418 Expression::DayOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
420 "ISODOW".to_string(),
421 vec![f.this],
422 )))),
423
424 Expression::DayOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
426 "DAYOFYEAR".to_string(),
427 vec![f.this],
428 )))),
429
430 Expression::WeekOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
432 "WEEKOFYEAR".to_string(),
433 vec![f.this],
434 )))),
435
436 Expression::TimeStrToUnix(f) => Ok(Expression::Function(Box::new(Function::new(
439 "EPOCH".to_string(),
440 vec![f.this],
441 )))),
442
443 Expression::TimeToUnix(f) => Ok(Expression::Function(Box::new(Function::new(
445 "EPOCH".to_string(),
446 vec![f.this],
447 )))),
448
449 Expression::UnixMicros(f) => Ok(Expression::Function(Box::new(Function::new(
451 "EPOCH_US".to_string(),
452 vec![f.this],
453 )))),
454
455 Expression::UnixMillis(f) => Ok(Expression::Function(Box::new(Function::new(
457 "EPOCH_MS".to_string(),
458 vec![f.this],
459 )))),
460
461 Expression::TimestampDiff(f) => Ok(Expression::Function(Box::new(Function::new(
463 "DATE_DIFF".to_string(),
464 vec![*f.this, *f.expression],
465 )))),
466
467 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
470 "SHA1".to_string(),
471 vec![f.this],
472 )))),
473
474 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
476 "UNHEX".to_string(),
477 vec![*f.this],
478 )))),
479
480 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
482 "UNHEX".to_string(),
483 vec![f.this],
484 )))),
485
486 Expression::SHA2Digest(f) => Ok(Expression::Function(Box::new(Function::new(
488 "UNHEX".to_string(),
489 vec![*f.this],
490 )))),
491
492 Expression::CosineDistance(f) => Ok(Expression::Function(Box::new(Function::new(
495 "LIST_COSINE_DISTANCE".to_string(),
496 vec![*f.this, *f.expression],
497 )))),
498
499 Expression::EuclideanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
501 "LIST_DISTANCE".to_string(),
502 vec![*f.this, *f.expression],
503 )))),
504
505 Expression::IsInf(f) => Ok(Expression::Function(Box::new(Function::new(
508 "ISINF".to_string(),
509 vec![f.this],
510 )))),
511
512 Expression::IsNan(f) => Ok(Expression::Function(Box::new(Function::new(
514 "ISNAN".to_string(),
515 vec![f.this],
516 )))),
517
518 Expression::RegexpLike(f) => Ok(Expression::Function(Box::new(Function::new(
521 "REGEXP_FULL_MATCH".to_string(),
522 vec![f.this, f.pattern],
523 )))),
524
525 Expression::CurrentTime(_) => Ok(Expression::Function(Box::new(Function {
528 name: "CURRENT_TIME".to_string(),
529 args: vec![],
530 distinct: false,
531 trailing_comments: vec![],
532 use_bracket_syntax: false,
533 no_parens: true,
534 quoted: false,
535 span: None,
536 inferred_type: None,
537 }))),
538
539 Expression::ReturnStmt(e) => Ok(*e),
542
543 Expression::CommentColumnConstraint(_) => Ok(Expression::Literal(Box::new(
546 crate::expressions::Literal::String(String::new()),
547 ))),
548
549 Expression::JsonExtract(mut f) => {
551 f.arrow_syntax = true;
552 f.path = normalize_json_path(f.path);
553 Ok(Expression::JsonExtract(f))
554 }
555
556 Expression::JsonExtractScalar(mut f) => {
558 f.arrow_syntax = true;
559 f.path = normalize_json_path(f.path);
560 Ok(Expression::JsonExtractScalar(f))
561 }
562
563 Expression::AddMonths(f) => {
569 let func = Function::new("ADD_MONTHS".to_string(), vec![f.this, f.expression]);
570 self.transform_function(func)
571 }
572
573 Expression::NextDay(f) => {
575 let func = Function::new("NEXT_DAY".to_string(), vec![f.this, f.expression]);
576 self.transform_function(func)
577 }
578
579 Expression::LastDay(f) => {
581 if let Some(unit) = f.unit {
582 let unit_str = match unit {
583 crate::expressions::DateTimeField::Year => "YEAR",
584 crate::expressions::DateTimeField::Month => "MONTH",
585 crate::expressions::DateTimeField::Quarter => "QUARTER",
586 crate::expressions::DateTimeField::Week => "WEEK",
587 crate::expressions::DateTimeField::Day => "DAY",
588 _ => "MONTH",
589 };
590 let func = Function::new(
591 "LAST_DAY".to_string(),
592 vec![
593 f.this,
594 Expression::Identifier(Identifier {
595 name: unit_str.to_string(),
596 quoted: false,
597 trailing_comments: Vec::new(),
598 span: None,
599 }),
600 ],
601 );
602 self.transform_function(func)
603 } else {
604 Ok(Expression::Function(Box::new(Function::new(
606 "LAST_DAY".to_string(),
607 vec![f.this],
608 ))))
609 }
610 }
611
612 Expression::Dayname(d) => Ok(Expression::Function(Box::new(Function::new(
614 "STRFTIME".to_string(),
615 vec![
616 *d.this,
617 Expression::Literal(Box::new(Literal::String("%a".to_string()))),
618 ],
619 )))),
620
621 Expression::Monthname(d) => Ok(Expression::Function(Box::new(Function::new(
623 "STRFTIME".to_string(),
624 vec![
625 *d.this,
626 Expression::Literal(Box::new(Literal::String("%b".to_string()))),
627 ],
628 )))),
629
630 Expression::Floor(f) if f.scale.is_some() => {
632 let x = f.this;
633 let scale = f.scale.unwrap();
634 let needs_cast = match &scale {
635 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
636 let Literal::Number(n) = lit.as_ref() else {
637 unreachable!()
638 };
639 n.contains('.')
640 }
641 _ => false,
642 };
643 let int_scale = if needs_cast {
644 Expression::Cast(Box::new(Cast {
645 this: scale.clone(),
646 to: DataType::Int {
647 length: None,
648 integer_spelling: false,
649 },
650 trailing_comments: Vec::new(),
651 double_colon_syntax: false,
652 format: None,
653 default: None,
654 inferred_type: None,
655 }))
656 } else {
657 scale.clone()
658 };
659 let power_10 = Expression::Function(Box::new(Function::new(
660 "POWER".to_string(),
661 vec![Expression::number(10), int_scale.clone()],
662 )));
663 let x_paren = match &x {
664 Expression::Add(_)
665 | Expression::Sub(_)
666 | Expression::Mul(_)
667 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
668 this: x,
669 trailing_comments: Vec::new(),
670 })),
671 _ => x,
672 };
673 let multiplied = Expression::Mul(Box::new(BinaryOp {
674 left: x_paren,
675 right: power_10.clone(),
676 left_comments: Vec::new(),
677 operator_comments: Vec::new(),
678 trailing_comments: Vec::new(),
679 inferred_type: None,
680 }));
681 let floored = Expression::Function(Box::new(Function::new(
682 "FLOOR".to_string(),
683 vec![multiplied],
684 )));
685 let divided = Expression::Div(Box::new(BinaryOp {
686 left: floored,
687 right: power_10,
688 left_comments: Vec::new(),
689 operator_comments: Vec::new(),
690 trailing_comments: Vec::new(),
691 inferred_type: None,
692 }));
693 Ok(Expression::Function(Box::new(Function::new(
694 "ROUND".to_string(),
695 vec![divided, int_scale],
696 ))))
697 }
698
699 Expression::Ceil(f) if f.decimals.is_some() => {
701 let x = f.this;
702 let scale = f.decimals.unwrap();
703 let needs_cast = match &scale {
704 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
705 let Literal::Number(n) = lit.as_ref() else {
706 unreachable!()
707 };
708 n.contains('.')
709 }
710 _ => false,
711 };
712 let int_scale = if needs_cast {
713 Expression::Cast(Box::new(Cast {
714 this: scale.clone(),
715 to: DataType::Int {
716 length: None,
717 integer_spelling: false,
718 },
719 trailing_comments: Vec::new(),
720 double_colon_syntax: false,
721 format: None,
722 default: None,
723 inferred_type: None,
724 }))
725 } else {
726 scale.clone()
727 };
728 let power_10 = Expression::Function(Box::new(Function::new(
729 "POWER".to_string(),
730 vec![Expression::number(10), int_scale.clone()],
731 )));
732 let x_paren = match &x {
733 Expression::Add(_)
734 | Expression::Sub(_)
735 | Expression::Mul(_)
736 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
737 this: x,
738 trailing_comments: Vec::new(),
739 })),
740 _ => x,
741 };
742 let multiplied = Expression::Mul(Box::new(BinaryOp {
743 left: x_paren,
744 right: power_10.clone(),
745 left_comments: Vec::new(),
746 operator_comments: Vec::new(),
747 trailing_comments: Vec::new(),
748 inferred_type: None,
749 }));
750 let ceiled = Expression::Function(Box::new(Function::new(
751 "CEIL".to_string(),
752 vec![multiplied],
753 )));
754 let divided = Expression::Div(Box::new(BinaryOp {
755 left: ceiled,
756 right: power_10,
757 left_comments: Vec::new(),
758 operator_comments: Vec::new(),
759 trailing_comments: Vec::new(),
760 inferred_type: None,
761 }));
762 Ok(Expression::Function(Box::new(Function::new(
763 "ROUND".to_string(),
764 vec![divided, int_scale],
765 ))))
766 }
767
768 Expression::TableArgument(ta) if ta.prefix.to_uppercase() == "TABLE" => {
773 match ta.this {
775 Expression::Function(ref f) if f.name.to_uppercase() == "RANGE" => {
776 Ok(ta.this)
778 }
779 Expression::Function(ref f) if f.name.to_uppercase() == "GENERATOR" => {
780 let mut rowcount = None;
782 for arg in &f.args {
783 if let Expression::NamedArgument(na) = arg {
784 if na.name.name.to_uppercase() == "ROWCOUNT" {
785 rowcount = Some(na.value.clone());
786 }
787 }
788 }
789 if let Some(n) = rowcount {
790 Ok(Expression::Function(Box::new(Function::new(
791 "RANGE".to_string(),
792 vec![n],
793 ))))
794 } else {
795 Ok(Expression::TableArgument(ta))
796 }
797 }
798 _ => Ok(Expression::TableArgument(ta)),
799 }
800 }
801
802 Expression::JSONExtract(e) if e.variant_extract.is_some() => {
804 let path = match *e.expression {
805 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
806 let Literal::String(s) = lit.as_ref() else {
807 unreachable!()
808 };
809 let s = Self::convert_bracket_to_quoted_path(&s);
811 let normalized = if s.starts_with('$') {
812 s
813 } else if s.starts_with('[') {
814 format!("${}", s)
815 } else {
816 format!("$.{}", s)
817 };
818 Expression::Literal(Box::new(Literal::String(normalized)))
819 }
820 other => other,
821 };
822 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
823 this: *e.this,
824 path,
825 returning: None,
826 arrow_syntax: true,
827 hash_arrow_syntax: false,
828 wrapper_option: None,
829 quotes_option: None,
830 on_scalar_string: false,
831 on_error: None,
832 })))
833 }
834
835 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::HexString(_)) => {
837 let Literal::HexString(s) = lit.as_ref() else {
838 unreachable!()
839 };
840 Ok(Expression::Function(Box::new(Function::new(
841 "UNHEX".to_string(),
842 vec![Expression::Literal(Box::new(Literal::String(s.clone())))],
843 ))))
844 }
845
846 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::ByteString(_)) => {
848 let Literal::ByteString(s) = lit.as_ref() else {
849 unreachable!()
850 };
851 Ok(Expression::Cast(Box::new(Cast {
852 this: Expression::Literal(Box::new(Literal::EscapeString(s.clone()))),
853 to: DataType::VarBinary { length: None },
854 trailing_comments: Vec::new(),
855 double_colon_syntax: false,
856 format: None,
857 default: None,
858 inferred_type: None,
859 })))
860 }
861
862 Expression::Cast(mut c) => {
865 if matches!(
866 &c.to,
867 DataType::Decimal {
868 precision: None,
869 ..
870 }
871 ) && !matches!(&c.this, Expression::IntDiv(_))
872 {
873 c.to = DataType::Decimal {
874 precision: Some(18),
875 scale: Some(3),
876 };
877 }
878 let transformed_this = self.transform_expr(c.this)?;
879 c.this = transformed_this;
880 Ok(Expression::Cast(c))
881 }
882
883 Expression::Function(f) => self.transform_function(*f),
885
886 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
888
889 Expression::WindowFunction(wf) => {
893 if let Expression::Case(case_box) = wf.this {
894 let case = *case_box;
895 if case.whens.len() == 1
897 && matches!(&case.else_, Some(Expression::AggregateFunction(ref af)) if af.name.to_uppercase() == "CORR")
898 {
899 let over = wf.over;
901 let new_else = case.else_.map(|e| {
902 Expression::WindowFunction(Box::new(WindowFunction {
903 this: e,
904 over: over.clone(),
905 keep: None,
906 inferred_type: None,
907 }))
908 });
909 let new_whens = case
910 .whens
911 .into_iter()
912 .map(|(when_cond, when_result)| {
913 let new_cond = if let Expression::Function(func) = when_cond {
915 if func.name.to_uppercase() == "ISNAN" && func.args.len() == 1 {
916 let inner = func.args.into_iter().next().unwrap();
917 let windowed =
918 Expression::WindowFunction(Box::new(WindowFunction {
919 this: inner,
920 over: over.clone(),
921 keep: None,
922 inferred_type: None,
923 }));
924 Expression::Function(Box::new(Function::new(
925 "ISNAN".to_string(),
926 vec![windowed],
927 )))
928 } else {
929 Expression::Function(func)
930 }
931 } else {
932 when_cond
933 };
934 (new_cond, when_result)
935 })
936 .collect();
937 Ok(Expression::Case(Box::new(Case {
938 operand: None,
939 whens: new_whens,
940 else_: new_else,
941 comments: Vec::new(),
942 inferred_type: None,
943 })))
944 } else {
945 Ok(Expression::WindowFunction(Box::new(WindowFunction {
946 this: Expression::Case(Box::new(case)),
947 over: wf.over,
948 keep: wf.keep,
949 inferred_type: None,
950 })))
951 }
952 } else {
953 Ok(Expression::WindowFunction(wf))
954 }
955 }
956
957 Expression::Eq(op) => Ok(Expression::Eq(Box::new(BinaryOp {
964 left: wrap_if_json_arrow(op.left),
965 right: wrap_if_json_arrow(op.right),
966 ..*op
967 }))),
968 Expression::Neq(op) => Ok(Expression::Neq(Box::new(BinaryOp {
969 left: wrap_if_json_arrow(op.left),
970 right: wrap_if_json_arrow(op.right),
971 ..*op
972 }))),
973 Expression::Lt(op) => Ok(Expression::Lt(Box::new(BinaryOp {
974 left: wrap_if_json_arrow(op.left),
975 right: wrap_if_json_arrow(op.right),
976 ..*op
977 }))),
978 Expression::Lte(op) => Ok(Expression::Lte(Box::new(BinaryOp {
979 left: wrap_if_json_arrow(op.left),
980 right: wrap_if_json_arrow(op.right),
981 ..*op
982 }))),
983 Expression::Gt(op) => Ok(Expression::Gt(Box::new(BinaryOp {
984 left: wrap_if_json_arrow(op.left),
985 right: wrap_if_json_arrow(op.right),
986 ..*op
987 }))),
988 Expression::Gte(op) => Ok(Expression::Gte(Box::new(BinaryOp {
989 left: wrap_if_json_arrow(op.left),
990 right: wrap_if_json_arrow(op.right),
991 ..*op
992 }))),
993 Expression::And(op) => Ok(Expression::And(Box::new(BinaryOp {
994 left: wrap_if_json_arrow(op.left),
995 right: wrap_if_json_arrow(op.right),
996 ..*op
997 }))),
998 Expression::Or(op) => Ok(Expression::Or(Box::new(BinaryOp {
999 left: wrap_if_json_arrow(op.left),
1000 right: wrap_if_json_arrow(op.right),
1001 ..*op
1002 }))),
1003 Expression::Add(op) => Ok(Expression::Add(Box::new(BinaryOp {
1004 left: wrap_if_json_arrow(op.left),
1005 right: wrap_if_json_arrow(op.right),
1006 ..*op
1007 }))),
1008 Expression::Sub(op) => Ok(Expression::Sub(Box::new(BinaryOp {
1009 left: wrap_if_json_arrow(op.left),
1010 right: wrap_if_json_arrow(op.right),
1011 ..*op
1012 }))),
1013 Expression::Mul(op) => Ok(Expression::Mul(Box::new(BinaryOp {
1014 left: wrap_if_json_arrow(op.left),
1015 right: wrap_if_json_arrow(op.right),
1016 ..*op
1017 }))),
1018 Expression::Div(op) => Ok(Expression::Div(Box::new(BinaryOp {
1019 left: wrap_if_json_arrow(op.left),
1020 right: wrap_if_json_arrow(op.right),
1021 ..*op
1022 }))),
1023 Expression::Mod(op) => Ok(Expression::Mod(Box::new(BinaryOp {
1024 left: wrap_if_json_arrow(op.left),
1025 right: wrap_if_json_arrow(op.right),
1026 ..*op
1027 }))),
1028 Expression::Concat(op) => Ok(Expression::Concat(Box::new(BinaryOp {
1029 left: wrap_if_json_arrow(op.left),
1030 right: wrap_if_json_arrow(op.right),
1031 ..*op
1032 }))),
1033
1034 Expression::In(mut i) => {
1037 i.this = wrap_if_json_arrow(i.this);
1038 if i.not {
1039 i.not = false;
1041 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
1042 this: Expression::In(i),
1043 inferred_type: None,
1044 })))
1045 } else {
1046 Ok(Expression::In(i))
1047 }
1048 }
1049
1050 Expression::Not(mut n) => {
1052 n.this = wrap_if_json_arrow(n.this);
1053 Ok(Expression::Not(n))
1054 }
1055
1056 Expression::WithinGroup(wg) => {
1058 match &wg.this {
1059 Expression::ListAgg(listagg) => {
1060 let mut listagg = listagg.clone();
1061 listagg.order_by = Some(wg.order_by.clone());
1062 Ok(Expression::ListAgg(listagg))
1063 }
1064 Expression::PercentileCont(p) => {
1065 let column = wg
1066 .order_by
1067 .first()
1068 .map(|o| o.this.clone())
1069 .unwrap_or_else(|| p.this.clone());
1070 let percentile = p.percentile.clone();
1071 let filter = p.filter.clone();
1072 Ok(Expression::AggregateFunction(Box::new(
1073 crate::expressions::AggregateFunction {
1074 name: "QUANTILE_CONT".to_string(),
1075 args: vec![column, percentile],
1076 distinct: false,
1077 filter,
1078 order_by: wg.order_by,
1079 limit: None,
1080 ignore_nulls: None,
1081 inferred_type: None,
1082 },
1083 )))
1084 }
1085 Expression::PercentileDisc(p) => {
1086 let column = wg
1087 .order_by
1088 .first()
1089 .map(|o| o.this.clone())
1090 .unwrap_or_else(|| p.this.clone());
1091 let percentile = p.percentile.clone();
1092 let filter = p.filter.clone();
1093 Ok(Expression::AggregateFunction(Box::new(
1094 crate::expressions::AggregateFunction {
1095 name: "QUANTILE_DISC".to_string(),
1096 args: vec![column, percentile],
1097 distinct: false,
1098 filter,
1099 order_by: wg.order_by,
1100 limit: None,
1101 ignore_nulls: None,
1102 inferred_type: None,
1103 },
1104 )))
1105 }
1106 Expression::AggregateFunction(af)
1108 if af.name == "PERCENTILE_CONT" || af.name == "PERCENTILE_DISC" =>
1109 {
1110 let new_name = if af.name == "PERCENTILE_CONT" {
1111 "QUANTILE_CONT"
1112 } else {
1113 "QUANTILE_DISC"
1114 };
1115 let column = wg.order_by.first().map(|o| o.this.clone());
1116 let quantile = af.args.first().cloned();
1117 match (column, quantile) {
1118 (Some(col), Some(q)) => Ok(Expression::AggregateFunction(Box::new(
1119 crate::expressions::AggregateFunction {
1120 name: new_name.to_string(),
1121 args: vec![col, q],
1122 distinct: false,
1123 filter: af.filter.clone(),
1124 order_by: wg.order_by,
1125 limit: None,
1126 ignore_nulls: None,
1127 inferred_type: None,
1128 },
1129 ))),
1130 _ => Ok(Expression::WithinGroup(wg)),
1131 }
1132 }
1133 _ => Ok(Expression::WithinGroup(wg)),
1134 }
1135 }
1136
1137 Expression::Column(ref c) if c.name.name.starts_with('@') && c.table.is_none() => {
1141 let col_name = &c.name.name[1..]; Ok(Expression::Abs(Box::new(UnaryFunc {
1143 this: Expression::boxed_column(Column {
1144 name: Identifier::new(col_name),
1145 table: None,
1146 join_mark: false,
1147 trailing_comments: Vec::new(),
1148 span: None,
1149 inferred_type: None,
1150 }),
1151 original_name: None,
1152 inferred_type: None,
1153 })))
1154 }
1155
1156 Expression::Select(mut select) => {
1161 select.expressions = select
1162 .expressions
1163 .into_iter()
1164 .map(|e| {
1165 match e {
1166 Expression::JSONExtract(ref je) if je.variant_extract.is_some() => {
1167 let alias_ident = match je.this.as_ref() {
1169 Expression::Identifier(ident) => Some(ident.clone()),
1170 Expression::Column(col) if col.table.is_none() => {
1171 Some(col.name.clone())
1172 }
1173 _ => None,
1174 };
1175 let value_expr = match je.expression.as_ref() {
1176 Expression::Literal(lit)
1177 if matches!(lit.as_ref(), Literal::String(_)) =>
1178 {
1179 let Literal::String(s) = lit.as_ref() else {
1180 unreachable!()
1181 };
1182 if s.contains('.') {
1184 let parts: Vec<&str> = s.splitn(2, '.').collect();
1186 Some(Expression::boxed_column(Column {
1187 name: Identifier::new(parts[1]),
1188 table: Some(Identifier::new(parts[0])),
1189 join_mark: false,
1190 trailing_comments: Vec::new(),
1191 span: None,
1192 inferred_type: None,
1193 }))
1194 } else {
1195 Some(Expression::boxed_column(Column {
1196 name: Identifier::new(s.as_str()),
1197 table: None,
1198 join_mark: false,
1199 trailing_comments: Vec::new(),
1200 span: None,
1201 inferred_type: None,
1202 }))
1203 }
1204 }
1205 _ => None,
1206 };
1207
1208 if let (Some(alias), Some(value)) = (alias_ident, value_expr) {
1209 Expression::Alias(Box::new(Alias {
1210 this: value,
1211 alias,
1212 column_aliases: Vec::new(),
1213 alias_explicit_as: false,
1214 alias_keyword: None,
1215 pre_alias_comments: Vec::new(),
1216 trailing_comments: Vec::new(),
1217 inferred_type: None,
1218 }))
1219 } else {
1220 e
1221 }
1222 }
1223 _ => e,
1224 }
1225 })
1226 .collect();
1227
1228 if let Some(ref mut from) = select.from {
1231 if from.expressions.len() > 1 {
1232 let mut new_from_exprs = Vec::new();
1234 let mut new_joins = Vec::new();
1235
1236 for (idx, expr) in from.expressions.drain(..).enumerate() {
1237 if idx == 0 {
1238 new_from_exprs.push(expr);
1240 } else {
1241 let is_unnest = match &expr {
1243 Expression::Unnest(_) => true,
1244 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
1245 _ => false,
1246 };
1247
1248 if is_unnest {
1249 new_joins.push(crate::expressions::Join {
1251 this: expr,
1252 on: Some(Expression::Boolean(
1253 crate::expressions::BooleanLiteral { value: true },
1254 )),
1255 using: Vec::new(),
1256 kind: crate::expressions::JoinKind::Inner,
1257 use_inner_keyword: false,
1258 use_outer_keyword: false,
1259 deferred_condition: false,
1260 join_hint: None,
1261 match_condition: None,
1262 pivots: Vec::new(),
1263 comments: Vec::new(),
1264 nesting_group: 0,
1265 directed: false,
1266 });
1267 } else {
1268 new_from_exprs.push(expr);
1270 }
1271 }
1272 }
1273
1274 from.expressions = new_from_exprs;
1275
1276 new_joins.append(&mut select.joins);
1278 select.joins = new_joins;
1279 }
1280 }
1281
1282 Ok(Expression::Select(select))
1283 }
1284
1285 Expression::Interval(interval) => self.transform_interval(*interval),
1290
1291 Expression::CreateFunction(mut cf) => {
1293 cf.parameters = cf
1295 .parameters
1296 .into_iter()
1297 .map(|mut p| {
1298 if let Ok(Expression::DataType(new_dt)) =
1299 self.transform_data_type(p.data_type.clone())
1300 {
1301 p.data_type = new_dt;
1302 }
1303 p
1304 })
1305 .collect();
1306
1307 if cf.returns_table_body.is_some()
1311 && !matches!(&cf.return_type, Some(DataType::Custom { ref name }) if name == "TABLE")
1312 {
1313 cf.return_type = Some(DataType::Custom {
1314 name: "TABLE".to_string(),
1315 });
1316 cf.returns_table_body = None;
1317 }
1318
1319 Ok(Expression::CreateFunction(cf))
1320 }
1321
1322 Expression::IfFunc(f) => Ok(Expression::Case(Box::new(Case {
1326 operand: None,
1327 whens: vec![(f.condition, f.true_value)],
1328 else_: f.false_value,
1329 comments: Vec::new(),
1330 inferred_type: None,
1331 }))),
1332
1333 Expression::VarSamp(f) => Ok(Expression::Function(Box::new(Function::new(
1335 "VARIANCE".to_string(),
1336 vec![f.this],
1337 )))),
1338
1339 Expression::Nvl2(f) => {
1341 let condition = Expression::IsNull(Box::new(crate::expressions::IsNull {
1342 this: f.this,
1343 not: true,
1344 postfix_form: false,
1345 }));
1346 Ok(Expression::Case(Box::new(Case {
1347 operand: None,
1348 whens: vec![(condition, f.true_value)],
1349 else_: Some(f.false_value),
1350 comments: Vec::new(),
1351 inferred_type: None,
1352 })))
1353 }
1354
1355 _ => Ok(expr),
1357 }
1358 }
1359}
1360
1361#[cfg(feature = "transpile")]
1362impl DuckDBDialect {
1363 fn extract_number_value(expr: &Expression) -> Option<f64> {
1365 match expr {
1366 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
1367 let Literal::Number(n) = lit.as_ref() else {
1368 unreachable!()
1369 };
1370 n.parse::<f64>().ok()
1371 }
1372 _ => None,
1373 }
1374 }
1375
1376 fn expr_to_sql(expr: &Expression) -> String {
1378 crate::generator::Generator::sql(expr).unwrap_or_default()
1379 }
1380
1381 fn extract_seed_info(gen: &Expression) -> (String, bool) {
1387 match gen {
1388 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
1389 if func.args.is_empty() {
1390 ("RANDOM()".to_string(), true)
1391 } else {
1392 (Self::expr_to_sql(&func.args[0]), false)
1394 }
1395 }
1396 Expression::Rand(r) => {
1397 if let Some(ref seed) = r.seed {
1398 (Self::expr_to_sql(seed), false)
1400 } else {
1401 ("RANDOM()".to_string(), true)
1402 }
1403 }
1404 Expression::Random(_) => ("RANDOM()".to_string(), true),
1405 _ => (Self::expr_to_sql(gen), false),
1406 }
1407 }
1408
1409 fn parse_as_subquery(sql: &str) -> Result<Expression> {
1412 let sql_owned = sql.to_string();
1413 let handle = std::thread::Builder::new()
1414 .stack_size(16 * 1024 * 1024) .spawn(move || match crate::parser::Parser::parse_sql(&sql_owned) {
1416 Ok(stmts) => {
1417 if let Some(stmt) = stmts.into_iter().next() {
1418 Ok(Expression::Subquery(Box::new(Subquery {
1419 this: stmt,
1420 alias: None,
1421 column_aliases: Vec::new(),
1422 alias_explicit_as: false,
1423 alias_keyword: None,
1424 order_by: None,
1425 limit: None,
1426 offset: None,
1427 distribute_by: None,
1428 sort_by: None,
1429 cluster_by: None,
1430 lateral: false,
1431 modifiers_inside: false,
1432 trailing_comments: Vec::new(),
1433 inferred_type: None,
1434 })))
1435 } else {
1436 Err(crate::error::Error::Generate(
1437 "Failed to parse template SQL".to_string(),
1438 ))
1439 }
1440 }
1441 Err(e) => Err(e),
1442 })
1443 .map_err(|e| {
1444 crate::error::Error::Internal(format!("Failed to spawn parser thread: {}", e))
1445 })?;
1446
1447 handle
1448 .join()
1449 .map_err(|_| crate::error::Error::Internal("Parser thread panicked".to_string()))?
1450 }
1451
1452 fn normalize_empty_map_expr(expr: Expression) -> Expression {
1454 match expr {
1455 Expression::Cast(mut c) if matches!(&c.to, DataType::Map { .. }) => {
1456 if matches!(&c.this, Expression::Struct(s) if s.fields.is_empty()) {
1457 c.this =
1458 Expression::Function(Box::new(Function::new("MAP".to_string(), vec![])));
1459 }
1460 Expression::Cast(c)
1461 }
1462 other => other,
1463 }
1464 }
1465
1466 fn convert_bracket_to_quoted_path(path: &str) -> String {
1470 let mut result = String::new();
1471 let mut chars = path.chars().peekable();
1472 while let Some(c) = chars.next() {
1473 if c == '[' && chars.peek() == Some(&'"') {
1474 chars.next(); let mut key = String::new();
1477 while let Some(kc) = chars.next() {
1478 if kc == '"' && chars.peek() == Some(&']') {
1479 chars.next(); break;
1481 }
1482 key.push(kc);
1483 }
1484 if !result.is_empty() && !result.ends_with('.') {
1486 result.push('.');
1487 }
1488 result.push('"');
1489 result.push_str(&key);
1490 result.push('"');
1491 } else {
1492 result.push(c);
1493 }
1494 }
1495 result
1496 }
1497
1498 fn transform_data_type(&self, dt: crate::expressions::DataType) -> Result<Expression> {
1500 use crate::expressions::DataType;
1501 let transformed = match dt {
1502 DataType::Binary { length } => DataType::VarBinary { length },
1504 DataType::Blob => DataType::VarBinary { length: None },
1507 DataType::Char { .. } | DataType::VarChar { .. } => dt,
1509 DataType::Float {
1511 precision, scale, ..
1512 } => DataType::Float {
1513 precision,
1514 scale,
1515 real_spelling: true,
1516 },
1517 DataType::JsonB => DataType::Json,
1519 DataType::Custom { ref name } => {
1521 let upper = name.to_uppercase();
1522 match upper.as_str() {
1523 "INT64" | "INT8" => DataType::BigInt { length: None },
1525 "INT32" | "INT4" | "SIGNED" => DataType::Int {
1527 length: None,
1528 integer_spelling: false,
1529 },
1530 "INT16" => DataType::SmallInt { length: None },
1532 "INT1" => DataType::TinyInt { length: None },
1534 "HUGEINT" => DataType::Custom {
1536 name: "INT128".to_string(),
1537 },
1538 "UHUGEINT" => DataType::Custom {
1540 name: "UINT128".to_string(),
1541 },
1542 "BPCHAR" => DataType::Text,
1544 "CHARACTER VARYING" | "CHAR VARYING" => DataType::Text,
1546 "FLOAT4" => DataType::Custom {
1548 name: "REAL".to_string(),
1549 },
1550 "LOGICAL" => DataType::Boolean,
1552 "TIMESTAMPNTZ" | "TIMESTAMP_NTZ" => DataType::Timestamp {
1554 precision: None,
1555 timezone: false,
1556 },
1557 "TIMESTAMP_US" => DataType::Timestamp {
1559 precision: None,
1560 timezone: false,
1561 },
1562 "TIMESTAMPLTZ" | "TIMESTAMP_LTZ" | "TIMESTAMPTZ" | "TIMESTAMP_TZ" => {
1564 DataType::Timestamp {
1565 precision: None,
1566 timezone: true,
1567 }
1568 }
1569 "DECFLOAT" => DataType::Decimal {
1571 precision: Some(38),
1572 scale: Some(5),
1573 },
1574 _ => dt,
1576 }
1577 }
1578 other => other,
1580 };
1581 Ok(Expression::DataType(transformed))
1582 }
1583
1584 fn transform_interval(&self, interval: Interval) -> Result<Expression> {
1587 if interval.unit.is_some() {
1591 return Ok(Expression::Interval(Box::new(interval)));
1593 }
1594
1595 if let Some(Expression::Literal(ref lit)) = interval.this {
1596 if let Literal::String(ref s) = lit.as_ref() {
1597 if let Some((value, unit)) = Self::parse_interval_string(s) {
1599 return Ok(Expression::Interval(Box::new(Interval {
1601 this: Some(Expression::Literal(Box::new(Literal::String(
1602 value.to_string(),
1603 )))),
1604 unit: Some(IntervalUnitSpec::Simple {
1605 unit,
1606 use_plural: false, }),
1608 })));
1609 }
1610 }
1611 }
1612
1613 Ok(Expression::Interval(Box::new(interval)))
1615 }
1616
1617 fn parse_interval_string(s: &str) -> Option<(&str, IntervalUnit)> {
1620 let s = s.trim();
1621
1622 let mut num_end = 0;
1625 let mut chars = s.chars().peekable();
1626
1627 if chars.peek() == Some(&'-') {
1629 chars.next();
1630 num_end += 1;
1631 }
1632
1633 while let Some(&c) = chars.peek() {
1635 if c.is_ascii_digit() {
1636 chars.next();
1637 num_end += 1;
1638 } else {
1639 break;
1640 }
1641 }
1642
1643 if chars.peek() == Some(&'.') {
1645 chars.next();
1646 num_end += 1;
1647 while let Some(&c) = chars.peek() {
1648 if c.is_ascii_digit() {
1649 chars.next();
1650 num_end += 1;
1651 } else {
1652 break;
1653 }
1654 }
1655 }
1656
1657 if num_end == 0 || (num_end == 1 && s.starts_with('-')) {
1658 return None; }
1660
1661 let value = &s[..num_end];
1662 let rest = s[num_end..].trim();
1663
1664 if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_alphabetic()) {
1666 return None;
1667 }
1668
1669 let unit = match rest.to_uppercase().as_str() {
1671 "YEAR" | "YEARS" | "Y" => IntervalUnit::Year,
1672 "MONTH" | "MONTHS" | "MON" | "MONS" => IntervalUnit::Month,
1673 "DAY" | "DAYS" | "D" => IntervalUnit::Day,
1674 "HOUR" | "HOURS" | "H" | "HR" | "HRS" => IntervalUnit::Hour,
1675 "MINUTE" | "MINUTES" | "MIN" | "MINS" | "M" => IntervalUnit::Minute,
1676 "SECOND" | "SECONDS" | "SEC" | "SECS" | "S" => IntervalUnit::Second,
1677 "MILLISECOND" | "MILLISECONDS" | "MS" => IntervalUnit::Millisecond,
1678 "MICROSECOND" | "MICROSECONDS" | "US" => IntervalUnit::Microsecond,
1679 "QUARTER" | "QUARTERS" | "Q" => IntervalUnit::Quarter,
1680 "WEEK" | "WEEKS" | "W" => IntervalUnit::Week,
1681 _ => return None, };
1683
1684 Some((value, unit))
1685 }
1686
1687 fn transform_function(&self, f: Function) -> Result<Expression> {
1688 let name_upper = f.name.to_uppercase();
1689 match name_upper.as_str() {
1690 "FROM_HEX" if f.args.len() == 1 => {
1691 let mut args = f.args;
1692 Ok(Expression::Unhex(Box::new(Unhex {
1693 this: Box::new(args.remove(0)),
1694 expression: None,
1695 })))
1696 }
1697
1698 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1700 original_name: None,
1701 expressions: f.args,
1702 inferred_type: None,
1703 }))),
1704
1705 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1707 original_name: None,
1708 expressions: f.args,
1709 inferred_type: None,
1710 }))),
1711
1712 "ISNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1714 original_name: None,
1715 expressions: f.args,
1716 inferred_type: None,
1717 }))),
1718
1719 "ARRAY_COMPACT" if f.args.len() == 1 => {
1721 let arr = f.args.into_iter().next().unwrap();
1722 let lambda = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
1723 parameters: vec![Identifier::new("_u".to_string())],
1724 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
1725 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
1726 this: Expression::boxed_column(Column {
1727 table: None,
1728 name: Identifier::new("_u".to_string()),
1729 join_mark: false,
1730 trailing_comments: Vec::new(),
1731 span: None,
1732 inferred_type: None,
1733 }),
1734 not: false,
1735 postfix_form: false,
1736 })),
1737 inferred_type: None,
1738 })),
1739 colon: false,
1740 parameter_types: Vec::new(),
1741 }));
1742 Ok(Expression::Function(Box::new(Function::new(
1743 "LIST_FILTER".to_string(),
1744 vec![arr, lambda],
1745 ))))
1746 }
1747
1748 "ARRAY_CONSTRUCT_COMPACT" => Ok(Expression::Function(Box::new(f))),
1750
1751 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1753 Function::new("LISTAGG".to_string(), f.args),
1754 ))),
1755
1756 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
1758
1759 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1761 Function::new("LISTAGG".to_string(), f.args),
1762 ))),
1763
1764 "ARRAY_UNIQUE_AGG" if f.args.len() == 1 => {
1766 let col = f.args.into_iter().next().unwrap();
1767 let filter_expr = Expression::Not(Box::new(UnaryOp {
1769 this: Expression::IsNull(Box::new(IsNull {
1770 this: col.clone(),
1771 not: false,
1772 postfix_form: false,
1773 })),
1774 inferred_type: None,
1775 }));
1776 Ok(Expression::ArrayAgg(Box::new(AggFunc {
1777 this: col,
1778 distinct: true,
1779 filter: Some(filter_expr),
1780 order_by: Vec::new(),
1781 name: Some("LIST".to_string()),
1782 ignore_nulls: None,
1783 having_max: None,
1784 limit: None,
1785 inferred_type: None,
1786 })))
1787 }
1788
1789 "CHECK_JSON" if f.args.len() == 1 => {
1791 let x = f.args.into_iter().next().unwrap();
1792 let is_null = Expression::IsNull(Box::new(IsNull {
1794 this: x.clone(),
1795 not: false,
1796 postfix_form: false,
1797 }));
1798 let eq_empty = Expression::Eq(Box::new(BinaryOp::new(
1800 x.clone(),
1801 Expression::Literal(Box::new(Literal::String(String::new()))),
1802 )));
1803 let json_valid = Expression::Function(Box::new(Function::new(
1805 "JSON_VALID".to_string(),
1806 vec![x],
1807 )));
1808 let or1 = Expression::Or(Box::new(BinaryOp::new(is_null, eq_empty)));
1810 let condition = Expression::Or(Box::new(BinaryOp::new(or1, json_valid)));
1812 Ok(Expression::Case(Box::new(Case {
1813 operand: None,
1814 whens: vec![(condition, Expression::Null(Null))],
1815 else_: Some(Expression::Literal(Box::new(Literal::String(
1816 "Invalid JSON".to_string(),
1817 )))),
1818 comments: Vec::new(),
1819 inferred_type: None,
1820 })))
1821 }
1822
1823 "SUBSTR" => Ok(Expression::Function(Box::new(f))),
1825
1826 "FLATTEN" => Ok(Expression::Function(Box::new(Function::new(
1828 "UNNEST".to_string(),
1829 f.args,
1830 )))),
1831
1832 "ARRAY_FLATTEN" => Ok(Expression::Function(Box::new(Function::new(
1834 "FLATTEN".to_string(),
1835 f.args,
1836 )))),
1837
1838 "RPAD" if f.args.len() == 2 => {
1840 let mut args = f.args;
1841 args.push(Expression::Literal(Box::new(Literal::String(
1842 " ".to_string(),
1843 ))));
1844 Ok(Expression::Function(Box::new(Function::new(
1845 "RPAD".to_string(),
1846 args,
1847 ))))
1848 }
1849
1850 "BASE64_DECODE_STRING" => {
1853 let mut args = f.args;
1854 let input = args.remove(0);
1855 let has_alphabet = !args.is_empty();
1856 let decoded_input = if has_alphabet {
1857 let r1 = Expression::Function(Box::new(Function::new(
1859 "REPLACE".to_string(),
1860 vec![
1861 input,
1862 Expression::Literal(Box::new(Literal::String("-".to_string()))),
1863 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1864 ],
1865 )));
1866 let r2 = Expression::Function(Box::new(Function::new(
1867 "REPLACE".to_string(),
1868 vec![
1869 r1,
1870 Expression::Literal(Box::new(Literal::String("_".to_string()))),
1871 Expression::Literal(Box::new(Literal::String("/".to_string()))),
1872 ],
1873 )));
1874 Expression::Function(Box::new(Function::new(
1875 "REPLACE".to_string(),
1876 vec![
1877 r2,
1878 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1879 Expression::Literal(Box::new(Literal::String("=".to_string()))),
1880 ],
1881 )))
1882 } else {
1883 input
1884 };
1885 let from_base64 = Expression::Function(Box::new(Function::new(
1886 "FROM_BASE64".to_string(),
1887 vec![decoded_input],
1888 )));
1889 Ok(Expression::Function(Box::new(Function::new(
1890 "DECODE".to_string(),
1891 vec![from_base64],
1892 ))))
1893 }
1894
1895 "BASE64_DECODE_BINARY" => {
1898 let mut args = f.args;
1899 let input = args.remove(0);
1900 let has_alphabet = !args.is_empty();
1901 let decoded_input = if has_alphabet {
1902 let r1 = Expression::Function(Box::new(Function::new(
1903 "REPLACE".to_string(),
1904 vec![
1905 input,
1906 Expression::Literal(Box::new(Literal::String("-".to_string()))),
1907 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1908 ],
1909 )));
1910 let r2 = Expression::Function(Box::new(Function::new(
1911 "REPLACE".to_string(),
1912 vec![
1913 r1,
1914 Expression::Literal(Box::new(Literal::String("_".to_string()))),
1915 Expression::Literal(Box::new(Literal::String("/".to_string()))),
1916 ],
1917 )));
1918 Expression::Function(Box::new(Function::new(
1919 "REPLACE".to_string(),
1920 vec![
1921 r2,
1922 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1923 Expression::Literal(Box::new(Literal::String("=".to_string()))),
1924 ],
1925 )))
1926 } else {
1927 input
1928 };
1929 Ok(Expression::Function(Box::new(Function::new(
1930 "FROM_BASE64".to_string(),
1931 vec![decoded_input],
1932 ))))
1933 }
1934
1935 "SPACE" if f.args.len() == 1 => {
1937 let arg = f.args.into_iter().next().unwrap();
1938 let cast_arg = Expression::Cast(Box::new(Cast {
1939 this: arg,
1940 to: DataType::BigInt { length: None },
1941 trailing_comments: Vec::new(),
1942 double_colon_syntax: false,
1943 format: None,
1944 default: None,
1945 inferred_type: None,
1946 }));
1947 Ok(Expression::Function(Box::new(Function::new(
1948 "REPEAT".to_string(),
1949 vec![
1950 Expression::Literal(Box::new(Literal::String(" ".to_string()))),
1951 cast_arg,
1952 ],
1953 ))))
1954 }
1955
1956 "IS_ARRAY" if f.args.len() == 1 => {
1958 let arg = f.args.into_iter().next().unwrap();
1959 let json_type = Expression::Function(Box::new(Function::new(
1960 "JSON_TYPE".to_string(),
1961 vec![arg],
1962 )));
1963 Ok(Expression::Eq(Box::new(BinaryOp {
1964 left: json_type,
1965 right: Expression::Literal(Box::new(Literal::String("ARRAY".to_string()))),
1966 left_comments: Vec::new(),
1967 operator_comments: Vec::new(),
1968 trailing_comments: Vec::new(),
1969 inferred_type: None,
1970 })))
1971 }
1972
1973 "EXPLODE" => Ok(Expression::Function(Box::new(Function::new(
1975 "UNNEST".to_string(),
1976 f.args,
1977 )))),
1978
1979 "GETDATE" => Ok(Expression::CurrentTimestamp(
1981 crate::expressions::CurrentTimestamp {
1982 precision: None,
1983 sysdate: false,
1984 },
1985 )),
1986
1987 "TODAY" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1989
1990 "CURDATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1992
1993 "GET_CURRENT_TIME" => Ok(Expression::CurrentTime(crate::expressions::CurrentTime {
1995 precision: None,
1996 })),
1997
1998 "CURRENT_LOCALTIMESTAMP" => Ok(Expression::Localtimestamp(Box::new(
2000 crate::expressions::Localtimestamp { this: None },
2001 ))),
2002
2003 "REGEXP_EXTRACT_ALL" if f.args.len() == 3 => {
2005 if matches!(&f.args[2], Expression::Literal(lit) if matches!(lit.as_ref(), crate::expressions::Literal::Number(n) if n == "0"))
2007 {
2008 Ok(Expression::Function(Box::new(Function::new(
2009 "REGEXP_EXTRACT_ALL".to_string(),
2010 vec![f.args[0].clone(), f.args[1].clone()],
2011 ))))
2012 } else {
2013 Ok(Expression::Function(Box::new(Function::new(
2014 "REGEXP_EXTRACT_ALL".to_string(),
2015 f.args,
2016 ))))
2017 }
2018 }
2019
2020 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
2022
2023 "TO_DATE" if f.args.len() == 1 => {
2025 let arg = f.args.into_iter().next().unwrap();
2026 Ok(Expression::Cast(Box::new(Cast {
2027 this: arg,
2028 to: DataType::Date,
2029 trailing_comments: Vec::new(),
2030 double_colon_syntax: false,
2031 format: None,
2032 default: None,
2033 inferred_type: None,
2034 })))
2035 }
2036
2037 "DATE_FORMAT" if f.args.len() >= 2 => {
2041 let mut args = f.args;
2042 args[1] = Self::convert_format_to_duckdb(&args[1]);
2043 Ok(Expression::Function(Box::new(Function::new(
2044 "STRFTIME".to_string(),
2045 args,
2046 ))))
2047 }
2048
2049 "DATE_PARSE" if f.args.len() >= 2 => {
2051 let mut args = f.args;
2052 args[1] = Self::convert_format_to_duckdb(&args[1]);
2053 Ok(Expression::Function(Box::new(Function::new(
2054 "STRPTIME".to_string(),
2055 args,
2056 ))))
2057 }
2058
2059 "FORMAT_DATE" if f.args.len() >= 2 => {
2061 let mut args = f.args;
2062 args[1] = Self::convert_format_to_duckdb(&args[1]);
2063 Ok(Expression::Function(Box::new(Function::new(
2064 "STRFTIME".to_string(),
2065 args,
2066 ))))
2067 }
2068
2069 "TO_CHAR" if f.args.len() >= 2 => {
2071 let mut args = f.args;
2072 args[1] = Self::convert_format_to_duckdb(&args[1]);
2073 Ok(Expression::Function(Box::new(Function::new(
2074 "STRFTIME".to_string(),
2075 args,
2076 ))))
2077 }
2078
2079 "EPOCH_MS" => Ok(Expression::Function(Box::new(f))),
2081
2082 "EPOCH" => Ok(Expression::Function(Box::new(f))),
2084
2085 "FROM_UNIXTIME" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
2087 Function::new("TO_TIMESTAMP".to_string(), f.args),
2088 ))),
2089
2090 "UNIX_TIMESTAMP" => Ok(Expression::Function(Box::new(Function::new(
2092 "EPOCH".to_string(),
2093 f.args,
2094 )))),
2095
2096 "JSON_EXTRACT" if f.args.len() == 2 => {
2098 let mut args = f.args;
2099 let path = args.pop().unwrap();
2100 let this = args.pop().unwrap();
2101 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2102 this,
2103 path,
2104 returning: None,
2105 arrow_syntax: true,
2106 hash_arrow_syntax: false,
2107 wrapper_option: None,
2108 quotes_option: None,
2109 on_scalar_string: false,
2110 on_error: None,
2111 })))
2112 }
2113
2114 "JSON_EXTRACT_STRING" if f.args.len() == 2 => {
2116 let mut args = f.args;
2117 let path = args.pop().unwrap();
2118 let this = args.pop().unwrap();
2119 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
2120 this,
2121 path,
2122 returning: None,
2123 arrow_syntax: true,
2124 hash_arrow_syntax: false,
2125 wrapper_option: None,
2126 quotes_option: None,
2127 on_scalar_string: false,
2128 on_error: None,
2129 })))
2130 }
2131
2132 "ARRAY_CONSTRUCT" => Ok(Expression::Function(Box::new(Function::new(
2134 "list_value".to_string(),
2135 f.args,
2136 )))),
2137
2138 "ARRAY" => {
2141 let has_query = f
2143 .args
2144 .iter()
2145 .any(|a| matches!(a, Expression::Subquery(_) | Expression::Select(_)));
2146 if has_query {
2147 Ok(Expression::Function(Box::new(Function::new(
2149 "ARRAY".to_string(),
2150 f.args,
2151 ))))
2152 } else {
2153 Ok(Expression::Function(Box::new(Function::new(
2154 "list_value".to_string(),
2155 f.args,
2156 ))))
2157 }
2158 }
2159
2160 "LIST_VALUE" => Ok(Expression::Array(Box::new(crate::expressions::Array {
2162 expressions: f.args,
2163 }))),
2164
2165 "ARRAY_AGG" => Ok(Expression::Function(Box::new(Function::new(
2167 "list".to_string(),
2168 f.args,
2169 )))),
2170
2171 "LIST_CONTAINS" | "ARRAY_CONTAINS" => Ok(Expression::Function(Box::new(
2173 Function::new("ARRAY_CONTAINS".to_string(), f.args),
2174 ))),
2175
2176 "ARRAY_SIZE" | "CARDINALITY" => Ok(Expression::Function(Box::new(Function::new(
2178 "ARRAY_LENGTH".to_string(),
2179 f.args,
2180 )))),
2181
2182 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
2184 f.args.into_iter().next().unwrap(),
2185 )))),
2186
2187 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
2189 this: f.args.into_iter().next().unwrap(),
2190 decimals: None,
2191 to: None,
2192 }))),
2193
2194 "LOGICAL_OR" if f.args.len() == 1 => {
2196 let arg = f.args.into_iter().next().unwrap();
2197 Ok(Expression::Function(Box::new(Function::new(
2198 "BOOL_OR".to_string(),
2199 vec![Expression::Cast(Box::new(crate::expressions::Cast {
2200 this: arg,
2201 to: crate::expressions::DataType::Boolean,
2202 trailing_comments: Vec::new(),
2203 double_colon_syntax: false,
2204 format: None,
2205 default: None,
2206 inferred_type: None,
2207 }))],
2208 ))))
2209 }
2210
2211 "LOGICAL_AND" if f.args.len() == 1 => {
2213 let arg = f.args.into_iter().next().unwrap();
2214 Ok(Expression::Function(Box::new(Function::new(
2215 "BOOL_AND".to_string(),
2216 vec![Expression::Cast(Box::new(crate::expressions::Cast {
2217 this: arg,
2218 to: crate::expressions::DataType::Boolean,
2219 trailing_comments: Vec::new(),
2220 double_colon_syntax: false,
2221 format: None,
2222 default: None,
2223 inferred_type: None,
2224 }))],
2225 ))))
2226 }
2227
2228 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(Function::new(
2230 "REGEXP_MATCHES".to_string(),
2231 f.args,
2232 )))),
2233
2234 "POSITION" => Ok(Expression::Function(Box::new(f))),
2236
2237 "CHARINDEX" if f.args.len() == 2 => {
2239 let mut args = f.args;
2240 let substr = args.remove(0);
2241 let str_expr = args.remove(0);
2242 Ok(Expression::Function(Box::new(Function::new(
2243 "STRPOS".to_string(),
2244 vec![str_expr, substr],
2245 ))))
2246 }
2247
2248 "CHARINDEX" if f.args.len() == 3 => {
2254 let mut args = f.args;
2255 let substr = args.remove(0);
2256 let str_expr = args.remove(0);
2257 let pos = args.remove(0);
2258
2259 let zero = Expression::Literal(Box::new(Literal::Number("0".to_string())));
2260 let one = Expression::Literal(Box::new(Literal::Number("1".to_string())));
2261
2262 let pos_case = Expression::Case(Box::new(Case {
2264 operand: None,
2265 whens: vec![(
2266 Expression::Lte(Box::new(BinaryOp::new(pos.clone(), zero.clone()))),
2267 one.clone(),
2268 )],
2269 else_: Some(pos.clone()),
2270 comments: Vec::new(),
2271 inferred_type: None,
2272 }));
2273
2274 let substring_expr = Expression::Substring(Box::new(SubstringFunc {
2276 this: str_expr,
2277 start: pos_case.clone(),
2278 length: None,
2279 from_for_syntax: false,
2280 }));
2281
2282 let strpos = Expression::Function(Box::new(Function::new(
2284 "STRPOS".to_string(),
2285 vec![substring_expr, substr],
2286 )));
2287
2288 let eq_zero = Expression::Eq(Box::new(BinaryOp::new(strpos.clone(), zero.clone())));
2290
2291 let add_pos = Expression::Add(Box::new(BinaryOp::new(strpos, pos_case)));
2293 let sub_one = Expression::Sub(Box::new(BinaryOp::new(add_pos, one)));
2294
2295 Ok(Expression::Case(Box::new(Case {
2296 operand: None,
2297 whens: vec![(eq_zero, zero)],
2298 else_: Some(sub_one),
2299 comments: Vec::new(),
2300 inferred_type: None,
2301 })))
2302 }
2303
2304 "SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2306 "STR_SPLIT".to_string(),
2307 f.args,
2308 )))),
2309
2310 "STRING_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2312 "STR_SPLIT".to_string(),
2313 f.args,
2314 )))),
2315
2316 "STRTOK_TO_ARRAY" => Ok(Expression::Function(Box::new(Function::new(
2318 "STR_SPLIT".to_string(),
2319 f.args,
2320 )))),
2321
2322 "REGEXP_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2324 "STR_SPLIT_REGEX".to_string(),
2325 f.args,
2326 )))),
2327
2328 "EDITDIST3" => Ok(Expression::Function(Box::new(Function::new(
2330 "LEVENSHTEIN".to_string(),
2331 f.args,
2332 )))),
2333
2334 "JSON_EXTRACT_PATH" if f.args.len() >= 2 => {
2336 let mut args = f.args;
2337 let this = args.remove(0);
2338 let path = args.remove(0);
2339 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2340 this,
2341 path,
2342 returning: None,
2343 arrow_syntax: true,
2344 hash_arrow_syntax: false,
2345 wrapper_option: None,
2346 quotes_option: None,
2347 on_scalar_string: false,
2348 on_error: None,
2349 })))
2350 }
2351
2352 "JSON_EXTRACT_PATH_TEXT" if f.args.len() >= 2 => {
2354 let mut args = f.args;
2355 let this = args.remove(0);
2356 let path = args.remove(0);
2357 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
2358 this,
2359 path,
2360 returning: None,
2361 arrow_syntax: true,
2362 hash_arrow_syntax: false,
2363 wrapper_option: None,
2364 quotes_option: None,
2365 on_scalar_string: false,
2366 on_error: None,
2367 })))
2368 }
2369
2370 "DATE_ADD" if f.args.len() == 2 => {
2372 let mut args = f.args;
2373 let date = args.remove(0);
2374 let interval = args.remove(0);
2375 Ok(Expression::Add(Box::new(BinaryOp {
2376 left: date,
2377 right: interval,
2378 left_comments: Vec::new(),
2379 operator_comments: Vec::new(),
2380 trailing_comments: Vec::new(),
2381 inferred_type: None,
2382 })))
2383 }
2384
2385 "DATE_SUB" if f.args.len() == 2 => {
2387 let mut args = f.args;
2388 let date = args.remove(0);
2389 let interval = args.remove(0);
2390 Ok(Expression::Sub(Box::new(BinaryOp {
2391 left: date,
2392 right: interval,
2393 left_comments: Vec::new(),
2394 operator_comments: Vec::new(),
2395 trailing_comments: Vec::new(),
2396 inferred_type: None,
2397 })))
2398 }
2399
2400 "RANGE" if f.args.len() == 1 => {
2402 let mut new_args = vec![Expression::number(0)];
2403 new_args.extend(f.args);
2404 Ok(Expression::Function(Box::new(Function::new(
2405 "RANGE".to_string(),
2406 new_args,
2407 ))))
2408 }
2409
2410 "GENERATE_SERIES" if f.args.len() == 1 => {
2412 let mut new_args = vec![Expression::number(0)];
2413 new_args.extend(f.args);
2414 Ok(Expression::Function(Box::new(Function::new(
2415 "GENERATE_SERIES".to_string(),
2416 new_args,
2417 ))))
2418 }
2419
2420 "REGEXP_EXTRACT" if f.args.len() == 3 => {
2423 let drop_group = match &f.args[2] {
2425 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
2426 let Literal::Number(n) = lit.as_ref() else {
2427 unreachable!()
2428 };
2429 n == "0"
2430 }
2431 _ => false,
2432 };
2433 if drop_group {
2434 Ok(Expression::Function(Box::new(Function::new(
2435 "REGEXP_EXTRACT".to_string(),
2436 vec![f.args[0].clone(), f.args[1].clone()],
2437 ))))
2438 } else {
2439 Ok(Expression::Function(Box::new(f)))
2440 }
2441 }
2442
2443 "STRUCT_PACK" => {
2445 let mut fields = Vec::new();
2446 for arg in f.args {
2447 match arg {
2448 Expression::NamedArgument(na) => {
2449 fields.push((Some(na.name.name.clone()), na.value));
2450 }
2451 other => {
2453 fields.push((None, other));
2454 }
2455 }
2456 }
2457 Ok(Expression::Struct(Box::new(Struct { fields })))
2458 }
2459
2460 "REPLACE" if f.args.len() == 2 => {
2462 let mut args = f.args;
2463 args.push(Expression::Literal(Box::new(
2464 Literal::String(String::new()),
2465 )));
2466 Ok(Expression::Function(Box::new(Function::new(
2467 "REPLACE".to_string(),
2468 args,
2469 ))))
2470 }
2471
2472 "TO_UNIXTIME" => Ok(Expression::Function(Box::new(Function::new(
2474 "EPOCH".to_string(),
2475 f.args,
2476 )))),
2477
2478 "FROM_ISO8601_TIMESTAMP" if f.args.len() == 1 => {
2480 use crate::expressions::{Cast, DataType};
2481 Ok(Expression::Cast(Box::new(Cast {
2482 this: f.args.into_iter().next().unwrap(),
2483 to: DataType::Timestamp {
2484 precision: None,
2485 timezone: true,
2486 },
2487 trailing_comments: Vec::new(),
2488 double_colon_syntax: false,
2489 format: None,
2490 default: None,
2491 inferred_type: None,
2492 })))
2493 }
2494
2495 "APPROX_DISTINCT" => {
2497 let args = if f.args.len() > 1 {
2499 vec![f.args.into_iter().next().unwrap()]
2500 } else {
2501 f.args
2502 };
2503 Ok(Expression::Function(Box::new(Function::new(
2504 "APPROX_COUNT_DISTINCT".to_string(),
2505 args,
2506 ))))
2507 }
2508
2509 "ARRAY_SORT" => {
2511 let args = vec![f.args.into_iter().next().unwrap()];
2512 Ok(Expression::Function(Box::new(Function::new(
2513 "ARRAY_SORT".to_string(),
2514 args,
2515 ))))
2516 }
2517
2518 "TO_UTF8" => Ok(Expression::Function(Box::new(Function::new(
2520 "ENCODE".to_string(),
2521 f.args,
2522 )))),
2523
2524 "FROM_UTF8" => Ok(Expression::Function(Box::new(Function::new(
2526 "DECODE".to_string(),
2527 f.args,
2528 )))),
2529
2530 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
2532 "ANY_VALUE".to_string(),
2533 f.args,
2534 )))),
2535
2536 "MAX_BY" => Ok(Expression::Function(Box::new(Function::new(
2538 "ARG_MAX".to_string(),
2539 f.args,
2540 )))),
2541
2542 "MIN_BY" => Ok(Expression::Function(Box::new(Function::new(
2544 "ARG_MIN".to_string(),
2545 f.args,
2546 )))),
2547
2548 "IFF" if f.args.len() == 3 => {
2550 let mut args = f.args;
2551 let cond = args.remove(0);
2552 let true_val = args.remove(0);
2553 let false_val = args.remove(0);
2554 Ok(Expression::Case(Box::new(Case {
2555 operand: None,
2556 whens: vec![(cond, true_val)],
2557 else_: Some(false_val),
2558 comments: Vec::new(),
2559 inferred_type: None,
2560 })))
2561 }
2562 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
2563 "SKEWNESS".to_string(),
2564 f.args,
2565 )))),
2566 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2567 "VARIANCE".to_string(),
2568 f.args,
2569 )))),
2570 "VARIANCE_POP" => Ok(Expression::Function(Box::new(Function::new(
2571 "VAR_POP".to_string(),
2572 f.args,
2573 )))),
2574 "REGR_VALX" if f.args.len() == 2 => {
2575 let mut args = f.args;
2576 let y = args.remove(0);
2577 let x = args.remove(0);
2578 Ok(Expression::Case(Box::new(Case {
2579 operand: None,
2580 whens: vec![(
2581 Expression::IsNull(Box::new(crate::expressions::IsNull {
2582 this: y,
2583 not: false,
2584 postfix_form: false,
2585 })),
2586 Expression::Cast(Box::new(Cast {
2587 this: Expression::Null(crate::expressions::Null),
2588 to: DataType::Double {
2589 precision: None,
2590 scale: None,
2591 },
2592 trailing_comments: Vec::new(),
2593 double_colon_syntax: false,
2594 format: None,
2595 default: None,
2596 inferred_type: None,
2597 })),
2598 )],
2599 else_: Some(x),
2600 comments: Vec::new(),
2601 inferred_type: None,
2602 })))
2603 }
2604 "REGR_VALY" if f.args.len() == 2 => {
2605 let mut args = f.args;
2606 let y = args.remove(0);
2607 let x = args.remove(0);
2608 Ok(Expression::Case(Box::new(Case {
2609 operand: None,
2610 whens: vec![(
2611 Expression::IsNull(Box::new(crate::expressions::IsNull {
2612 this: x,
2613 not: false,
2614 postfix_form: false,
2615 })),
2616 Expression::Cast(Box::new(Cast {
2617 this: Expression::Null(crate::expressions::Null),
2618 to: DataType::Double {
2619 precision: None,
2620 scale: None,
2621 },
2622 trailing_comments: Vec::new(),
2623 double_colon_syntax: false,
2624 format: None,
2625 default: None,
2626 inferred_type: None,
2627 })),
2628 )],
2629 else_: Some(y),
2630 comments: Vec::new(),
2631 inferred_type: None,
2632 })))
2633 }
2634 "BOOLNOT" if f.args.len() == 1 => {
2635 let arg = f.args.into_iter().next().unwrap();
2636 let rounded = Expression::Function(Box::new(Function::new(
2638 "ROUND".to_string(),
2639 vec![arg, Expression::number(0)],
2640 )));
2641 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
2642 this: Expression::Paren(Box::new(Paren {
2643 this: rounded,
2644 trailing_comments: Vec::new(),
2645 })),
2646 inferred_type: None,
2647 })))
2648 }
2649 "BITMAP_BIT_POSITION" if f.args.len() == 1 => {
2650 let n = f.args.into_iter().next().unwrap();
2651 let case_expr = Expression::Case(Box::new(Case {
2652 operand: None,
2653 whens: vec![(
2654 Expression::Gt(Box::new(BinaryOp {
2655 left: n.clone(),
2656 right: Expression::number(0),
2657 left_comments: Vec::new(),
2658 operator_comments: Vec::new(),
2659 trailing_comments: Vec::new(),
2660 inferred_type: None,
2661 })),
2662 Expression::Sub(Box::new(BinaryOp {
2663 left: n.clone(),
2664 right: Expression::number(1),
2665 left_comments: Vec::new(),
2666 operator_comments: Vec::new(),
2667 trailing_comments: Vec::new(),
2668 inferred_type: None,
2669 })),
2670 )],
2671 else_: Some(Expression::Abs(Box::new(UnaryFunc {
2672 this: n,
2673 original_name: None,
2674 inferred_type: None,
2675 }))),
2676 comments: Vec::new(),
2677 inferred_type: None,
2678 }));
2679 Ok(Expression::Mod(Box::new(BinaryOp {
2680 left: Expression::Paren(Box::new(Paren {
2681 this: case_expr,
2682 trailing_comments: Vec::new(),
2683 })),
2684 right: Expression::number(32768),
2685 left_comments: Vec::new(),
2686 operator_comments: Vec::new(),
2687 trailing_comments: Vec::new(),
2688 inferred_type: None,
2689 })))
2690 }
2691 "GREATEST" | "LEAST" => Ok(Expression::Function(Box::new(f))),
2693 "GREATEST_IGNORE_NULLS" => Ok(Expression::Greatest(Box::new(VarArgFunc {
2694 expressions: f.args,
2695 original_name: None,
2696 inferred_type: None,
2697 }))),
2698 "LEAST_IGNORE_NULLS" => Ok(Expression::Least(Box::new(VarArgFunc {
2699 expressions: f.args,
2700 original_name: None,
2701 inferred_type: None,
2702 }))),
2703 "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
2704 "JSON".to_string(),
2705 f.args,
2706 )))),
2707 "TRY_PARSE_JSON" if f.args.len() == 1 => {
2709 let x = f.args.into_iter().next().unwrap();
2710 let json_valid = Expression::Function(Box::new(Function::new(
2711 "JSON_VALID".to_string(),
2712 vec![x.clone()],
2713 )));
2714 let cast_json = Expression::Cast(Box::new(crate::expressions::Cast {
2715 this: x,
2716 to: DataType::Json,
2717 double_colon_syntax: false,
2718 trailing_comments: Vec::new(),
2719 format: None,
2720 default: None,
2721 inferred_type: None,
2722 }));
2723 Ok(Expression::Case(Box::new(crate::expressions::Case {
2724 operand: None,
2725 whens: vec![(json_valid, cast_json)],
2726 else_: Some(Expression::Null(crate::expressions::Null)),
2727 comments: Vec::new(),
2728 inferred_type: None,
2729 })))
2730 }
2731 "OBJECT_CONSTRUCT_KEEP_NULL" => {
2732 Ok(Expression::Function(Box::new(Function::new(
2734 "JSON_OBJECT".to_string(),
2735 f.args,
2736 ))))
2737 }
2738 "OBJECT_CONSTRUCT" => {
2739 let args = f.args;
2741 if args.is_empty() {
2742 Ok(Expression::Function(Box::new(Function::new(
2744 "STRUCT_PACK".to_string(),
2745 vec![],
2746 ))))
2747 } else {
2748 let mut fields = Vec::new();
2750 let mut i = 0;
2751 while i + 1 < args.len() {
2752 let key = &args[i];
2753 let value = args[i + 1].clone();
2754 let key_name = match key {
2755 Expression::Literal(lit)
2756 if matches!(lit.as_ref(), Literal::String(_)) =>
2757 {
2758 let Literal::String(s) = lit.as_ref() else {
2759 unreachable!()
2760 };
2761 Some(s.clone())
2762 }
2763 _ => None,
2764 };
2765 fields.push((key_name, value));
2766 i += 2;
2767 }
2768 Ok(Expression::Struct(Box::new(Struct { fields })))
2769 }
2770 }
2771 "IS_NULL_VALUE" if f.args.len() == 1 => {
2772 let arg = f.args.into_iter().next().unwrap();
2773 Ok(Expression::Eq(Box::new(BinaryOp {
2774 left: Expression::Function(Box::new(Function::new(
2775 "JSON_TYPE".to_string(),
2776 vec![arg],
2777 ))),
2778 right: Expression::Literal(Box::new(Literal::String("NULL".to_string()))),
2779 left_comments: Vec::new(),
2780 operator_comments: Vec::new(),
2781 trailing_comments: Vec::new(),
2782 inferred_type: None,
2783 })))
2784 }
2785 "TRY_TO_DOUBLE" | "TRY_TO_NUMBER" | "TRY_TO_NUMERIC" | "TRY_TO_DECIMAL"
2786 if f.args.len() == 1 =>
2787 {
2788 let arg = f.args.into_iter().next().unwrap();
2789 Ok(Expression::TryCast(Box::new(Cast {
2790 this: arg,
2791 to: DataType::Double {
2792 precision: None,
2793 scale: None,
2794 },
2795 trailing_comments: Vec::new(),
2796 double_colon_syntax: false,
2797 format: None,
2798 default: None,
2799 inferred_type: None,
2800 })))
2801 }
2802 "TRY_TO_TIME" if f.args.len() == 1 => {
2803 let arg = f.args.into_iter().next().unwrap();
2804 Ok(Expression::TryCast(Box::new(Cast {
2805 this: arg,
2806 to: DataType::Time {
2807 precision: None,
2808 timezone: false,
2809 },
2810 trailing_comments: Vec::new(),
2811 double_colon_syntax: false,
2812 format: None,
2813 default: None,
2814 inferred_type: None,
2815 })))
2816 }
2817 "TRY_TO_TIME" if f.args.len() == 2 => {
2818 let mut args = f.args;
2819 let value = args.remove(0);
2820 let fmt = self.convert_snowflake_time_format(args.remove(0));
2821 Ok(Expression::TryCast(Box::new(Cast {
2822 this: Expression::Function(Box::new(Function::new(
2823 "TRY_STRPTIME".to_string(),
2824 vec![value, fmt],
2825 ))),
2826 to: DataType::Time {
2827 precision: None,
2828 timezone: false,
2829 },
2830 trailing_comments: Vec::new(),
2831 double_colon_syntax: false,
2832 format: None,
2833 default: None,
2834 inferred_type: None,
2835 })))
2836 }
2837 "TRY_TO_TIMESTAMP" if f.args.len() == 1 => {
2838 let arg = f.args.into_iter().next().unwrap();
2839 Ok(Expression::TryCast(Box::new(Cast {
2840 this: arg,
2841 to: DataType::Timestamp {
2842 precision: None,
2843 timezone: false,
2844 },
2845 trailing_comments: Vec::new(),
2846 double_colon_syntax: false,
2847 format: None,
2848 default: None,
2849 inferred_type: None,
2850 })))
2851 }
2852 "TRY_TO_TIMESTAMP" if f.args.len() == 2 => {
2853 let mut args = f.args;
2854 let value = args.remove(0);
2855 let fmt = self.convert_snowflake_time_format(args.remove(0));
2856 Ok(Expression::Cast(Box::new(Cast {
2857 this: Expression::Function(Box::new(Function::new(
2858 "TRY_STRPTIME".to_string(),
2859 vec![value, fmt],
2860 ))),
2861 to: DataType::Timestamp {
2862 precision: None,
2863 timezone: false,
2864 },
2865 trailing_comments: Vec::new(),
2866 double_colon_syntax: false,
2867 format: None,
2868 default: None,
2869 inferred_type: None,
2870 })))
2871 }
2872 "TRY_TO_DATE" if f.args.len() == 1 => {
2873 let arg = f.args.into_iter().next().unwrap();
2874 Ok(Expression::TryCast(Box::new(Cast {
2875 this: arg,
2876 to: DataType::Date,
2877 trailing_comments: Vec::new(),
2878 double_colon_syntax: false,
2879 format: None,
2880 default: None,
2881 inferred_type: None,
2882 })))
2883 }
2884 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Function(Box::new(Function::new(
2885 "ISODOW".to_string(),
2886 f.args,
2887 )))),
2888 "YEAROFWEEK" | "YEAROFWEEKISO" if f.args.len() == 1 => {
2889 let arg = f.args.into_iter().next().unwrap();
2890 Ok(Expression::Extract(Box::new(
2891 crate::expressions::ExtractFunc {
2892 this: arg,
2893 field: crate::expressions::DateTimeField::Custom("ISOYEAR".to_string()),
2894 },
2895 )))
2896 }
2897 "WEEKISO" => Ok(Expression::Function(Box::new(Function::new(
2898 "WEEKOFYEAR".to_string(),
2899 f.args,
2900 )))),
2901 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 3 => {
2902 let args_ref = &f.args;
2903 let all_in_range = if let (Some(h_val), Some(m_val), Some(s_val)) = (
2905 Self::extract_number_value(&args_ref[0]),
2906 Self::extract_number_value(&args_ref[1]),
2907 Self::extract_number_value(&args_ref[2]),
2908 ) {
2909 h_val >= 0.0
2910 && h_val < 24.0
2911 && m_val >= 0.0
2912 && m_val < 60.0
2913 && s_val >= 0.0
2914 && s_val < 60.0
2915 } else {
2916 false
2917 };
2918 if all_in_range {
2919 Ok(Expression::Function(Box::new(Function::new(
2921 "MAKE_TIME".to_string(),
2922 f.args,
2923 ))))
2924 } else {
2925 let mut args = f.args;
2928 let h = args.remove(0);
2929 let m = args.remove(0);
2930 let s = args.remove(0);
2931 let seconds_expr = Expression::Add(Box::new(BinaryOp {
2932 left: Expression::Add(Box::new(BinaryOp {
2933 left: Expression::Paren(Box::new(Paren {
2934 this: Expression::Mul(Box::new(BinaryOp {
2935 left: h,
2936 right: Expression::number(3600),
2937 left_comments: Vec::new(),
2938 operator_comments: Vec::new(),
2939 trailing_comments: Vec::new(),
2940 inferred_type: None,
2941 })),
2942 trailing_comments: Vec::new(),
2943 })),
2944 right: Expression::Paren(Box::new(Paren {
2945 this: Expression::Mul(Box::new(BinaryOp {
2946 left: m,
2947 right: Expression::number(60),
2948 left_comments: Vec::new(),
2949 operator_comments: Vec::new(),
2950 trailing_comments: Vec::new(),
2951 inferred_type: None,
2952 })),
2953 trailing_comments: Vec::new(),
2954 })),
2955 left_comments: Vec::new(),
2956 operator_comments: Vec::new(),
2957 trailing_comments: Vec::new(),
2958 inferred_type: None,
2959 })),
2960 right: s,
2961 left_comments: Vec::new(),
2962 operator_comments: Vec::new(),
2963 trailing_comments: Vec::new(),
2964 inferred_type: None,
2965 }));
2966 let base_time = Expression::Cast(Box::new(Cast {
2967 this: Expression::Literal(Box::new(Literal::String(
2968 "00:00:00".to_string(),
2969 ))),
2970 to: DataType::Time {
2971 precision: None,
2972 timezone: false,
2973 },
2974 trailing_comments: Vec::new(),
2975 double_colon_syntax: false,
2976 format: None,
2977 default: None,
2978 inferred_type: None,
2979 }));
2980 Ok(Expression::Add(Box::new(BinaryOp {
2981 left: base_time,
2982 right: Expression::Interval(Box::new(Interval {
2983 this: Some(Expression::Paren(Box::new(crate::expressions::Paren {
2984 this: seconds_expr,
2985 trailing_comments: Vec::new(),
2986 }))),
2987 unit: Some(IntervalUnitSpec::Simple {
2988 unit: IntervalUnit::Second,
2989 use_plural: false,
2990 }),
2991 })),
2992 left_comments: Vec::new(),
2993 operator_comments: Vec::new(),
2994 trailing_comments: Vec::new(),
2995 inferred_type: None,
2996 })))
2997 }
2998 }
2999 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 4 => {
3000 let mut args = f.args;
3001 let h = args.remove(0);
3002 let m = args.remove(0);
3003 let s = args.remove(0);
3004 let ns = args.remove(0);
3005 let seconds_expr = Expression::Add(Box::new(BinaryOp {
3006 left: Expression::Add(Box::new(BinaryOp {
3007 left: Expression::Add(Box::new(BinaryOp {
3008 left: Expression::Paren(Box::new(Paren {
3009 this: Expression::Mul(Box::new(BinaryOp {
3010 left: h,
3011 right: Expression::number(3600),
3012 left_comments: Vec::new(),
3013 operator_comments: Vec::new(),
3014 trailing_comments: Vec::new(),
3015 inferred_type: None,
3016 })),
3017 trailing_comments: Vec::new(),
3018 })),
3019 right: Expression::Paren(Box::new(Paren {
3020 this: Expression::Mul(Box::new(BinaryOp {
3021 left: m,
3022 right: Expression::number(60),
3023 left_comments: Vec::new(),
3024 operator_comments: Vec::new(),
3025 trailing_comments: Vec::new(),
3026 inferred_type: None,
3027 })),
3028 trailing_comments: Vec::new(),
3029 })),
3030 left_comments: Vec::new(),
3031 operator_comments: Vec::new(),
3032 trailing_comments: Vec::new(),
3033 inferred_type: None,
3034 })),
3035 right: s,
3036 left_comments: Vec::new(),
3037 operator_comments: Vec::new(),
3038 trailing_comments: Vec::new(),
3039 inferred_type: None,
3040 })),
3041 right: Expression::Paren(Box::new(Paren {
3042 this: Expression::Div(Box::new(BinaryOp {
3043 left: ns,
3044 right: Expression::Literal(Box::new(Literal::Number(
3045 "1000000000.0".to_string(),
3046 ))),
3047 left_comments: Vec::new(),
3048 operator_comments: Vec::new(),
3049 trailing_comments: Vec::new(),
3050 inferred_type: None,
3051 })),
3052 trailing_comments: Vec::new(),
3053 })),
3054 left_comments: Vec::new(),
3055 operator_comments: Vec::new(),
3056 trailing_comments: Vec::new(),
3057 inferred_type: None,
3058 }));
3059 let base_time = Expression::Cast(Box::new(Cast {
3060 this: Expression::Literal(Box::new(Literal::String("00:00:00".to_string()))),
3061 to: DataType::Time {
3062 precision: None,
3063 timezone: false,
3064 },
3065 trailing_comments: Vec::new(),
3066 double_colon_syntax: false,
3067 format: None,
3068 default: None,
3069 inferred_type: None,
3070 }));
3071 Ok(Expression::Add(Box::new(BinaryOp {
3072 left: base_time,
3073 right: Expression::Interval(Box::new(Interval {
3074 this: Some(Expression::Paren(Box::new(crate::expressions::Paren {
3075 this: seconds_expr,
3076 trailing_comments: Vec::new(),
3077 }))),
3078 unit: Some(IntervalUnitSpec::Simple {
3079 unit: IntervalUnit::Second,
3080 use_plural: false,
3081 }),
3082 })),
3083 left_comments: Vec::new(),
3084 operator_comments: Vec::new(),
3085 trailing_comments: Vec::new(),
3086 inferred_type: None,
3087 })))
3088 }
3089 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" if f.args.len() == 6 => {
3090 Ok(Expression::Function(Box::new(Function::new(
3091 "MAKE_TIMESTAMP".to_string(),
3092 f.args,
3093 ))))
3094 }
3095 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMP_NTZ_FROM_PARTS"
3096 if f.args.len() == 2 =>
3097 {
3098 let mut args = f.args;
3099 let d = args.remove(0);
3100 let t = args.remove(0);
3101 Ok(Expression::Add(Box::new(BinaryOp {
3102 left: d,
3103 right: t,
3104 left_comments: Vec::new(),
3105 operator_comments: Vec::new(),
3106 trailing_comments: Vec::new(),
3107 inferred_type: None,
3108 })))
3109 }
3110 "TIMESTAMP_LTZ_FROM_PARTS" if f.args.len() == 6 => {
3111 Ok(Expression::Cast(Box::new(Cast {
3112 this: Expression::Function(Box::new(Function::new(
3113 "MAKE_TIMESTAMP".to_string(),
3114 f.args,
3115 ))),
3116 to: DataType::Timestamp {
3117 precision: None,
3118 timezone: true,
3119 },
3120 trailing_comments: Vec::new(),
3121 double_colon_syntax: false,
3122 format: None,
3123 default: None,
3124 inferred_type: None,
3125 })))
3126 }
3127 "TIMESTAMP_TZ_FROM_PARTS" if f.args.len() == 8 => {
3128 let mut args = f.args;
3129 let ts_args = vec![
3130 args.remove(0),
3131 args.remove(0),
3132 args.remove(0),
3133 args.remove(0),
3134 args.remove(0),
3135 args.remove(0),
3136 ];
3137 let _nano = args.remove(0);
3138 let tz = args.remove(0);
3139 Ok(Expression::AtTimeZone(Box::new(
3140 crate::expressions::AtTimeZone {
3141 this: Expression::Function(Box::new(Function::new(
3142 "MAKE_TIMESTAMP".to_string(),
3143 ts_args,
3144 ))),
3145 zone: tz,
3146 },
3147 )))
3148 }
3149 "BOOLAND_AGG" if f.args.len() == 1 => {
3150 let arg = f.args.into_iter().next().unwrap();
3151 Ok(Expression::Function(Box::new(Function::new(
3152 "BOOL_AND".to_string(),
3153 vec![Expression::Cast(Box::new(Cast {
3154 this: arg,
3155 to: DataType::Boolean,
3156 trailing_comments: Vec::new(),
3157 double_colon_syntax: false,
3158 format: None,
3159 default: None,
3160 inferred_type: None,
3161 }))],
3162 ))))
3163 }
3164 "BOOLOR_AGG" if f.args.len() == 1 => {
3165 let arg = f.args.into_iter().next().unwrap();
3166 Ok(Expression::Function(Box::new(Function::new(
3167 "BOOL_OR".to_string(),
3168 vec![Expression::Cast(Box::new(Cast {
3169 this: arg,
3170 to: DataType::Boolean,
3171 trailing_comments: Vec::new(),
3172 double_colon_syntax: false,
3173 format: None,
3174 default: None,
3175 inferred_type: None,
3176 }))],
3177 ))))
3178 }
3179 "NVL2" if f.args.len() == 3 => {
3180 let mut args = f.args;
3181 let a = args.remove(0);
3182 let b = args.remove(0);
3183 let c = args.remove(0);
3184 Ok(Expression::Case(Box::new(Case {
3185 operand: None,
3186 whens: vec![(
3187 Expression::Not(Box::new(crate::expressions::UnaryOp {
3188 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3189 this: a,
3190 not: false,
3191 postfix_form: false,
3192 })),
3193 inferred_type: None,
3194 })),
3195 b,
3196 )],
3197 else_: Some(c),
3198 comments: Vec::new(),
3199 inferred_type: None,
3200 })))
3201 }
3202 "EQUAL_NULL" if f.args.len() == 2 => {
3203 let mut args = f.args;
3204 let a = args.remove(0);
3205 let b = args.remove(0);
3206 Ok(Expression::NullSafeEq(Box::new(BinaryOp {
3207 left: a,
3208 right: b,
3209 left_comments: Vec::new(),
3210 operator_comments: Vec::new(),
3211 trailing_comments: Vec::new(),
3212 inferred_type: None,
3213 })))
3214 }
3215 "EDITDISTANCE" if f.args.len() == 3 => {
3216 let mut args = f.args;
3218 let a = args.remove(0);
3219 let b = args.remove(0);
3220 let max_dist = args.remove(0);
3221 let lev = Expression::Function(Box::new(Function::new(
3222 "LEVENSHTEIN".to_string(),
3223 vec![a, b],
3224 )));
3225 let lev_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
3226 this: lev.clone(),
3227 not: false,
3228 postfix_form: false,
3229 }));
3230 let max_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
3231 this: max_dist.clone(),
3232 not: false,
3233 postfix_form: false,
3234 }));
3235 let null_check = Expression::Or(Box::new(BinaryOp {
3236 left: lev_is_null,
3237 right: max_is_null,
3238 left_comments: Vec::new(),
3239 operator_comments: Vec::new(),
3240 trailing_comments: Vec::new(),
3241 inferred_type: None,
3242 }));
3243 let least = Expression::Least(Box::new(VarArgFunc {
3244 expressions: vec![lev, max_dist],
3245 original_name: None,
3246 inferred_type: None,
3247 }));
3248 Ok(Expression::Case(Box::new(Case {
3249 operand: None,
3250 whens: vec![(null_check, Expression::Null(crate::expressions::Null))],
3251 else_: Some(least),
3252 comments: Vec::new(),
3253 inferred_type: None,
3254 })))
3255 }
3256 "EDITDISTANCE" => Ok(Expression::Function(Box::new(Function::new(
3257 "LEVENSHTEIN".to_string(),
3258 f.args,
3259 )))),
3260 "BITAND" if f.args.len() == 2 => {
3261 let mut args = f.args;
3262 let left = args.remove(0);
3263 let right = args.remove(0);
3264 let wrap = |e: Expression| -> Expression {
3266 match &e {
3267 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) => {
3268 Expression::Paren(Box::new(Paren {
3269 this: e,
3270 trailing_comments: Vec::new(),
3271 }))
3272 }
3273 _ => e,
3274 }
3275 };
3276 Ok(Expression::BitwiseAnd(Box::new(BinaryOp {
3277 left: wrap(left),
3278 right: wrap(right),
3279 left_comments: Vec::new(),
3280 operator_comments: Vec::new(),
3281 trailing_comments: Vec::new(),
3282 inferred_type: None,
3283 })))
3284 }
3285 "BITOR" if f.args.len() == 2 => {
3286 let mut args = f.args;
3287 let left = args.remove(0);
3288 let right = args.remove(0);
3289 let wrap = |e: Expression| -> Expression {
3291 match &e {
3292 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) => {
3293 Expression::Paren(Box::new(Paren {
3294 this: e,
3295 trailing_comments: Vec::new(),
3296 }))
3297 }
3298 _ => e,
3299 }
3300 };
3301 Ok(Expression::BitwiseOr(Box::new(BinaryOp {
3302 left: wrap(left),
3303 right: wrap(right),
3304 left_comments: Vec::new(),
3305 operator_comments: Vec::new(),
3306 trailing_comments: Vec::new(),
3307 inferred_type: None,
3308 })))
3309 }
3310 "BITXOR" if f.args.len() == 2 => {
3311 let mut args = f.args;
3312 Ok(Expression::BitwiseXor(Box::new(BinaryOp {
3313 left: args.remove(0),
3314 right: args.remove(0),
3315 left_comments: Vec::new(),
3316 operator_comments: Vec::new(),
3317 trailing_comments: Vec::new(),
3318 inferred_type: None,
3319 })))
3320 }
3321 "BITNOT" if f.args.len() == 1 => {
3322 let arg = f.args.into_iter().next().unwrap();
3323 Ok(Expression::BitwiseNot(Box::new(
3324 crate::expressions::UnaryOp {
3325 this: Expression::Paren(Box::new(Paren {
3326 this: arg,
3327 trailing_comments: Vec::new(),
3328 })),
3329 inferred_type: None,
3330 },
3331 )))
3332 }
3333 "BITSHIFTLEFT" if f.args.len() == 2 => {
3334 let mut args = f.args;
3335 let a = args.remove(0);
3336 let b = args.remove(0);
3337 let is_binary = if let Expression::Cast(ref c) = a {
3339 matches!(
3340 &c.to,
3341 DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob
3342 ) || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
3343 } else {
3344 false
3345 };
3346 if is_binary {
3347 let cast_to_bit = Expression::Cast(Box::new(Cast {
3349 this: a,
3350 to: DataType::Custom {
3351 name: "BIT".to_string(),
3352 },
3353 trailing_comments: Vec::new(),
3354 double_colon_syntax: false,
3355 format: None,
3356 default: None,
3357 inferred_type: None,
3358 }));
3359 let shift = Expression::BitwiseLeftShift(Box::new(BinaryOp {
3360 left: cast_to_bit,
3361 right: b,
3362 left_comments: Vec::new(),
3363 operator_comments: Vec::new(),
3364 trailing_comments: Vec::new(),
3365 inferred_type: None,
3366 }));
3367 Ok(Expression::Cast(Box::new(Cast {
3368 this: shift,
3369 to: DataType::Custom {
3370 name: "BLOB".to_string(),
3371 },
3372 trailing_comments: Vec::new(),
3373 double_colon_syntax: false,
3374 format: None,
3375 default: None,
3376 inferred_type: None,
3377 })))
3378 } else {
3379 Ok(Expression::BitwiseLeftShift(Box::new(BinaryOp {
3380 left: Expression::Cast(Box::new(Cast {
3381 this: a,
3382 to: DataType::Custom {
3383 name: "INT128".to_string(),
3384 },
3385 trailing_comments: Vec::new(),
3386 double_colon_syntax: false,
3387 format: None,
3388 default: None,
3389 inferred_type: None,
3390 })),
3391 right: b,
3392 left_comments: Vec::new(),
3393 operator_comments: Vec::new(),
3394 trailing_comments: Vec::new(),
3395 inferred_type: None,
3396 })))
3397 }
3398 }
3399 "BITSHIFTRIGHT" if f.args.len() == 2 => {
3400 let mut args = f.args;
3401 let a = args.remove(0);
3402 let b = args.remove(0);
3403 let is_binary = if let Expression::Cast(ref c) = a {
3405 matches!(
3406 &c.to,
3407 DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob
3408 ) || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
3409 } else {
3410 false
3411 };
3412 if is_binary {
3413 let cast_to_bit = Expression::Cast(Box::new(Cast {
3415 this: a,
3416 to: DataType::Custom {
3417 name: "BIT".to_string(),
3418 },
3419 trailing_comments: Vec::new(),
3420 double_colon_syntax: false,
3421 format: None,
3422 default: None,
3423 inferred_type: None,
3424 }));
3425 let shift = Expression::BitwiseRightShift(Box::new(BinaryOp {
3426 left: cast_to_bit,
3427 right: b,
3428 left_comments: Vec::new(),
3429 operator_comments: Vec::new(),
3430 trailing_comments: Vec::new(),
3431 inferred_type: None,
3432 }));
3433 Ok(Expression::Cast(Box::new(Cast {
3434 this: shift,
3435 to: DataType::Custom {
3436 name: "BLOB".to_string(),
3437 },
3438 trailing_comments: Vec::new(),
3439 double_colon_syntax: false,
3440 format: None,
3441 default: None,
3442 inferred_type: None,
3443 })))
3444 } else {
3445 Ok(Expression::BitwiseRightShift(Box::new(BinaryOp {
3446 left: Expression::Cast(Box::new(Cast {
3447 this: a,
3448 to: DataType::Custom {
3449 name: "INT128".to_string(),
3450 },
3451 trailing_comments: Vec::new(),
3452 double_colon_syntax: false,
3453 format: None,
3454 default: None,
3455 inferred_type: None,
3456 })),
3457 right: b,
3458 left_comments: Vec::new(),
3459 operator_comments: Vec::new(),
3460 trailing_comments: Vec::new(),
3461 inferred_type: None,
3462 })))
3463 }
3464 }
3465 "SQUARE" if f.args.len() == 1 => {
3466 let arg = f.args.into_iter().next().unwrap();
3467 Ok(Expression::Function(Box::new(Function::new(
3468 "POWER".to_string(),
3469 vec![arg, Expression::number(2)],
3470 ))))
3471 }
3472 "LIST"
3473 if f.args.len() == 1 && !matches!(f.args.first(), Some(Expression::Select(_))) =>
3474 {
3475 Ok(Expression::Function(Box::new(Function::new(
3476 "ARRAY_AGG".to_string(),
3477 f.args,
3478 ))))
3479 }
3480 "UUID_STRING" => {
3481 if f.args.is_empty() {
3482 Ok(Expression::Function(Box::new(Function::new(
3483 "UUID".to_string(),
3484 vec![],
3485 ))))
3486 } else {
3487 Ok(Expression::Function(Box::new(Function::new(
3488 "UUID_STRING".to_string(),
3489 f.args,
3490 ))))
3491 }
3492 }
3493 "ENDSWITH" => Ok(Expression::Function(Box::new(Function::new(
3494 "ENDS_WITH".to_string(),
3495 f.args,
3496 )))),
3497 "REGEXP_REPLACE" if f.args.len() == 2 => {
3501 let mut args = f.args;
3503 args.push(Expression::Literal(Box::new(
3504 Literal::String(String::new()),
3505 )));
3506 Ok(Expression::Function(Box::new(Function::new(
3507 "REGEXP_REPLACE".to_string(),
3508 args,
3509 ))))
3510 }
3511 "DIV0" if f.args.len() == 2 => {
3512 let mut args = f.args;
3513 let a = args.remove(0);
3514 let b = args.remove(0);
3515 Ok(Expression::Case(Box::new(Case {
3516 operand: None,
3517 whens: vec![(
3518 Expression::And(Box::new(BinaryOp {
3519 left: Expression::Eq(Box::new(BinaryOp {
3520 left: b.clone(),
3521 right: Expression::number(0),
3522 left_comments: Vec::new(),
3523 operator_comments: Vec::new(),
3524 trailing_comments: Vec::new(),
3525 inferred_type: None,
3526 })),
3527 right: Expression::Not(Box::new(crate::expressions::UnaryOp {
3528 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3529 this: a.clone(),
3530 not: false,
3531 postfix_form: false,
3532 })),
3533 inferred_type: None,
3534 })),
3535 left_comments: Vec::new(),
3536 operator_comments: Vec::new(),
3537 trailing_comments: Vec::new(),
3538 inferred_type: None,
3539 })),
3540 Expression::number(0),
3541 )],
3542 else_: Some(Expression::Div(Box::new(BinaryOp {
3543 left: a,
3544 right: b,
3545 left_comments: Vec::new(),
3546 operator_comments: Vec::new(),
3547 trailing_comments: Vec::new(),
3548 inferred_type: None,
3549 }))),
3550 comments: Vec::new(),
3551 inferred_type: None,
3552 })))
3553 }
3554 "DIV0NULL" if f.args.len() == 2 => {
3555 let mut args = f.args;
3556 let a = args.remove(0);
3557 let b = args.remove(0);
3558 Ok(Expression::Case(Box::new(Case {
3559 operand: None,
3560 whens: vec![(
3561 Expression::Or(Box::new(BinaryOp {
3562 left: Expression::Eq(Box::new(BinaryOp {
3563 left: b.clone(),
3564 right: Expression::number(0),
3565 left_comments: Vec::new(),
3566 operator_comments: Vec::new(),
3567 trailing_comments: Vec::new(),
3568 inferred_type: None,
3569 })),
3570 right: Expression::IsNull(Box::new(crate::expressions::IsNull {
3571 this: b.clone(),
3572 not: false,
3573 postfix_form: false,
3574 })),
3575 left_comments: Vec::new(),
3576 operator_comments: Vec::new(),
3577 trailing_comments: Vec::new(),
3578 inferred_type: None,
3579 })),
3580 Expression::number(0),
3581 )],
3582 else_: Some(Expression::Div(Box::new(BinaryOp {
3583 left: a,
3584 right: b,
3585 left_comments: Vec::new(),
3586 operator_comments: Vec::new(),
3587 trailing_comments: Vec::new(),
3588 inferred_type: None,
3589 }))),
3590 comments: Vec::new(),
3591 inferred_type: None,
3592 })))
3593 }
3594 "ZEROIFNULL" if f.args.len() == 1 => {
3595 let x = f.args.into_iter().next().unwrap();
3596 Ok(Expression::Case(Box::new(Case {
3597 operand: None,
3598 whens: vec![(
3599 Expression::IsNull(Box::new(crate::expressions::IsNull {
3600 this: x.clone(),
3601 not: false,
3602 postfix_form: false,
3603 })),
3604 Expression::number(0),
3605 )],
3606 else_: Some(x),
3607 comments: Vec::new(),
3608 inferred_type: None,
3609 })))
3610 }
3611 "NULLIFZERO" if f.args.len() == 1 => {
3612 let x = f.args.into_iter().next().unwrap();
3613 Ok(Expression::Case(Box::new(Case {
3614 operand: None,
3615 whens: vec![(
3616 Expression::Eq(Box::new(BinaryOp {
3617 left: x.clone(),
3618 right: Expression::number(0),
3619 left_comments: Vec::new(),
3620 operator_comments: Vec::new(),
3621 trailing_comments: Vec::new(),
3622 inferred_type: None,
3623 })),
3624 Expression::Null(crate::expressions::Null),
3625 )],
3626 else_: Some(x),
3627 comments: Vec::new(),
3628 inferred_type: None,
3629 })))
3630 }
3631 "TO_DOUBLE" if f.args.len() == 1 => {
3632 let arg = f.args.into_iter().next().unwrap();
3633 Ok(Expression::Cast(Box::new(Cast {
3634 this: arg,
3635 to: DataType::Double {
3636 precision: None,
3637 scale: None,
3638 },
3639 trailing_comments: Vec::new(),
3640 double_colon_syntax: false,
3641 format: None,
3642 default: None,
3643 inferred_type: None,
3644 })))
3645 }
3646 "DATE" if f.args.len() == 1 => {
3647 let arg = f.args.into_iter().next().unwrap();
3648 Ok(Expression::Cast(Box::new(Cast {
3649 this: arg,
3650 to: DataType::Date,
3651 trailing_comments: Vec::new(),
3652 double_colon_syntax: false,
3653 format: None,
3654 default: None,
3655 inferred_type: None,
3656 })))
3657 }
3658 "DATE" if f.args.len() == 2 => {
3659 let mut args = f.args;
3660 let value = args.remove(0);
3661 let fmt = self.convert_snowflake_date_format(args.remove(0));
3662 Ok(Expression::Cast(Box::new(Cast {
3663 this: Expression::Function(Box::new(Function::new(
3664 "STRPTIME".to_string(),
3665 vec![value, fmt],
3666 ))),
3667 to: DataType::Date,
3668 trailing_comments: Vec::new(),
3669 double_colon_syntax: false,
3670 format: None,
3671 default: None,
3672 inferred_type: None,
3673 })))
3674 }
3675 "SYSDATE" => Ok(Expression::AtTimeZone(Box::new(
3676 crate::expressions::AtTimeZone {
3677 this: Expression::CurrentTimestamp(crate::expressions::CurrentTimestamp {
3678 precision: None,
3679 sysdate: false,
3680 }),
3681 zone: Expression::Literal(Box::new(Literal::String("UTC".to_string()))),
3682 },
3683 ))),
3684 "HEX_DECODE_BINARY" => Ok(Expression::Function(Box::new(Function::new(
3685 "UNHEX".to_string(),
3686 f.args,
3687 )))),
3688 "CONVERT_TIMEZONE" if f.args.len() == 3 => {
3689 let mut args = f.args;
3690 let src_tz = args.remove(0);
3691 let tgt_tz = args.remove(0);
3692 let ts = args.remove(0);
3693 let cast_ts = Expression::Cast(Box::new(Cast {
3694 this: ts,
3695 to: DataType::Timestamp {
3696 precision: None,
3697 timezone: false,
3698 },
3699 trailing_comments: Vec::new(),
3700 double_colon_syntax: false,
3701 format: None,
3702 default: None,
3703 inferred_type: None,
3704 }));
3705 Ok(Expression::AtTimeZone(Box::new(
3706 crate::expressions::AtTimeZone {
3707 this: Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone {
3708 this: cast_ts,
3709 zone: src_tz,
3710 })),
3711 zone: tgt_tz,
3712 },
3713 )))
3714 }
3715 "CONVERT_TIMEZONE" if f.args.len() == 2 => {
3716 let mut args = f.args;
3717 let tgt_tz = args.remove(0);
3718 let ts = args.remove(0);
3719 let cast_ts = Expression::Cast(Box::new(Cast {
3720 this: ts,
3721 to: DataType::Timestamp {
3722 precision: None,
3723 timezone: false,
3724 },
3725 trailing_comments: Vec::new(),
3726 double_colon_syntax: false,
3727 format: None,
3728 default: None,
3729 inferred_type: None,
3730 }));
3731 Ok(Expression::AtTimeZone(Box::new(
3732 crate::expressions::AtTimeZone {
3733 this: cast_ts,
3734 zone: tgt_tz,
3735 },
3736 )))
3737 }
3738 "DATE_PART" | "DATEPART" if f.args.len() == 2 => self.transform_date_part(f.args),
3739 "DATEADD" | "TIMEADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3740 "TIMESTAMPADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3741 "DATEDIFF" | "TIMEDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3742 "TIMESTAMPDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3743 "CORR" if f.args.len() == 2 => {
3744 Ok(Expression::Function(Box::new(f)))
3746 }
3747 "TO_TIMESTAMP" | "TO_TIMESTAMP_NTZ" if f.args.len() == 2 => {
3748 let mut args = f.args;
3749 let value = args.remove(0);
3750 let second_arg = args.remove(0);
3751 match &second_arg {
3752 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => Ok(
3753 Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone {
3754 this: Expression::Function(Box::new(Function::new(
3755 "TO_TIMESTAMP".to_string(),
3756 vec![Expression::Div(Box::new(BinaryOp {
3757 left: value,
3758 right: Expression::Function(Box::new(Function::new(
3759 "POWER".to_string(),
3760 vec![Expression::number(10), second_arg],
3761 ))),
3762 left_comments: Vec::new(),
3763 operator_comments: Vec::new(),
3764 trailing_comments: Vec::new(),
3765 inferred_type: None,
3766 }))],
3767 ))),
3768 zone: Expression::Literal(Box::new(Literal::String("UTC".to_string()))),
3769 })),
3770 ),
3771 _ => {
3772 let fmt = self.convert_snowflake_time_format(second_arg);
3773 Ok(Expression::Function(Box::new(Function::new(
3774 "STRPTIME".to_string(),
3775 vec![value, fmt],
3776 ))))
3777 }
3778 }
3779 }
3780 "TO_TIME" if f.args.len() == 1 => {
3781 let arg = f.args.into_iter().next().unwrap();
3782 Ok(Expression::Cast(Box::new(Cast {
3783 this: arg,
3784 to: DataType::Time {
3785 precision: None,
3786 timezone: false,
3787 },
3788 trailing_comments: Vec::new(),
3789 double_colon_syntax: false,
3790 format: None,
3791 default: None,
3792 inferred_type: None,
3793 })))
3794 }
3795 "TO_TIME" if f.args.len() == 2 => {
3796 let mut args = f.args;
3797 let value = args.remove(0);
3798 let fmt = self.convert_snowflake_time_format(args.remove(0));
3799 Ok(Expression::Cast(Box::new(Cast {
3800 this: Expression::Function(Box::new(Function::new(
3801 "STRPTIME".to_string(),
3802 vec![value, fmt],
3803 ))),
3804 to: DataType::Time {
3805 precision: None,
3806 timezone: false,
3807 },
3808 trailing_comments: Vec::new(),
3809 double_colon_syntax: false,
3810 format: None,
3811 default: None,
3812 inferred_type: None,
3813 })))
3814 }
3815 "TO_DATE" if f.args.len() == 2 => {
3816 let mut args = f.args;
3817 let value = args.remove(0);
3818 let fmt = self.convert_snowflake_date_format(args.remove(0));
3819 Ok(Expression::Cast(Box::new(Cast {
3820 this: Expression::Function(Box::new(Function::new(
3821 "STRPTIME".to_string(),
3822 vec![value, fmt],
3823 ))),
3824 to: DataType::Date,
3825 trailing_comments: Vec::new(),
3826 double_colon_syntax: false,
3827 format: None,
3828 default: None,
3829 inferred_type: None,
3830 })))
3831 }
3832 "SAFE_DIVIDE" if f.args.len() == 2 => {
3836 let mut args = f.args;
3837 let x = args.remove(0);
3838 let y = args.remove(0);
3839 Ok(Expression::Case(Box::new(Case {
3840 operand: None,
3841 whens: vec![(
3842 Expression::Neq(Box::new(BinaryOp {
3843 left: y.clone(),
3844 right: Expression::number(0),
3845 left_comments: Vec::new(),
3846 operator_comments: Vec::new(),
3847 trailing_comments: Vec::new(),
3848 inferred_type: None,
3849 })),
3850 Expression::Div(Box::new(BinaryOp {
3851 left: x,
3852 right: y,
3853 left_comments: Vec::new(),
3854 operator_comments: Vec::new(),
3855 trailing_comments: Vec::new(),
3856 inferred_type: None,
3857 })),
3858 )],
3859 else_: Some(Expression::Null(crate::expressions::Null)),
3860 comments: Vec::new(),
3861 inferred_type: None,
3862 })))
3863 }
3864
3865 "TO_HEX" if f.args.len() == 1 => {
3867 let arg = f.args.into_iter().next().unwrap();
3868 Ok(Expression::Lower(Box::new(UnaryFunc::new(
3869 Expression::Function(Box::new(Function::new("HEX".to_string(), vec![arg]))),
3870 ))))
3871 }
3872
3873 "EDIT_DISTANCE" if f.args.len() >= 2 => {
3875 let mut args = f.args;
3877 let a = args.remove(0);
3878 let b = args.remove(0);
3879 Ok(Expression::Function(Box::new(Function::new(
3880 "LEVENSHTEIN".to_string(),
3881 vec![a, b],
3882 ))))
3883 }
3884
3885 "UNIX_DATE" if f.args.len() == 1 => {
3887 let arg = f.args.into_iter().next().unwrap();
3888 Ok(Expression::Function(Box::new(Function::new(
3889 "DATE_DIFF".to_string(),
3890 vec![
3891 Expression::Literal(Box::new(Literal::String("DAY".to_string()))),
3892 Expression::Cast(Box::new(Cast {
3893 this: Expression::Literal(Box::new(Literal::String(
3894 "1970-01-01".to_string(),
3895 ))),
3896 to: DataType::Date,
3897 trailing_comments: Vec::new(),
3898 double_colon_syntax: false,
3899 format: None,
3900 default: None,
3901 inferred_type: None,
3902 })),
3903 arg,
3904 ],
3905 ))))
3906 }
3907
3908 "TIMESTAMP" if f.args.len() == 1 => {
3910 let arg = f.args.into_iter().next().unwrap();
3911 Ok(Expression::Cast(Box::new(Cast {
3912 this: arg,
3913 to: DataType::Custom {
3914 name: "TIMESTAMPTZ".to_string(),
3915 },
3916 trailing_comments: Vec::new(),
3917 double_colon_syntax: false,
3918 format: None,
3919 default: None,
3920 inferred_type: None,
3921 })))
3922 }
3923
3924 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3926 "MAKE_TIME".to_string(),
3927 f.args,
3928 )))),
3929
3930 "DATE" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3932 "MAKE_DATE".to_string(),
3933 f.args,
3934 )))),
3935
3936 "DATETIME" if f.args.len() == 6 => Ok(Expression::Function(Box::new(Function::new(
3938 "MAKE_TIMESTAMP".to_string(),
3939 f.args,
3940 )))),
3941
3942 "PARSE_TIMESTAMP" if f.args.len() >= 2 => {
3944 let mut args = f.args;
3945 let fmt = args.remove(0);
3946 let value = args.remove(0);
3947 let duckdb_fmt = self.convert_bq_to_strptime_format(fmt);
3949 Ok(Expression::Function(Box::new(Function::new(
3950 "STRPTIME".to_string(),
3951 vec![value, duckdb_fmt],
3952 ))))
3953 }
3954
3955 "BOOLAND" if f.args.len() == 2 => {
3957 let mut args = f.args;
3958 let a = args.remove(0);
3959 let b = args.remove(0);
3960 let ra = Expression::Function(Box::new(Function::new(
3961 "ROUND".to_string(),
3962 vec![a, Expression::number(0)],
3963 )));
3964 let rb = Expression::Function(Box::new(Function::new(
3965 "ROUND".to_string(),
3966 vec![b, Expression::number(0)],
3967 )));
3968 Ok(Expression::Paren(Box::new(Paren {
3969 this: Expression::And(Box::new(BinaryOp {
3970 left: Expression::Paren(Box::new(Paren {
3971 this: ra,
3972 trailing_comments: Vec::new(),
3973 })),
3974 right: Expression::Paren(Box::new(Paren {
3975 this: rb,
3976 trailing_comments: Vec::new(),
3977 })),
3978 left_comments: Vec::new(),
3979 operator_comments: Vec::new(),
3980 trailing_comments: Vec::new(),
3981 inferred_type: None,
3982 })),
3983 trailing_comments: Vec::new(),
3984 })))
3985 }
3986
3987 "BOOLOR" if f.args.len() == 2 => {
3989 let mut args = f.args;
3990 let a = args.remove(0);
3991 let b = args.remove(0);
3992 let ra = Expression::Function(Box::new(Function::new(
3993 "ROUND".to_string(),
3994 vec![a, Expression::number(0)],
3995 )));
3996 let rb = Expression::Function(Box::new(Function::new(
3997 "ROUND".to_string(),
3998 vec![b, Expression::number(0)],
3999 )));
4000 Ok(Expression::Paren(Box::new(Paren {
4001 this: Expression::Or(Box::new(BinaryOp {
4002 left: Expression::Paren(Box::new(Paren {
4003 this: ra,
4004 trailing_comments: Vec::new(),
4005 })),
4006 right: Expression::Paren(Box::new(Paren {
4007 this: rb,
4008 trailing_comments: Vec::new(),
4009 })),
4010 left_comments: Vec::new(),
4011 operator_comments: Vec::new(),
4012 trailing_comments: Vec::new(),
4013 inferred_type: None,
4014 })),
4015 trailing_comments: Vec::new(),
4016 })))
4017 }
4018
4019 "BOOLXOR" if f.args.len() == 2 => {
4021 let mut args = f.args;
4022 let a = args.remove(0);
4023 let b = args.remove(0);
4024 let ra = Expression::Function(Box::new(Function::new(
4025 "ROUND".to_string(),
4026 vec![a, Expression::number(0)],
4027 )));
4028 let rb = Expression::Function(Box::new(Function::new(
4029 "ROUND".to_string(),
4030 vec![b, Expression::number(0)],
4031 )));
4032 let not_rb = Expression::Not(Box::new(crate::expressions::UnaryOp {
4034 this: rb.clone(),
4035 inferred_type: None,
4036 }));
4037 let not_ra = Expression::Not(Box::new(crate::expressions::UnaryOp {
4038 this: ra.clone(),
4039 inferred_type: None,
4040 }));
4041 let left_and = Expression::And(Box::new(BinaryOp {
4042 left: ra,
4043 right: Expression::Paren(Box::new(Paren {
4044 this: not_rb,
4045 trailing_comments: Vec::new(),
4046 })),
4047 left_comments: Vec::new(),
4048 operator_comments: Vec::new(),
4049 trailing_comments: Vec::new(),
4050 inferred_type: None,
4051 }));
4052 let right_and = Expression::And(Box::new(BinaryOp {
4053 left: Expression::Paren(Box::new(Paren {
4054 this: not_ra,
4055 trailing_comments: Vec::new(),
4056 })),
4057 right: rb,
4058 left_comments: Vec::new(),
4059 operator_comments: Vec::new(),
4060 trailing_comments: Vec::new(),
4061 inferred_type: None,
4062 }));
4063 Ok(Expression::Or(Box::new(BinaryOp {
4064 left: Expression::Paren(Box::new(Paren {
4065 this: left_and,
4066 trailing_comments: Vec::new(),
4067 })),
4068 right: Expression::Paren(Box::new(Paren {
4069 this: right_and,
4070 trailing_comments: Vec::new(),
4071 })),
4072 left_comments: Vec::new(),
4073 operator_comments: Vec::new(),
4074 trailing_comments: Vec::new(),
4075 inferred_type: None,
4076 })))
4077 }
4078
4079 "DECODE" if f.args.len() >= 3 => {
4082 let mut args = f.args;
4083 let expr = args.remove(0);
4084 let mut whens = Vec::new();
4085 let mut else_expr = None;
4086 while args.len() >= 2 {
4087 let search = args.remove(0);
4088 let result = args.remove(0);
4089 let condition = if matches!(&search, Expression::Null(_)) {
4091 Expression::IsNull(Box::new(crate::expressions::IsNull {
4092 this: expr.clone(),
4093 not: false,
4094 postfix_form: false,
4095 }))
4096 } else {
4097 Expression::Eq(Box::new(BinaryOp {
4098 left: expr.clone(),
4099 right: search,
4100 left_comments: Vec::new(),
4101 operator_comments: Vec::new(),
4102 trailing_comments: Vec::new(),
4103 inferred_type: None,
4104 }))
4105 };
4106 whens.push((condition, result));
4107 }
4108 if !args.is_empty() {
4109 else_expr = Some(args.remove(0));
4110 }
4111 Ok(Expression::Case(Box::new(Case {
4112 operand: None,
4113 whens,
4114 else_: else_expr,
4115 comments: Vec::new(),
4116 inferred_type: None,
4117 })))
4118 }
4119
4120 "TRY_TO_BOOLEAN" if f.args.len() == 1 => {
4122 let arg = f.args.into_iter().next().unwrap();
4123 let cast_text = Expression::Cast(Box::new(Cast {
4124 this: arg.clone(),
4125 to: DataType::Text,
4126 trailing_comments: Vec::new(),
4127 double_colon_syntax: false,
4128 format: None,
4129 default: None,
4130 inferred_type: None,
4131 }));
4132 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
4133 Ok(Expression::Case(Box::new(Case {
4134 operand: None,
4135 whens: vec![
4136 (
4137 Expression::Eq(Box::new(BinaryOp {
4138 left: upper_text.clone(),
4139 right: Expression::Literal(Box::new(Literal::String(
4140 "ON".to_string(),
4141 ))),
4142 left_comments: Vec::new(),
4143 operator_comments: Vec::new(),
4144 trailing_comments: Vec::new(),
4145 inferred_type: None,
4146 })),
4147 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
4148 ),
4149 (
4150 Expression::Eq(Box::new(BinaryOp {
4151 left: upper_text,
4152 right: Expression::Literal(Box::new(Literal::String(
4153 "OFF".to_string(),
4154 ))),
4155 left_comments: Vec::new(),
4156 operator_comments: Vec::new(),
4157 trailing_comments: Vec::new(),
4158 inferred_type: None,
4159 })),
4160 Expression::Boolean(crate::expressions::BooleanLiteral {
4161 value: false,
4162 }),
4163 ),
4164 ],
4165 else_: Some(Expression::TryCast(Box::new(Cast {
4166 this: arg,
4167 to: DataType::Boolean,
4168 trailing_comments: Vec::new(),
4169 double_colon_syntax: false,
4170 format: None,
4171 default: None,
4172 inferred_type: None,
4173 }))),
4174 comments: Vec::new(),
4175 inferred_type: None,
4176 })))
4177 }
4178
4179 "TO_BOOLEAN" if f.args.len() == 1 => {
4181 let arg = f.args.into_iter().next().unwrap();
4182 let cast_text = Expression::Cast(Box::new(Cast {
4183 this: arg.clone(),
4184 to: DataType::Text,
4185 trailing_comments: Vec::new(),
4186 double_colon_syntax: false,
4187 format: None,
4188 default: None,
4189 inferred_type: None,
4190 }));
4191 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
4192 Ok(Expression::Case(Box::new(Case {
4193 operand: None,
4194 whens: vec![
4195 (
4196 Expression::Eq(Box::new(BinaryOp {
4197 left: upper_text.clone(),
4198 right: Expression::Literal(Box::new(Literal::String(
4199 "ON".to_string(),
4200 ))),
4201 left_comments: Vec::new(),
4202 operator_comments: Vec::new(),
4203 trailing_comments: Vec::new(),
4204 inferred_type: None,
4205 })),
4206 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
4207 ),
4208 (
4209 Expression::Eq(Box::new(BinaryOp {
4210 left: upper_text,
4211 right: Expression::Literal(Box::new(Literal::String(
4212 "OFF".to_string(),
4213 ))),
4214 left_comments: Vec::new(),
4215 operator_comments: Vec::new(),
4216 trailing_comments: Vec::new(),
4217 inferred_type: None,
4218 })),
4219 Expression::Boolean(crate::expressions::BooleanLiteral {
4220 value: false,
4221 }),
4222 ),
4223 (
4224 Expression::Or(Box::new(BinaryOp {
4225 left: Expression::Function(Box::new(Function::new(
4226 "ISNAN".to_string(),
4227 vec![Expression::TryCast(Box::new(Cast {
4228 this: arg.clone(),
4229 to: DataType::Custom {
4230 name: "REAL".to_string(),
4231 },
4232 trailing_comments: Vec::new(),
4233 double_colon_syntax: false,
4234 format: None,
4235 default: None,
4236 inferred_type: None,
4237 }))],
4238 ))),
4239 right: Expression::Function(Box::new(Function::new(
4240 "ISINF".to_string(),
4241 vec![Expression::TryCast(Box::new(Cast {
4242 this: arg.clone(),
4243 to: DataType::Custom {
4244 name: "REAL".to_string(),
4245 },
4246 trailing_comments: Vec::new(),
4247 double_colon_syntax: false,
4248 format: None,
4249 default: None,
4250 inferred_type: None,
4251 }))],
4252 ))),
4253 left_comments: Vec::new(),
4254 operator_comments: Vec::new(),
4255 trailing_comments: Vec::new(),
4256 inferred_type: None,
4257 })),
4258 Expression::Function(Box::new(Function::new(
4259 "ERROR".to_string(),
4260 vec![Expression::Literal(Box::new(Literal::String(
4261 "TO_BOOLEAN: Non-numeric values NaN and INF are not supported"
4262 .to_string(),
4263 )))],
4264 ))),
4265 ),
4266 ],
4267 else_: Some(Expression::Cast(Box::new(Cast {
4268 this: arg,
4269 to: DataType::Boolean,
4270 trailing_comments: Vec::new(),
4271 double_colon_syntax: false,
4272 format: None,
4273 default: None,
4274 inferred_type: None,
4275 }))),
4276 comments: Vec::new(),
4277 inferred_type: None,
4278 })))
4279 }
4280
4281 "OBJECT_INSERT" if f.args.len() == 3 => {
4284 let mut args = f.args;
4285 let obj = args.remove(0);
4286 let key = args.remove(0);
4287 let value = args.remove(0);
4288 let key_name = match &key {
4290 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4291 let Literal::String(s) = lit.as_ref() else {
4292 unreachable!()
4293 };
4294 s.clone()
4295 }
4296 _ => "key".to_string(),
4297 };
4298 let named_arg =
4299 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
4300 name: Identifier::new(&key_name),
4301 value,
4302 separator: crate::expressions::NamedArgSeparator::ColonEq,
4303 }));
4304 let is_empty_struct = match &obj {
4306 Expression::Struct(s) if s.fields.is_empty() => true,
4307 Expression::Function(f) => {
4308 let n = f.name.to_uppercase();
4309 (n == "STRUCT_PACK" || n == "OBJECT_CONSTRUCT") && f.args.is_empty()
4310 }
4311 _ => false,
4312 };
4313 if is_empty_struct {
4314 Ok(Expression::Function(Box::new(Function::new(
4316 "STRUCT_PACK".to_string(),
4317 vec![named_arg],
4318 ))))
4319 } else {
4320 Ok(Expression::Function(Box::new(Function::new(
4321 "STRUCT_INSERT".to_string(),
4322 vec![obj, named_arg],
4323 ))))
4324 }
4325 }
4326
4327 "GET" if f.args.len() == 2 => {
4329 let mut args = f.args;
4330 let this = args.remove(0);
4331 let key = args.remove(0);
4332 match &key {
4333 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4335 let Literal::String(s) = lit.as_ref() else {
4336 unreachable!()
4337 };
4338 let json_path = format!("$.{}", s);
4339 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4340 this,
4341 path: Expression::Literal(Box::new(Literal::String(json_path))),
4342 returning: None,
4343 arrow_syntax: true,
4344 hash_arrow_syntax: false,
4345 wrapper_option: None,
4346 quotes_option: None,
4347 on_scalar_string: false,
4348 on_error: None,
4349 })))
4350 }
4351 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4355 let Literal::Number(n) = lit.as_ref() else {
4356 unreachable!()
4357 };
4358 let idx: i64 = n.parse().unwrap_or(0);
4359 let is_map = matches!(&this, Expression::Cast(c) if matches!(c.to, DataType::Map { .. }));
4360 let index_val = if is_map { idx } else { idx + 1 };
4361 Ok(Expression::Subscript(Box::new(
4362 crate::expressions::Subscript {
4363 this,
4364 index: Expression::number(index_val),
4365 },
4366 )))
4367 }
4368 _ => {
4369 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4371 this,
4372 path: Expression::JSONPath(Box::new(JSONPath {
4373 expressions: vec![
4374 Expression::JSONPathRoot(JSONPathRoot),
4375 Expression::JSONPathKey(Box::new(JSONPathKey {
4376 this: Box::new(key),
4377 })),
4378 ],
4379 escape: None,
4380 })),
4381 returning: None,
4382 arrow_syntax: true,
4383 hash_arrow_syntax: false,
4384 wrapper_option: None,
4385 quotes_option: None,
4386 on_scalar_string: false,
4387 on_error: None,
4388 })))
4389 }
4390 }
4391 }
4392
4393 "GET_PATH" if f.args.len() == 2 => {
4395 let mut args = f.args;
4396 let this = args.remove(0);
4397 let path = args.remove(0);
4398 let json_path = match &path {
4400 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4401 let Literal::String(s) = lit.as_ref() else {
4402 unreachable!()
4403 };
4404 let s = Self::convert_bracket_to_quoted_path(s);
4406 let normalized = if s.starts_with('$') {
4408 s
4409 } else if s.starts_with('[') {
4410 format!("${}", s)
4411 } else {
4412 format!("$.{}", s)
4413 };
4414 Expression::Literal(Box::new(Literal::String(normalized)))
4415 }
4416 _ => path,
4417 };
4418 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4419 this,
4420 path: json_path,
4421 returning: None,
4422 arrow_syntax: true,
4423 hash_arrow_syntax: false,
4424 wrapper_option: None,
4425 quotes_option: None,
4426 on_scalar_string: false,
4427 on_error: None,
4428 })))
4429 }
4430
4431 "BASE64_ENCODE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
4433 Function::new("TO_BASE64".to_string(), f.args),
4434 ))),
4435
4436 "BASE64_ENCODE" if f.args.len() >= 2 => {
4438 let mut args = f.args;
4439 let x = args.remove(0);
4440 let line_len = args.remove(0);
4441 let line_len_str = match &line_len {
4442 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4443 let Literal::Number(n) = lit.as_ref() else {
4444 unreachable!()
4445 };
4446 n.clone()
4447 }
4448 _ => "76".to_string(),
4449 };
4450 let to_base64 =
4451 Expression::Function(Box::new(Function::new("TO_BASE64".to_string(), vec![x])));
4452 let pattern = format!("(.{{{}}})", line_len_str);
4453 let chr_10 = Expression::Function(Box::new(Function::new(
4454 "CHR".to_string(),
4455 vec![Expression::number(10)],
4456 )));
4457 let replacement = Expression::Concat(Box::new(BinaryOp {
4458 left: Expression::Literal(Box::new(Literal::String("\\1".to_string()))),
4459 right: chr_10.clone(),
4460 left_comments: Vec::new(),
4461 operator_comments: Vec::new(),
4462 trailing_comments: Vec::new(),
4463 inferred_type: None,
4464 }));
4465 let regexp_replace = Expression::Function(Box::new(Function::new(
4466 "REGEXP_REPLACE".to_string(),
4467 vec![
4468 to_base64,
4469 Expression::Literal(Box::new(Literal::String(pattern))),
4470 replacement,
4471 Expression::Literal(Box::new(Literal::String("g".to_string()))),
4472 ],
4473 )));
4474 Ok(Expression::Function(Box::new(Function::new(
4475 "RTRIM".to_string(),
4476 vec![regexp_replace, chr_10],
4477 ))))
4478 }
4479
4480 "TRY_TO_DATE" if f.args.len() == 2 => {
4482 let mut args = f.args;
4483 let value = args.remove(0);
4484 let fmt = self.convert_snowflake_date_format(args.remove(0));
4485 Ok(Expression::Cast(Box::new(Cast {
4486 this: Expression::Cast(Box::new(Cast {
4487 this: Expression::Function(Box::new(Function::new(
4488 "TRY_STRPTIME".to_string(),
4489 vec![value, fmt],
4490 ))),
4491 to: DataType::Timestamp {
4492 precision: None,
4493 timezone: false,
4494 },
4495 trailing_comments: Vec::new(),
4496 double_colon_syntax: false,
4497 format: None,
4498 default: None,
4499 inferred_type: None,
4500 })),
4501 to: DataType::Date,
4502 trailing_comments: Vec::new(),
4503 double_colon_syntax: false,
4504 format: None,
4505 default: None,
4506 inferred_type: None,
4507 })))
4508 }
4509
4510 "REGEXP_REPLACE" if f.args.len() == 4 => {
4513 let is_snowflake_position = matches!(&f.args[3], Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)));
4514 if is_snowflake_position {
4515 let mut args = f.args;
4517 let subject = args.remove(0);
4518 let pattern = args.remove(0);
4519 let replacement = args.remove(0);
4520 Ok(Expression::Function(Box::new(Function::new(
4521 "REGEXP_REPLACE".to_string(),
4522 vec![
4523 subject,
4524 pattern,
4525 replacement,
4526 Expression::Literal(Box::new(Literal::String("g".to_string()))),
4527 ],
4528 ))))
4529 } else {
4530 Ok(Expression::Function(Box::new(f)))
4532 }
4533 }
4534
4535 "REGEXP_REPLACE" if f.args.len() >= 5 => {
4537 let mut args = f.args;
4538 let subject = args.remove(0);
4539 let pattern = args.remove(0);
4540 let replacement = args.remove(0);
4541 let _position = args.remove(0);
4542 let occurrence = if !args.is_empty() {
4543 Some(args.remove(0))
4544 } else {
4545 None
4546 };
4547 let params = if !args.is_empty() {
4548 Some(args.remove(0))
4549 } else {
4550 None
4551 };
4552
4553 let mut flags = String::new();
4554 if let Some(Expression::Literal(lit)) = ¶ms {
4555 if let Literal::String(p) = lit.as_ref() {
4556 flags = p.clone();
4557 }
4558 }
4559 let is_global = match &occurrence {
4560 Some(Expression::Literal(lit))
4561 if matches!(lit.as_ref(), Literal::Number(_)) =>
4562 {
4563 let Literal::Number(n) = lit.as_ref() else {
4564 unreachable!()
4565 };
4566 n == "0"
4567 }
4568 None => true,
4569 _ => false,
4570 };
4571 if is_global && !flags.contains('g') {
4572 flags.push('g');
4573 }
4574
4575 Ok(Expression::Function(Box::new(Function::new(
4576 "REGEXP_REPLACE".to_string(),
4577 vec![
4578 subject,
4579 pattern,
4580 replacement,
4581 Expression::Literal(Box::new(Literal::String(flags))),
4582 ],
4583 ))))
4584 }
4585
4586 "ROUND"
4588 if f.args
4589 .iter()
4590 .any(|a| matches!(a, Expression::NamedArgument(_))) =>
4591 {
4592 let mut expr_val = None;
4593 let mut scale_val = None;
4594 let mut rounding_mode = None;
4595 for arg in &f.args {
4596 if let Expression::NamedArgument(na) = arg {
4597 match na.name.name.to_uppercase().as_str() {
4598 "EXPR" => expr_val = Some(na.value.clone()),
4599 "SCALE" => scale_val = Some(na.value.clone()),
4600 "ROUNDING_MODE" => rounding_mode = Some(na.value.clone()),
4601 _ => {}
4602 }
4603 }
4604 }
4605 if let Some(expr) = expr_val {
4606 let scale = scale_val.unwrap_or(Expression::number(0));
4607 let is_half_to_even = match &rounding_mode {
4608 Some(Expression::Literal(lit))
4609 if matches!(lit.as_ref(), Literal::String(_)) =>
4610 {
4611 let Literal::String(s) = lit.as_ref() else {
4612 unreachable!()
4613 };
4614 s == "HALF_TO_EVEN"
4615 }
4616 _ => false,
4617 };
4618 if is_half_to_even {
4619 Ok(Expression::Function(Box::new(Function::new(
4620 "ROUND_EVEN".to_string(),
4621 vec![expr, scale],
4622 ))))
4623 } else {
4624 Ok(Expression::Function(Box::new(Function::new(
4625 "ROUND".to_string(),
4626 vec![expr, scale],
4627 ))))
4628 }
4629 } else {
4630 Ok(Expression::Function(Box::new(f)))
4631 }
4632 }
4633
4634 "ROUND" if f.args.len() == 3 => {
4637 let mut args = f.args;
4638 let x = args.remove(0);
4639 let scale = args.remove(0);
4640 let mode = args.remove(0);
4641 let is_half_to_even = match &mode {
4642 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4643 let Literal::String(s) = lit.as_ref() else {
4644 unreachable!()
4645 };
4646 s == "HALF_TO_EVEN"
4647 }
4648 _ => false,
4649 };
4650 if is_half_to_even {
4651 Ok(Expression::Function(Box::new(Function::new(
4652 "ROUND_EVEN".to_string(),
4653 vec![x, scale],
4654 ))))
4655 } else {
4656 Ok(Expression::Function(Box::new(Function::new(
4658 "ROUND".to_string(),
4659 vec![x, scale],
4660 ))))
4661 }
4662 }
4663
4664 "ROUND" if f.args.len() == 2 => {
4666 let mut args = f.args;
4667 let x = args.remove(0);
4668 let scale = args.remove(0);
4669 let needs_cast = match &scale {
4670 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4671 let Literal::Number(n) = lit.as_ref() else {
4672 unreachable!()
4673 };
4674 n.contains('.')
4675 }
4676 Expression::Cast(_) => {
4677 true
4679 }
4680 _ => false,
4681 };
4682 if needs_cast {
4683 Ok(Expression::Function(Box::new(Function::new(
4684 "ROUND".to_string(),
4685 vec![
4686 x,
4687 Expression::Cast(Box::new(Cast {
4688 this: scale,
4689 to: DataType::Int {
4690 length: None,
4691 integer_spelling: false,
4692 },
4693 trailing_comments: Vec::new(),
4694 double_colon_syntax: false,
4695 format: None,
4696 default: None,
4697 inferred_type: None,
4698 })),
4699 ],
4700 ))))
4701 } else {
4702 Ok(Expression::Function(Box::new(Function::new(
4703 "ROUND".to_string(),
4704 vec![x, scale],
4705 ))))
4706 }
4707 }
4708
4709 "FLOOR" if f.args.len() == 2 => {
4711 let mut args = f.args;
4712 let x = args.remove(0);
4713 let scale = args.remove(0);
4714 let needs_cast = match &scale {
4716 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4717 let Literal::Number(n) = lit.as_ref() else {
4718 unreachable!()
4719 };
4720 n.contains('.')
4721 }
4722 _ => false,
4723 };
4724 let int_scale = if needs_cast {
4725 Expression::Cast(Box::new(Cast {
4726 this: scale.clone(),
4727 to: DataType::Int {
4728 length: None,
4729 integer_spelling: false,
4730 },
4731 trailing_comments: Vec::new(),
4732 double_colon_syntax: false,
4733 format: None,
4734 default: None,
4735 inferred_type: None,
4736 }))
4737 } else {
4738 scale.clone()
4739 };
4740 let power_10 = Expression::Function(Box::new(Function::new(
4741 "POWER".to_string(),
4742 vec![Expression::number(10), int_scale.clone()],
4743 )));
4744 let x_paren = match &x {
4745 Expression::Add(_)
4746 | Expression::Sub(_)
4747 | Expression::Mul(_)
4748 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4749 this: x,
4750 trailing_comments: Vec::new(),
4751 })),
4752 _ => x,
4753 };
4754 let multiplied = Expression::Mul(Box::new(BinaryOp {
4755 left: x_paren,
4756 right: power_10.clone(),
4757 left_comments: Vec::new(),
4758 operator_comments: Vec::new(),
4759 trailing_comments: Vec::new(),
4760 inferred_type: None,
4761 }));
4762 let floored = Expression::Function(Box::new(Function::new(
4763 "FLOOR".to_string(),
4764 vec![multiplied],
4765 )));
4766 let divided = Expression::Div(Box::new(BinaryOp {
4767 left: floored,
4768 right: power_10,
4769 left_comments: Vec::new(),
4770 operator_comments: Vec::new(),
4771 trailing_comments: Vec::new(),
4772 inferred_type: None,
4773 }));
4774 Ok(Expression::Function(Box::new(Function::new(
4775 "ROUND".to_string(),
4776 vec![divided, int_scale],
4777 ))))
4778 }
4779
4780 "CEIL" | "CEILING" if f.args.len() == 2 => {
4782 let mut args = f.args;
4783 let x = args.remove(0);
4784 let scale = args.remove(0);
4785 let needs_cast = match &scale {
4786 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4787 let Literal::Number(n) = lit.as_ref() else {
4788 unreachable!()
4789 };
4790 n.contains('.')
4791 }
4792 _ => false,
4793 };
4794 let int_scale = if needs_cast {
4795 Expression::Cast(Box::new(Cast {
4796 this: scale.clone(),
4797 to: DataType::Int {
4798 length: None,
4799 integer_spelling: false,
4800 },
4801 trailing_comments: Vec::new(),
4802 double_colon_syntax: false,
4803 format: None,
4804 default: None,
4805 inferred_type: None,
4806 }))
4807 } else {
4808 scale.clone()
4809 };
4810 let power_10 = Expression::Function(Box::new(Function::new(
4811 "POWER".to_string(),
4812 vec![Expression::number(10), int_scale.clone()],
4813 )));
4814 let x_paren = match &x {
4815 Expression::Add(_)
4816 | Expression::Sub(_)
4817 | Expression::Mul(_)
4818 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4819 this: x,
4820 trailing_comments: Vec::new(),
4821 })),
4822 _ => x,
4823 };
4824 let multiplied = Expression::Mul(Box::new(BinaryOp {
4825 left: x_paren,
4826 right: power_10.clone(),
4827 left_comments: Vec::new(),
4828 operator_comments: Vec::new(),
4829 trailing_comments: Vec::new(),
4830 inferred_type: None,
4831 }));
4832 let ceiled = Expression::Function(Box::new(Function::new(
4833 "CEIL".to_string(),
4834 vec![multiplied],
4835 )));
4836 let divided = Expression::Div(Box::new(BinaryOp {
4837 left: ceiled,
4838 right: power_10,
4839 left_comments: Vec::new(),
4840 operator_comments: Vec::new(),
4841 trailing_comments: Vec::new(),
4842 inferred_type: None,
4843 }));
4844 Ok(Expression::Function(Box::new(Function::new(
4845 "ROUND".to_string(),
4846 vec![divided, int_scale],
4847 ))))
4848 }
4849
4850 "ADD_MONTHS" if f.args.len() == 2 => {
4852 let mut args = f.args;
4853 let date_expr_raw = args.remove(0);
4854 let months_expr = args.remove(0);
4855
4856 let was_string_literal = matches!(&date_expr_raw, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)));
4858
4859 let date_expr = match &date_expr_raw {
4861 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4862 Expression::Cast(Box::new(Cast {
4863 this: date_expr_raw,
4864 to: DataType::Timestamp {
4865 precision: None,
4866 timezone: false,
4867 },
4868 trailing_comments: Vec::new(),
4869 double_colon_syntax: false,
4870 format: None,
4871 default: None,
4872 inferred_type: None,
4873 }))
4874 }
4875 _ => date_expr_raw,
4876 };
4877
4878 let date_type = if was_string_literal {
4881 None
4882 } else {
4883 match &date_expr {
4884 Expression::Cast(c) => Some(c.to.clone()),
4885 _ => None,
4886 }
4887 };
4888
4889 let is_non_integer_months = match &months_expr {
4891 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4892 let Literal::Number(n) = lit.as_ref() else {
4893 unreachable!()
4894 };
4895 n.contains('.')
4896 }
4897 Expression::Neg(_) => {
4898 if let Expression::Neg(um) = &months_expr {
4899 matches!(&um.this, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(n) if n.contains('.')))
4900 } else {
4901 false
4902 }
4903 }
4904 Expression::Cast(c) => matches!(&c.to, DataType::Decimal { .. }),
4906 _ => false,
4907 };
4908
4909 let is_negative = match &months_expr {
4910 Expression::Neg(_) => true,
4911 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4912 let Literal::Number(n) = lit.as_ref() else {
4913 unreachable!()
4914 };
4915 n.starts_with('-')
4916 }
4917 _ => false,
4918 };
4919 let is_null = matches!(&months_expr, Expression::Null(_));
4920
4921 let interval_expr = if is_non_integer_months {
4922 Expression::Function(Box::new(Function::new(
4924 "TO_MONTHS".to_string(),
4925 vec![Expression::Cast(Box::new(Cast {
4926 this: Expression::Function(Box::new(Function::new(
4927 "ROUND".to_string(),
4928 vec![months_expr.clone()],
4929 ))),
4930 to: DataType::Int {
4931 length: None,
4932 integer_spelling: false,
4933 },
4934 trailing_comments: Vec::new(),
4935 double_colon_syntax: false,
4936 format: None,
4937 default: None,
4938 inferred_type: None,
4939 }))],
4940 )))
4941 } else if is_negative || is_null {
4942 Expression::Interval(Box::new(Interval {
4944 this: Some(Expression::Paren(Box::new(Paren {
4945 this: months_expr.clone(),
4946 trailing_comments: Vec::new(),
4947 }))),
4948 unit: Some(IntervalUnitSpec::Simple {
4949 unit: IntervalUnit::Month,
4950 use_plural: false,
4951 }),
4952 }))
4953 } else {
4954 Expression::Interval(Box::new(Interval {
4956 this: Some(months_expr.clone()),
4957 unit: Some(IntervalUnitSpec::Simple {
4958 unit: IntervalUnit::Month,
4959 use_plural: false,
4960 }),
4961 }))
4962 };
4963
4964 let date_plus_interval = Expression::Add(Box::new(BinaryOp {
4965 left: date_expr.clone(),
4966 right: interval_expr.clone(),
4967 left_comments: Vec::new(),
4968 operator_comments: Vec::new(),
4969 trailing_comments: Vec::new(),
4970 inferred_type: None,
4971 }));
4972
4973 let case_expr = Expression::Case(Box::new(Case {
4974 operand: None,
4975 whens: vec![(
4976 Expression::Eq(Box::new(BinaryOp {
4977 left: Expression::Function(Box::new(Function::new(
4978 "LAST_DAY".to_string(),
4979 vec![date_expr.clone()],
4980 ))),
4981 right: date_expr.clone(),
4982 left_comments: Vec::new(),
4983 operator_comments: Vec::new(),
4984 trailing_comments: Vec::new(),
4985 inferred_type: None,
4986 })),
4987 Expression::Function(Box::new(Function::new(
4988 "LAST_DAY".to_string(),
4989 vec![date_plus_interval.clone()],
4990 ))),
4991 )],
4992 else_: Some(date_plus_interval),
4993 comments: Vec::new(),
4994 inferred_type: None,
4995 }));
4996
4997 if let Some(dt) = date_type {
4999 Ok(Expression::Cast(Box::new(Cast {
5000 this: case_expr,
5001 to: dt,
5002 trailing_comments: Vec::new(),
5003 double_colon_syntax: false,
5004 format: None,
5005 default: None,
5006 inferred_type: None,
5007 })))
5008 } else {
5009 Ok(case_expr)
5010 }
5011 }
5012
5013 "TIME_SLICE" if f.args.len() >= 3 => {
5016 let mut args = f.args;
5017 let date_expr = args.remove(0);
5018 let n = args.remove(0);
5019 let unit_str = args.remove(0);
5020 let alignment = if !args.is_empty() {
5021 Some(args.remove(0))
5022 } else {
5023 None
5024 };
5025
5026 let unit = match &unit_str {
5028 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5029 let Literal::String(s) = lit.as_ref() else {
5030 unreachable!()
5031 };
5032 s.to_uppercase()
5033 }
5034 Expression::Column(c) => c.name.name.to_uppercase(),
5035 Expression::Identifier(i) => i.name.to_uppercase(),
5036 _ => "DAY".to_string(),
5037 };
5038
5039 let interval_unit = match unit.as_str() {
5040 "YEAR" => IntervalUnit::Year,
5041 "QUARTER" => IntervalUnit::Quarter,
5042 "MONTH" => IntervalUnit::Month,
5043 "WEEK" => IntervalUnit::Week,
5044 "DAY" => IntervalUnit::Day,
5045 "HOUR" => IntervalUnit::Hour,
5046 "MINUTE" => IntervalUnit::Minute,
5047 "SECOND" => IntervalUnit::Second,
5048 _ => IntervalUnit::Day,
5049 };
5050
5051 let interval = Expression::Interval(Box::new(Interval {
5052 this: Some(n.clone()),
5053 unit: Some(IntervalUnitSpec::Simple {
5054 unit: interval_unit.clone(),
5055 use_plural: false,
5056 }),
5057 }));
5058
5059 let time_bucket = Expression::Function(Box::new(Function::new(
5060 "TIME_BUCKET".to_string(),
5061 vec![interval.clone(), date_expr.clone()],
5062 )));
5063
5064 let is_end = match &alignment {
5065 Some(Expression::Literal(lit))
5066 if matches!(lit.as_ref(), Literal::String(_)) =>
5067 {
5068 let Literal::String(s) = lit.as_ref() else {
5069 unreachable!()
5070 };
5071 s.to_uppercase() == "END"
5072 }
5073 _ => false,
5074 };
5075
5076 let is_date_type = match &date_expr {
5078 Expression::Cast(c) => matches!(&c.to, DataType::Date),
5079 _ => false,
5080 };
5081
5082 if is_end {
5083 let bucket_plus = Expression::Add(Box::new(BinaryOp {
5084 left: time_bucket,
5085 right: Expression::Interval(Box::new(Interval {
5086 this: Some(n),
5087 unit: Some(IntervalUnitSpec::Simple {
5088 unit: interval_unit,
5089 use_plural: false,
5090 }),
5091 })),
5092 left_comments: Vec::new(),
5093 operator_comments: Vec::new(),
5094 trailing_comments: Vec::new(),
5095 inferred_type: None,
5096 }));
5097 if is_date_type {
5098 Ok(Expression::Cast(Box::new(Cast {
5099 this: bucket_plus,
5100 to: DataType::Date,
5101 trailing_comments: Vec::new(),
5102 double_colon_syntax: false,
5103 format: None,
5104 default: None,
5105 inferred_type: None,
5106 })))
5107 } else {
5108 Ok(bucket_plus)
5109 }
5110 } else {
5111 Ok(time_bucket)
5112 }
5113 }
5114
5115 "DATE_FROM_PARTS" | "DATEFROMPARTS" if f.args.len() == 3 => {
5117 let mut args = f.args;
5118 let year = args.remove(0);
5119 let month = args.remove(0);
5120 let day = args.remove(0);
5121
5122 let make_date = Expression::Function(Box::new(Function::new(
5123 "MAKE_DATE".to_string(),
5124 vec![year, Expression::number(1), Expression::number(1)],
5125 )));
5126
5127 let month_wrapped = match &month {
5129 Expression::Add(_)
5130 | Expression::Sub(_)
5131 | Expression::Mul(_)
5132 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
5133 this: month,
5134 trailing_comments: Vec::new(),
5135 })),
5136 _ => month,
5137 };
5138 let day_wrapped = match &day {
5139 Expression::Add(_)
5140 | Expression::Sub(_)
5141 | Expression::Mul(_)
5142 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
5143 this: day,
5144 trailing_comments: Vec::new(),
5145 })),
5146 _ => day,
5147 };
5148 let month_minus_1 = Expression::Sub(Box::new(BinaryOp {
5149 left: month_wrapped,
5150 right: Expression::number(1),
5151 left_comments: Vec::new(),
5152 operator_comments: Vec::new(),
5153 trailing_comments: Vec::new(),
5154 inferred_type: None,
5155 }));
5156 let month_interval = Expression::Interval(Box::new(Interval {
5157 this: Some(Expression::Paren(Box::new(Paren {
5158 this: month_minus_1,
5159 trailing_comments: Vec::new(),
5160 }))),
5161 unit: Some(IntervalUnitSpec::Simple {
5162 unit: IntervalUnit::Month,
5163 use_plural: false,
5164 }),
5165 }));
5166
5167 let day_minus_1 = Expression::Sub(Box::new(BinaryOp {
5168 left: day_wrapped,
5169 right: Expression::number(1),
5170 left_comments: Vec::new(),
5171 operator_comments: Vec::new(),
5172 trailing_comments: Vec::new(),
5173 inferred_type: None,
5174 }));
5175 let day_interval = Expression::Interval(Box::new(Interval {
5176 this: Some(Expression::Paren(Box::new(Paren {
5177 this: day_minus_1,
5178 trailing_comments: Vec::new(),
5179 }))),
5180 unit: Some(IntervalUnitSpec::Simple {
5181 unit: IntervalUnit::Day,
5182 use_plural: false,
5183 }),
5184 }));
5185
5186 let result = Expression::Add(Box::new(BinaryOp {
5187 left: Expression::Add(Box::new(BinaryOp {
5188 left: make_date,
5189 right: month_interval,
5190 left_comments: Vec::new(),
5191 operator_comments: Vec::new(),
5192 trailing_comments: Vec::new(),
5193 inferred_type: None,
5194 })),
5195 right: day_interval,
5196 left_comments: Vec::new(),
5197 operator_comments: Vec::new(),
5198 trailing_comments: Vec::new(),
5199 inferred_type: None,
5200 }));
5201
5202 Ok(Expression::Cast(Box::new(Cast {
5203 this: result,
5204 to: DataType::Date,
5205 trailing_comments: Vec::new(),
5206 double_colon_syntax: false,
5207 format: None,
5208 default: None,
5209 inferred_type: None,
5210 })))
5211 }
5212
5213 "NEXT_DAY" if f.args.len() == 2 => {
5215 let mut args = f.args;
5216 let date = args.remove(0);
5217 let day_name = args.remove(0);
5218
5219 let day_num = match &day_name {
5221 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5222 let Literal::String(s) = lit.as_ref() else {
5223 unreachable!()
5224 };
5225 let upper = s.to_uppercase();
5226 if upper.starts_with("MO") {
5227 Some(1)
5228 } else if upper.starts_with("TU") {
5229 Some(2)
5230 } else if upper.starts_with("WE") {
5231 Some(3)
5232 } else if upper.starts_with("TH") {
5233 Some(4)
5234 } else if upper.starts_with("FR") {
5235 Some(5)
5236 } else if upper.starts_with("SA") {
5237 Some(6)
5238 } else if upper.starts_with("SU") {
5239 Some(7)
5240 } else {
5241 None
5242 }
5243 }
5244 _ => None,
5245 };
5246
5247 let target_day_expr = if let Some(n) = day_num {
5248 Expression::number(n)
5249 } else {
5250 Expression::Case(Box::new(Case {
5252 operand: None,
5253 whens: vec![
5254 (
5255 Expression::Function(Box::new(Function::new(
5256 "STARTS_WITH".to_string(),
5257 vec![
5258 Expression::Upper(Box::new(UnaryFunc::new(
5259 day_name.clone(),
5260 ))),
5261 Expression::Literal(Box::new(Literal::String(
5262 "MO".to_string(),
5263 ))),
5264 ],
5265 ))),
5266 Expression::number(1),
5267 ),
5268 (
5269 Expression::Function(Box::new(Function::new(
5270 "STARTS_WITH".to_string(),
5271 vec![
5272 Expression::Upper(Box::new(UnaryFunc::new(
5273 day_name.clone(),
5274 ))),
5275 Expression::Literal(Box::new(Literal::String(
5276 "TU".to_string(),
5277 ))),
5278 ],
5279 ))),
5280 Expression::number(2),
5281 ),
5282 (
5283 Expression::Function(Box::new(Function::new(
5284 "STARTS_WITH".to_string(),
5285 vec![
5286 Expression::Upper(Box::new(UnaryFunc::new(
5287 day_name.clone(),
5288 ))),
5289 Expression::Literal(Box::new(Literal::String(
5290 "WE".to_string(),
5291 ))),
5292 ],
5293 ))),
5294 Expression::number(3),
5295 ),
5296 (
5297 Expression::Function(Box::new(Function::new(
5298 "STARTS_WITH".to_string(),
5299 vec![
5300 Expression::Upper(Box::new(UnaryFunc::new(
5301 day_name.clone(),
5302 ))),
5303 Expression::Literal(Box::new(Literal::String(
5304 "TH".to_string(),
5305 ))),
5306 ],
5307 ))),
5308 Expression::number(4),
5309 ),
5310 (
5311 Expression::Function(Box::new(Function::new(
5312 "STARTS_WITH".to_string(),
5313 vec![
5314 Expression::Upper(Box::new(UnaryFunc::new(
5315 day_name.clone(),
5316 ))),
5317 Expression::Literal(Box::new(Literal::String(
5318 "FR".to_string(),
5319 ))),
5320 ],
5321 ))),
5322 Expression::number(5),
5323 ),
5324 (
5325 Expression::Function(Box::new(Function::new(
5326 "STARTS_WITH".to_string(),
5327 vec![
5328 Expression::Upper(Box::new(UnaryFunc::new(
5329 day_name.clone(),
5330 ))),
5331 Expression::Literal(Box::new(Literal::String(
5332 "SA".to_string(),
5333 ))),
5334 ],
5335 ))),
5336 Expression::number(6),
5337 ),
5338 (
5339 Expression::Function(Box::new(Function::new(
5340 "STARTS_WITH".to_string(),
5341 vec![
5342 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
5343 Expression::Literal(Box::new(Literal::String(
5344 "SU".to_string(),
5345 ))),
5346 ],
5347 ))),
5348 Expression::number(7),
5349 ),
5350 ],
5351 else_: None,
5352 comments: Vec::new(),
5353 inferred_type: None,
5354 }))
5355 };
5356
5357 let isodow = Expression::Function(Box::new(Function::new(
5358 "ISODOW".to_string(),
5359 vec![date.clone()],
5360 )));
5361 let diff = Expression::Add(Box::new(BinaryOp {
5363 left: Expression::Paren(Box::new(Paren {
5364 this: Expression::Mod(Box::new(BinaryOp {
5365 left: Expression::Paren(Box::new(Paren {
5366 this: Expression::Add(Box::new(BinaryOp {
5367 left: Expression::Paren(Box::new(Paren {
5368 this: Expression::Sub(Box::new(BinaryOp {
5369 left: target_day_expr,
5370 right: isodow,
5371 left_comments: Vec::new(),
5372 operator_comments: Vec::new(),
5373 trailing_comments: Vec::new(),
5374 inferred_type: None,
5375 })),
5376 trailing_comments: Vec::new(),
5377 })),
5378 right: Expression::number(6),
5379 left_comments: Vec::new(),
5380 operator_comments: Vec::new(),
5381 trailing_comments: Vec::new(),
5382 inferred_type: None,
5383 })),
5384 trailing_comments: Vec::new(),
5385 })),
5386 right: Expression::number(7),
5387 left_comments: Vec::new(),
5388 operator_comments: Vec::new(),
5389 trailing_comments: Vec::new(),
5390 inferred_type: None,
5391 })),
5392 trailing_comments: Vec::new(),
5393 })),
5394 right: Expression::number(1),
5395 left_comments: Vec::new(),
5396 operator_comments: Vec::new(),
5397 trailing_comments: Vec::new(),
5398 inferred_type: None,
5399 }));
5400
5401 let result = Expression::Add(Box::new(BinaryOp {
5402 left: date,
5403 right: Expression::Interval(Box::new(Interval {
5404 this: Some(Expression::Paren(Box::new(Paren {
5405 this: diff,
5406 trailing_comments: Vec::new(),
5407 }))),
5408 unit: Some(IntervalUnitSpec::Simple {
5409 unit: IntervalUnit::Day,
5410 use_plural: false,
5411 }),
5412 })),
5413 left_comments: Vec::new(),
5414 operator_comments: Vec::new(),
5415 trailing_comments: Vec::new(),
5416 inferred_type: None,
5417 }));
5418
5419 Ok(Expression::Cast(Box::new(Cast {
5420 this: result,
5421 to: DataType::Date,
5422 trailing_comments: Vec::new(),
5423 double_colon_syntax: false,
5424 format: None,
5425 default: None,
5426 inferred_type: None,
5427 })))
5428 }
5429
5430 "PREVIOUS_DAY" if f.args.len() == 2 => {
5432 let mut args = f.args;
5433 let date = args.remove(0);
5434 let day_name = args.remove(0);
5435
5436 let day_num = match &day_name {
5437 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5438 let Literal::String(s) = lit.as_ref() else {
5439 unreachable!()
5440 };
5441 let upper = s.to_uppercase();
5442 if upper.starts_with("MO") {
5443 Some(1)
5444 } else if upper.starts_with("TU") {
5445 Some(2)
5446 } else if upper.starts_with("WE") {
5447 Some(3)
5448 } else if upper.starts_with("TH") {
5449 Some(4)
5450 } else if upper.starts_with("FR") {
5451 Some(5)
5452 } else if upper.starts_with("SA") {
5453 Some(6)
5454 } else if upper.starts_with("SU") {
5455 Some(7)
5456 } else {
5457 None
5458 }
5459 }
5460 _ => None,
5461 };
5462
5463 let target_day_expr = if let Some(n) = day_num {
5464 Expression::number(n)
5465 } else {
5466 Expression::Case(Box::new(Case {
5467 operand: None,
5468 whens: vec![
5469 (
5470 Expression::Function(Box::new(Function::new(
5471 "STARTS_WITH".to_string(),
5472 vec![
5473 Expression::Upper(Box::new(UnaryFunc::new(
5474 day_name.clone(),
5475 ))),
5476 Expression::Literal(Box::new(Literal::String(
5477 "MO".to_string(),
5478 ))),
5479 ],
5480 ))),
5481 Expression::number(1),
5482 ),
5483 (
5484 Expression::Function(Box::new(Function::new(
5485 "STARTS_WITH".to_string(),
5486 vec![
5487 Expression::Upper(Box::new(UnaryFunc::new(
5488 day_name.clone(),
5489 ))),
5490 Expression::Literal(Box::new(Literal::String(
5491 "TU".to_string(),
5492 ))),
5493 ],
5494 ))),
5495 Expression::number(2),
5496 ),
5497 (
5498 Expression::Function(Box::new(Function::new(
5499 "STARTS_WITH".to_string(),
5500 vec![
5501 Expression::Upper(Box::new(UnaryFunc::new(
5502 day_name.clone(),
5503 ))),
5504 Expression::Literal(Box::new(Literal::String(
5505 "WE".to_string(),
5506 ))),
5507 ],
5508 ))),
5509 Expression::number(3),
5510 ),
5511 (
5512 Expression::Function(Box::new(Function::new(
5513 "STARTS_WITH".to_string(),
5514 vec![
5515 Expression::Upper(Box::new(UnaryFunc::new(
5516 day_name.clone(),
5517 ))),
5518 Expression::Literal(Box::new(Literal::String(
5519 "TH".to_string(),
5520 ))),
5521 ],
5522 ))),
5523 Expression::number(4),
5524 ),
5525 (
5526 Expression::Function(Box::new(Function::new(
5527 "STARTS_WITH".to_string(),
5528 vec![
5529 Expression::Upper(Box::new(UnaryFunc::new(
5530 day_name.clone(),
5531 ))),
5532 Expression::Literal(Box::new(Literal::String(
5533 "FR".to_string(),
5534 ))),
5535 ],
5536 ))),
5537 Expression::number(5),
5538 ),
5539 (
5540 Expression::Function(Box::new(Function::new(
5541 "STARTS_WITH".to_string(),
5542 vec![
5543 Expression::Upper(Box::new(UnaryFunc::new(
5544 day_name.clone(),
5545 ))),
5546 Expression::Literal(Box::new(Literal::String(
5547 "SA".to_string(),
5548 ))),
5549 ],
5550 ))),
5551 Expression::number(6),
5552 ),
5553 (
5554 Expression::Function(Box::new(Function::new(
5555 "STARTS_WITH".to_string(),
5556 vec![
5557 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
5558 Expression::Literal(Box::new(Literal::String(
5559 "SU".to_string(),
5560 ))),
5561 ],
5562 ))),
5563 Expression::number(7),
5564 ),
5565 ],
5566 else_: None,
5567 comments: Vec::new(),
5568 inferred_type: None,
5569 }))
5570 };
5571
5572 let isodow = Expression::Function(Box::new(Function::new(
5573 "ISODOW".to_string(),
5574 vec![date.clone()],
5575 )));
5576 let diff = Expression::Add(Box::new(BinaryOp {
5578 left: Expression::Paren(Box::new(Paren {
5579 this: Expression::Mod(Box::new(BinaryOp {
5580 left: Expression::Paren(Box::new(Paren {
5581 this: Expression::Add(Box::new(BinaryOp {
5582 left: Expression::Paren(Box::new(Paren {
5583 this: Expression::Sub(Box::new(BinaryOp {
5584 left: isodow,
5585 right: target_day_expr,
5586 left_comments: Vec::new(),
5587 operator_comments: Vec::new(),
5588 trailing_comments: Vec::new(),
5589 inferred_type: None,
5590 })),
5591 trailing_comments: Vec::new(),
5592 })),
5593 right: Expression::number(6),
5594 left_comments: Vec::new(),
5595 operator_comments: Vec::new(),
5596 trailing_comments: Vec::new(),
5597 inferred_type: None,
5598 })),
5599 trailing_comments: Vec::new(),
5600 })),
5601 right: Expression::number(7),
5602 left_comments: Vec::new(),
5603 operator_comments: Vec::new(),
5604 trailing_comments: Vec::new(),
5605 inferred_type: None,
5606 })),
5607 trailing_comments: Vec::new(),
5608 })),
5609 right: Expression::number(1),
5610 left_comments: Vec::new(),
5611 operator_comments: Vec::new(),
5612 trailing_comments: Vec::new(),
5613 inferred_type: None,
5614 }));
5615
5616 let result = Expression::Sub(Box::new(BinaryOp {
5617 left: date,
5618 right: Expression::Interval(Box::new(Interval {
5619 this: Some(Expression::Paren(Box::new(Paren {
5620 this: diff,
5621 trailing_comments: Vec::new(),
5622 }))),
5623 unit: Some(IntervalUnitSpec::Simple {
5624 unit: IntervalUnit::Day,
5625 use_plural: false,
5626 }),
5627 })),
5628 left_comments: Vec::new(),
5629 operator_comments: Vec::new(),
5630 trailing_comments: Vec::new(),
5631 inferred_type: None,
5632 }));
5633
5634 Ok(Expression::Cast(Box::new(Cast {
5635 this: result,
5636 to: DataType::Date,
5637 trailing_comments: Vec::new(),
5638 double_colon_syntax: false,
5639 format: None,
5640 default: None,
5641 inferred_type: None,
5642 })))
5643 }
5644
5645 "LAST_DAY" if f.args.len() == 2 => {
5649 let mut args = f.args;
5650 let date = args.remove(0);
5651 let unit = args.remove(0);
5652 let unit_str = match &unit {
5653 Expression::Column(c) => c.name.name.to_uppercase(),
5654 Expression::Identifier(i) => i.name.to_uppercase(),
5655 _ => String::new(),
5656 };
5657
5658 match unit_str.as_str() {
5659 "MONTH" => Ok(Expression::Function(Box::new(Function::new(
5660 "LAST_DAY".to_string(),
5661 vec![date],
5662 )))),
5663 "YEAR" => Ok(Expression::Function(Box::new(Function::new(
5664 "MAKE_DATE".to_string(),
5665 vec![
5666 Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5667 this: date,
5668 field: crate::expressions::DateTimeField::Year,
5669 })),
5670 Expression::number(12),
5671 Expression::number(31),
5672 ],
5673 )))),
5674 "QUARTER" => {
5675 let year = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5676 this: date.clone(),
5677 field: crate::expressions::DateTimeField::Year,
5678 }));
5679 let quarter_month = Expression::Mul(Box::new(BinaryOp {
5680 left: Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5681 this: date,
5682 field: crate::expressions::DateTimeField::Custom(
5683 "QUARTER".to_string(),
5684 ),
5685 })),
5686 right: Expression::number(3),
5687 left_comments: Vec::new(),
5688 operator_comments: Vec::new(),
5689 trailing_comments: Vec::new(),
5690 inferred_type: None,
5691 }));
5692 let make_date = Expression::Function(Box::new(Function::new(
5693 "MAKE_DATE".to_string(),
5694 vec![year, quarter_month, Expression::number(1)],
5695 )));
5696 Ok(Expression::Function(Box::new(Function::new(
5697 "LAST_DAY".to_string(),
5698 vec![make_date],
5699 ))))
5700 }
5701 "WEEK" => {
5702 let dow = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5703 this: date.clone(),
5704 field: crate::expressions::DateTimeField::Custom(
5705 "DAYOFWEEK".to_string(),
5706 ),
5707 }));
5708 let diff = Expression::Mod(Box::new(BinaryOp {
5709 left: Expression::Paren(Box::new(Paren {
5710 this: Expression::Sub(Box::new(BinaryOp {
5711 left: Expression::number(7),
5712 right: dow,
5713 left_comments: Vec::new(),
5714 operator_comments: Vec::new(),
5715 trailing_comments: Vec::new(),
5716 inferred_type: None,
5717 })),
5718 trailing_comments: Vec::new(),
5719 })),
5720 right: Expression::number(7),
5721 left_comments: Vec::new(),
5722 operator_comments: Vec::new(),
5723 trailing_comments: Vec::new(),
5724 inferred_type: None,
5725 }));
5726 let result = Expression::Add(Box::new(BinaryOp {
5727 left: date,
5728 right: Expression::Interval(Box::new(Interval {
5729 this: Some(Expression::Paren(Box::new(Paren {
5730 this: diff,
5731 trailing_comments: Vec::new(),
5732 }))),
5733 unit: Some(IntervalUnitSpec::Simple {
5734 unit: IntervalUnit::Day,
5735 use_plural: false,
5736 }),
5737 })),
5738 left_comments: Vec::new(),
5739 operator_comments: Vec::new(),
5740 trailing_comments: Vec::new(),
5741 inferred_type: None,
5742 }));
5743 Ok(Expression::Cast(Box::new(Cast {
5744 this: result,
5745 to: DataType::Date,
5746 trailing_comments: Vec::new(),
5747 double_colon_syntax: false,
5748 format: None,
5749 default: None,
5750 inferred_type: None,
5751 })))
5752 }
5753 _ => Ok(Expression::Function(Box::new(Function::new(
5754 "LAST_DAY".to_string(),
5755 vec![date, unit],
5756 )))),
5757 }
5758 }
5759
5760 "SEQ1" | "SEQ2" | "SEQ4" | "SEQ8" => {
5763 let (range, half): (u128, u128) = match name_upper.as_str() {
5764 "SEQ1" => (256, 128),
5765 "SEQ2" => (65536, 32768),
5766 "SEQ4" => (4294967296, 2147483648),
5767 "SEQ8" => (18446744073709551616, 9223372036854775808),
5768 _ => unreachable!("sequence type already matched in caller"),
5769 };
5770
5771 let is_signed = match f.args.first() {
5772 Some(Expression::Literal(lit))
5773 if matches!(lit.as_ref(), Literal::Number(_)) =>
5774 {
5775 let Literal::Number(n) = lit.as_ref() else {
5776 unreachable!()
5777 };
5778 n == "1"
5779 }
5780 _ => false,
5781 };
5782
5783 let row_num = Expression::Sub(Box::new(BinaryOp {
5784 left: Expression::WindowFunction(Box::new(
5785 crate::expressions::WindowFunction {
5786 this: Expression::Function(Box::new(Function::new(
5787 "ROW_NUMBER".to_string(),
5788 vec![],
5789 ))),
5790 over: crate::expressions::Over {
5791 window_name: None,
5792 partition_by: vec![],
5793 order_by: vec![crate::expressions::Ordered {
5794 this: Expression::number(1),
5795 desc: false,
5796 nulls_first: Some(true),
5797 explicit_asc: false,
5798 with_fill: None,
5799 }],
5800 frame: None,
5801 alias: None,
5802 },
5803 keep: None,
5804 inferred_type: None,
5805 },
5806 )),
5807 right: Expression::number(1),
5808 left_comments: Vec::new(),
5809 operator_comments: Vec::new(),
5810 trailing_comments: Vec::new(),
5811 inferred_type: None,
5812 }));
5813
5814 let modded = Expression::Mod(Box::new(BinaryOp {
5815 left: Expression::Paren(Box::new(Paren {
5816 this: row_num,
5817 trailing_comments: Vec::new(),
5818 })),
5819 right: Expression::Literal(Box::new(Literal::Number(range.to_string()))),
5820 left_comments: Vec::new(),
5821 operator_comments: Vec::new(),
5822 trailing_comments: Vec::new(),
5823 inferred_type: None,
5824 }));
5825
5826 if is_signed {
5827 let cond = Expression::Gte(Box::new(BinaryOp {
5829 left: modded.clone(),
5830 right: Expression::Literal(Box::new(Literal::Number(half.to_string()))),
5831 left_comments: Vec::new(),
5832 operator_comments: Vec::new(),
5833 trailing_comments: Vec::new(),
5834 inferred_type: None,
5835 }));
5836 let signed_val = Expression::Sub(Box::new(BinaryOp {
5837 left: modded.clone(),
5838 right: Expression::Literal(Box::new(Literal::Number(range.to_string()))),
5839 left_comments: Vec::new(),
5840 operator_comments: Vec::new(),
5841 trailing_comments: Vec::new(),
5842 inferred_type: None,
5843 }));
5844 Ok(Expression::Paren(Box::new(Paren {
5845 this: Expression::Case(Box::new(Case {
5846 operand: None,
5847 whens: vec![(cond, signed_val)],
5848 else_: Some(modded),
5849 comments: Vec::new(),
5850 inferred_type: None,
5851 })),
5852 trailing_comments: Vec::new(),
5853 })))
5854 } else {
5855 Ok(modded)
5856 }
5857 }
5858
5859 "TABLE" if f.args.len() == 1 => {
5862 let inner = f.args.into_iter().next().unwrap();
5863 if let Expression::Function(ref gen_f) = inner {
5865 if gen_f.name.to_uppercase() == "GENERATOR" {
5866 let mut rowcount = None;
5867 for arg in &gen_f.args {
5868 if let Expression::NamedArgument(na) = arg {
5869 if na.name.name.to_uppercase() == "ROWCOUNT" {
5870 rowcount = Some(na.value.clone());
5871 }
5872 }
5873 }
5874 if let Some(n) = rowcount {
5875 return Ok(Expression::Function(Box::new(Function::new(
5876 "RANGE".to_string(),
5877 vec![n],
5878 ))));
5879 }
5880 }
5881 }
5882 Ok(inner)
5883 }
5884
5885 "GENERATOR" => {
5887 let mut rowcount = None;
5888 for arg in &f.args {
5889 if let Expression::NamedArgument(na) = arg {
5890 if na.name.name.to_uppercase() == "ROWCOUNT" {
5891 rowcount = Some(na.value.clone());
5892 }
5893 }
5894 }
5895 if let Some(n) = rowcount {
5896 Ok(Expression::Function(Box::new(Function::new(
5897 "RANGE".to_string(),
5898 vec![n],
5899 ))))
5900 } else {
5901 Ok(Expression::Function(Box::new(f)))
5902 }
5903 }
5904
5905 "UNIFORM" if f.args.len() == 3 => {
5908 let mut args = f.args;
5909 let low = args.remove(0);
5910 let high = args.remove(0);
5911 let gen = args.remove(0);
5912
5913 let range = Expression::Add(Box::new(BinaryOp {
5914 left: Expression::Sub(Box::new(BinaryOp {
5915 left: high,
5916 right: low.clone(),
5917 left_comments: Vec::new(),
5918 operator_comments: Vec::new(),
5919 trailing_comments: Vec::new(),
5920 inferred_type: None,
5921 })),
5922 right: Expression::number(1),
5923 left_comments: Vec::new(),
5924 operator_comments: Vec::new(),
5925 trailing_comments: Vec::new(),
5926 inferred_type: None,
5927 }));
5928
5929 let random_val = match &gen {
5931 Expression::Rand(_) | Expression::Random(_) => {
5932 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5934 }
5935 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
5936 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5938 }
5939 _ => {
5940 let hash = Expression::Function(Box::new(Function::new(
5942 "HASH".to_string(),
5943 vec![gen],
5944 )));
5945 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
5946 let modded = Expression::Mod(Box::new(BinaryOp {
5947 left: abs_hash,
5948 right: Expression::number(1000000),
5949 left_comments: Vec::new(),
5950 operator_comments: Vec::new(),
5951 trailing_comments: Vec::new(),
5952 inferred_type: None,
5953 }));
5954 let paren_modded = Expression::Paren(Box::new(Paren {
5955 this: modded,
5956 trailing_comments: Vec::new(),
5957 }));
5958 Expression::Div(Box::new(BinaryOp {
5959 left: paren_modded,
5960 right: Expression::Literal(Box::new(Literal::Number(
5961 "1000000.0".to_string(),
5962 ))),
5963 left_comments: Vec::new(),
5964 operator_comments: Vec::new(),
5965 trailing_comments: Vec::new(),
5966 inferred_type: None,
5967 }))
5968 }
5969 };
5970
5971 let inner = Expression::Function(Box::new(Function::new(
5972 "FLOOR".to_string(),
5973 vec![Expression::Add(Box::new(BinaryOp {
5974 left: low,
5975 right: Expression::Mul(Box::new(BinaryOp {
5976 left: random_val,
5977 right: Expression::Paren(Box::new(Paren {
5978 this: range,
5979 trailing_comments: Vec::new(),
5980 })),
5981 left_comments: Vec::new(),
5982 operator_comments: Vec::new(),
5983 trailing_comments: Vec::new(),
5984 inferred_type: None,
5985 })),
5986 left_comments: Vec::new(),
5987 operator_comments: Vec::new(),
5988 trailing_comments: Vec::new(),
5989 inferred_type: None,
5990 }))],
5991 )));
5992
5993 Ok(Expression::Cast(Box::new(Cast {
5994 this: inner,
5995 to: DataType::BigInt { length: None },
5996 trailing_comments: Vec::new(),
5997 double_colon_syntax: false,
5998 format: None,
5999 default: None,
6000 inferred_type: None,
6001 })))
6002 }
6003
6004 "NORMAL" if f.args.len() == 3 => {
6008 let mut args = f.args;
6009 let mean = args.remove(0);
6010 let stddev = args.remove(0);
6011 let gen = args.remove(0);
6012
6013 let make_seed_random = |seed: Expression| -> Expression {
6015 let hash = Expression::Function(Box::new(Function::new(
6016 "HASH".to_string(),
6017 vec![seed],
6018 )));
6019 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
6020 let modded = Expression::Mod(Box::new(BinaryOp {
6021 left: abs_hash,
6022 right: Expression::number(1000000),
6023 left_comments: Vec::new(),
6024 operator_comments: Vec::new(),
6025 trailing_comments: Vec::new(),
6026 inferred_type: None,
6027 }));
6028 let paren_modded = Expression::Paren(Box::new(Paren {
6029 this: modded,
6030 trailing_comments: Vec::new(),
6031 }));
6032 Expression::Div(Box::new(BinaryOp {
6033 left: paren_modded,
6034 right: Expression::Literal(Box::new(Literal::Number(
6035 "1000000.0".to_string(),
6036 ))),
6037 left_comments: Vec::new(),
6038 operator_comments: Vec::new(),
6039 trailing_comments: Vec::new(),
6040 inferred_type: None,
6041 }))
6042 };
6043
6044 let is_random_no_seed = match &gen {
6046 Expression::Random(_) => true,
6047 Expression::Rand(r) => r.seed.is_none(),
6048 _ => false,
6049 };
6050 let (u1, u2) = if is_random_no_seed {
6051 let u1 =
6053 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
6054 let u2 =
6055 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
6056 (u1, u2)
6057 } else {
6058 let seed = match gen {
6060 Expression::Rand(r) => r.seed.map(|s| *s).unwrap_or(Expression::number(0)),
6061 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
6062 if func.args.len() == 1 {
6063 func.args.into_iter().next().unwrap()
6064 } else {
6065 Expression::number(0)
6066 }
6067 }
6068 other => other,
6069 };
6070 let u1 = make_seed_random(seed.clone());
6071 let seed_plus_1 = Expression::Add(Box::new(BinaryOp {
6072 left: seed,
6073 right: Expression::number(1),
6074 left_comments: Vec::new(),
6075 operator_comments: Vec::new(),
6076 trailing_comments: Vec::new(),
6077 inferred_type: None,
6078 }));
6079 let u2 = make_seed_random(seed_plus_1);
6080 (u1, u2)
6081 };
6082
6083 let greatest = Expression::Greatest(Box::new(VarArgFunc {
6085 expressions: vec![
6086 u1,
6087 Expression::Literal(Box::new(Literal::Number("1e-10".to_string()))),
6088 ],
6089 original_name: None,
6090 inferred_type: None,
6091 }));
6092
6093 let neg2 = Expression::Neg(Box::new(crate::expressions::UnaryOp {
6095 this: Expression::number(2),
6096 inferred_type: None,
6097 }));
6098 let ln_greatest =
6099 Expression::Function(Box::new(Function::new("LN".to_string(), vec![greatest])));
6100 let neg2_times_ln = Expression::Mul(Box::new(BinaryOp {
6101 left: neg2,
6102 right: ln_greatest,
6103 left_comments: Vec::new(),
6104 operator_comments: Vec::new(),
6105 trailing_comments: Vec::new(),
6106 inferred_type: None,
6107 }));
6108 let sqrt_part = Expression::Function(Box::new(Function::new(
6109 "SQRT".to_string(),
6110 vec![neg2_times_ln],
6111 )));
6112
6113 let pi = Expression::Function(Box::new(Function::new("PI".to_string(), vec![])));
6115 let two_pi = Expression::Mul(Box::new(BinaryOp {
6116 left: Expression::number(2),
6117 right: pi,
6118 left_comments: Vec::new(),
6119 operator_comments: Vec::new(),
6120 trailing_comments: Vec::new(),
6121 inferred_type: None,
6122 }));
6123 let two_pi_u2 = Expression::Mul(Box::new(BinaryOp {
6124 left: two_pi,
6125 right: u2,
6126 left_comments: Vec::new(),
6127 operator_comments: Vec::new(),
6128 trailing_comments: Vec::new(),
6129 inferred_type: None,
6130 }));
6131 let cos_part = Expression::Function(Box::new(Function::new(
6132 "COS".to_string(),
6133 vec![two_pi_u2],
6134 )));
6135
6136 let stddev_times_sqrt = Expression::Mul(Box::new(BinaryOp {
6138 left: stddev,
6139 right: sqrt_part,
6140 left_comments: Vec::new(),
6141 operator_comments: Vec::new(),
6142 trailing_comments: Vec::new(),
6143 inferred_type: None,
6144 }));
6145 let inner = Expression::Mul(Box::new(BinaryOp {
6146 left: stddev_times_sqrt,
6147 right: cos_part,
6148 left_comments: Vec::new(),
6149 operator_comments: Vec::new(),
6150 trailing_comments: Vec::new(),
6151 inferred_type: None,
6152 }));
6153 let paren_inner = Expression::Paren(Box::new(Paren {
6154 this: inner,
6155 trailing_comments: Vec::new(),
6156 }));
6157
6158 Ok(Expression::Add(Box::new(BinaryOp {
6160 left: mean,
6161 right: paren_inner,
6162 left_comments: Vec::new(),
6163 operator_comments: Vec::new(),
6164 trailing_comments: Vec::new(),
6165 inferred_type: None,
6166 })))
6167 }
6168
6169 "ZIPF" if f.args.len() == 3 => {
6179 let mut args = f.args;
6180 let s_expr = args.remove(0);
6181 let n_expr = args.remove(0);
6182 let gen_expr = args.remove(0);
6183
6184 let s_sql = Self::expr_to_sql(&s_expr);
6185 let n_sql = Self::expr_to_sql(&n_expr);
6186 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
6187
6188 let rand_sql = if is_random {
6189 format!("SELECT {} AS r", seed_sql)
6190 } else {
6191 format!(
6192 "SELECT (ABS(HASH({})) % 1000000) / 1000000.0 AS r",
6193 seed_sql
6194 )
6195 };
6196
6197 let template = format!(
6198 "WITH rand AS ({}), weights AS (SELECT i, 1.0 / POWER(i, {}) AS w FROM RANGE(1, {} + 1) AS t(i)), cdf AS (SELECT i, SUM(w) OVER (ORDER BY i NULLS FIRST) / SUM(w) OVER () AS p FROM weights) SELECT MIN(i) FROM cdf WHERE p >= (SELECT r FROM rand)",
6199 rand_sql, s_sql, n_sql
6200 );
6201
6202 Self::parse_as_subquery(&template)
6203 }
6204
6205 "RANDSTR" if f.args.len() == 2 => {
6207 let mut args = f.args;
6208 let len_expr = args.remove(0);
6209 let gen_expr = args.remove(0);
6210
6211 let len_sql = Self::expr_to_sql(&len_expr);
6212 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
6213
6214 let random_value_sql = if is_random {
6215 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
6216 } else {
6217 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
6218 };
6219
6220 let template = format!(
6221 "SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT {} AS random_value FROM RANGE({}) AS t(i))",
6222 random_value_sql, len_sql
6223 );
6224
6225 Self::parse_as_subquery(&template)
6226 }
6227
6228 "MAP_CAT" if f.args.len() == 2 => {
6230 let mut args = f.args;
6231 let left = Self::normalize_empty_map_expr(args.remove(0));
6232 let right = Self::normalize_empty_map_expr(args.remove(0));
6233 let left_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6234 this: left.clone(),
6235 not: false,
6236 postfix_form: false,
6237 }));
6238 let right_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6239 this: right.clone(),
6240 not: false,
6241 postfix_form: false,
6242 }));
6243 let null_cond = Expression::Or(Box::new(BinaryOp {
6244 left: left_is_null,
6245 right: right_is_null,
6246 left_comments: Vec::new(),
6247 operator_comments: Vec::new(),
6248 trailing_comments: Vec::new(),
6249 inferred_type: None,
6250 }));
6251
6252 let list_concat = Expression::Function(Box::new(Function::new(
6253 "LIST_CONCAT".to_string(),
6254 vec![
6255 Expression::Function(Box::new(Function::new(
6256 "MAP_KEYS".to_string(),
6257 vec![left.clone()],
6258 ))),
6259 Expression::Function(Box::new(Function::new(
6260 "MAP_KEYS".to_string(),
6261 vec![right.clone()],
6262 ))),
6263 ],
6264 )));
6265 let list_distinct = Expression::Function(Box::new(Function::new(
6266 "LIST_DISTINCT".to_string(),
6267 vec![list_concat],
6268 )));
6269
6270 let k_ident = Identifier::new("__k");
6271 let k_ref = Expression::boxed_column(Column {
6272 table: None,
6273 name: k_ident.clone(),
6274 join_mark: false,
6275 trailing_comments: Vec::new(),
6276 span: None,
6277 inferred_type: None,
6278 });
6279 let right_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
6280 this: right.clone(),
6281 index: k_ref.clone(),
6282 }));
6283 let left_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
6284 this: left.clone(),
6285 index: k_ref.clone(),
6286 }));
6287 let key_value = Expression::Coalesce(Box::new(VarArgFunc {
6288 expressions: vec![right_key, left_key],
6289 original_name: None,
6290 inferred_type: None,
6291 }));
6292 let struct_pack = Expression::Function(Box::new(Function::new(
6293 "STRUCT_PACK".to_string(),
6294 vec![
6295 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
6296 name: Identifier::new("key"),
6297 value: k_ref.clone(),
6298 separator: crate::expressions::NamedArgSeparator::ColonEq,
6299 })),
6300 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
6301 name: Identifier::new("value"),
6302 value: key_value,
6303 separator: crate::expressions::NamedArgSeparator::ColonEq,
6304 })),
6305 ],
6306 )));
6307 let lambda_k = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6308 parameters: vec![k_ident],
6309 body: struct_pack,
6310 colon: false,
6311 parameter_types: Vec::new(),
6312 }));
6313
6314 let list_transform = Expression::Function(Box::new(Function::new(
6315 "LIST_TRANSFORM".to_string(),
6316 vec![list_distinct, lambda_k],
6317 )));
6318
6319 let x_ident = Identifier::new("__x");
6320 let x_ref = Expression::boxed_column(Column {
6321 table: None,
6322 name: x_ident.clone(),
6323 join_mark: false,
6324 trailing_comments: Vec::new(),
6325 span: None,
6326 inferred_type: None,
6327 });
6328 let x_value = Expression::Dot(Box::new(crate::expressions::DotAccess {
6329 this: x_ref,
6330 field: Identifier::new("value"),
6331 }));
6332 let x_value_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6333 this: x_value,
6334 not: false,
6335 postfix_form: false,
6336 }));
6337 let lambda_x = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6338 parameters: vec![x_ident],
6339 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
6340 this: x_value_is_null,
6341 inferred_type: None,
6342 })),
6343 colon: false,
6344 parameter_types: Vec::new(),
6345 }));
6346
6347 let list_filter = Expression::Function(Box::new(Function::new(
6348 "LIST_FILTER".to_string(),
6349 vec![list_transform, lambda_x],
6350 )));
6351 let merged_map = Expression::Function(Box::new(Function::new(
6352 "MAP_FROM_ENTRIES".to_string(),
6353 vec![list_filter],
6354 )));
6355
6356 Ok(Expression::Case(Box::new(Case {
6357 operand: None,
6358 whens: vec![(null_cond, Expression::Null(crate::expressions::Null))],
6359 else_: Some(merged_map),
6360 comments: Vec::new(),
6361 inferred_type: None,
6362 })))
6363 }
6364
6365 "MINHASH" if f.args.len() == 2 => {
6367 let mut args = f.args;
6368 let num_perm = args.remove(0);
6369 let value = args.remove(0);
6370
6371 let num_perm_sql = Self::expr_to_sql(&num_perm);
6372 let value_sql = Self::expr_to_sql(&value);
6373
6374 let template = format!(
6375 "SELECT JSON_OBJECT('state', LIST(min_h ORDER BY seed NULLS FIRST), 'type', 'minhash', 'version', 1) FROM (SELECT seed, LIST_MIN(LIST_TRANSFORM(vals, __v -> HASH(CAST(__v AS TEXT) || CAST(seed AS TEXT)))) AS min_h FROM (SELECT LIST({value}) AS vals), RANGE(0, {num_perm}) AS t(seed))",
6376 value = value_sql,
6377 num_perm = num_perm_sql
6378 );
6379
6380 Self::parse_as_subquery(&template)
6381 }
6382
6383 "MINHASH_COMBINE" if f.args.len() == 1 => {
6385 let sig_sql = Self::expr_to_sql(&f.args[0]);
6386 let template = format!(
6387 "SELECT JSON_OBJECT('state', LIST(min_h ORDER BY idx NULLS FIRST), 'type', 'minhash', 'version', 1) FROM (SELECT pos AS idx, MIN(val) AS min_h FROM UNNEST(LIST({sig})) AS _(sig) JOIN UNNEST(CAST(sig -> '$.state' AS UBIGINT[])) WITH ORDINALITY AS t(val, pos) ON TRUE GROUP BY pos)",
6388 sig = sig_sql
6389 );
6390 Self::parse_as_subquery(&template)
6391 }
6392
6393 "APPROXIMATE_SIMILARITY" if f.args.len() == 1 => {
6395 let sig_sql = Self::expr_to_sql(&f.args[0]);
6396 let template = format!(
6397 "SELECT CAST(SUM(CASE WHEN num_distinct = 1 THEN 1 ELSE 0 END) AS DOUBLE) / COUNT(*) FROM (SELECT pos, COUNT(DISTINCT h) AS num_distinct FROM (SELECT h, pos FROM UNNEST(LIST({sig})) AS _(sig) JOIN UNNEST(CAST(sig -> '$.state' AS UBIGINT[])) WITH ORDINALITY AS s(h, pos) ON TRUE) GROUP BY pos)",
6398 sig = sig_sql
6399 );
6400 Self::parse_as_subquery(&template)
6401 }
6402
6403 "ARRAYS_ZIP" if !f.args.is_empty() => {
6405 let args = f.args;
6406 let n = args.len();
6407 let is_null = |expr: Expression| {
6408 Expression::IsNull(Box::new(crate::expressions::IsNull {
6409 this: expr,
6410 not: false,
6411 postfix_form: false,
6412 }))
6413 };
6414 let length_of = |expr: Expression| {
6415 Expression::Function(Box::new(Function::new("LENGTH".to_string(), vec![expr])))
6416 };
6417 let eq_zero = |expr: Expression| {
6418 Expression::Eq(Box::new(BinaryOp {
6419 left: expr,
6420 right: Expression::number(0),
6421 left_comments: Vec::new(),
6422 operator_comments: Vec::new(),
6423 trailing_comments: Vec::new(),
6424 inferred_type: None,
6425 }))
6426 };
6427 let and_expr = |left: Expression, right: Expression| {
6428 Expression::And(Box::new(BinaryOp {
6429 left,
6430 right,
6431 left_comments: Vec::new(),
6432 operator_comments: Vec::new(),
6433 trailing_comments: Vec::new(),
6434 inferred_type: None,
6435 }))
6436 };
6437 let or_expr = |left: Expression, right: Expression| {
6438 Expression::Or(Box::new(BinaryOp {
6439 left,
6440 right,
6441 left_comments: Vec::new(),
6442 operator_comments: Vec::new(),
6443 trailing_comments: Vec::new(),
6444 inferred_type: None,
6445 }))
6446 };
6447
6448 let null_cond = args.iter().cloned().map(is_null).reduce(or_expr).unwrap();
6449 let empty_cond = args
6450 .iter()
6451 .cloned()
6452 .map(|a| eq_zero(length_of(a)))
6453 .reduce(and_expr)
6454 .unwrap();
6455
6456 let null_struct = Expression::Struct(Box::new(Struct {
6457 fields: (1..=n)
6458 .map(|i| {
6459 (
6460 Some(format!("${}", i)),
6461 Expression::Null(crate::expressions::Null),
6462 )
6463 })
6464 .collect(),
6465 }));
6466 let empty_result = Expression::Array(Box::new(crate::expressions::Array {
6467 expressions: vec![null_struct],
6468 }));
6469
6470 let range_upper = if n == 1 {
6471 length_of(args[0].clone())
6472 } else {
6473 let length_null_cond = args
6474 .iter()
6475 .cloned()
6476 .map(|a| is_null(length_of(a)))
6477 .reduce(or_expr)
6478 .unwrap();
6479 let greatest_len = Expression::Greatest(Box::new(VarArgFunc {
6480 expressions: args.iter().cloned().map(length_of).collect(),
6481 original_name: None,
6482 inferred_type: None,
6483 }));
6484 Expression::Case(Box::new(Case {
6485 operand: None,
6486 whens: vec![(length_null_cond, Expression::Null(crate::expressions::Null))],
6487 else_: Some(greatest_len),
6488 comments: Vec::new(),
6489 inferred_type: None,
6490 }))
6491 };
6492
6493 let range_expr = Expression::Function(Box::new(Function::new(
6494 "RANGE".to_string(),
6495 vec![Expression::number(0), range_upper],
6496 )));
6497
6498 let i_ident = Identifier::new("__i");
6499 let i_ref = Expression::boxed_column(Column {
6500 table: None,
6501 name: i_ident.clone(),
6502 join_mark: false,
6503 trailing_comments: Vec::new(),
6504 span: None,
6505 inferred_type: None,
6506 });
6507 let i_plus_one = Expression::Add(Box::new(BinaryOp {
6508 left: i_ref,
6509 right: Expression::number(1),
6510 left_comments: Vec::new(),
6511 operator_comments: Vec::new(),
6512 trailing_comments: Vec::new(),
6513 inferred_type: None,
6514 }));
6515 let empty_array = Expression::Array(Box::new(crate::expressions::Array {
6516 expressions: vec![],
6517 }));
6518 let zipped_struct = Expression::Struct(Box::new(Struct {
6519 fields: args
6520 .iter()
6521 .enumerate()
6522 .map(|(i, a)| {
6523 let coalesced = Expression::Coalesce(Box::new(VarArgFunc {
6524 expressions: vec![a.clone(), empty_array.clone()],
6525 original_name: None,
6526 inferred_type: None,
6527 }));
6528 let item =
6529 Expression::Subscript(Box::new(crate::expressions::Subscript {
6530 this: coalesced,
6531 index: i_plus_one.clone(),
6532 }));
6533 (Some(format!("${}", i + 1)), item)
6534 })
6535 .collect(),
6536 }));
6537 let lambda_i = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6538 parameters: vec![i_ident],
6539 body: zipped_struct,
6540 colon: false,
6541 parameter_types: Vec::new(),
6542 }));
6543 let zipped_result = Expression::Function(Box::new(Function::new(
6544 "LIST_TRANSFORM".to_string(),
6545 vec![range_expr, lambda_i],
6546 )));
6547
6548 Ok(Expression::Case(Box::new(Case {
6549 operand: None,
6550 whens: vec![
6551 (null_cond, Expression::Null(crate::expressions::Null)),
6552 (empty_cond, empty_result),
6553 ],
6554 else_: Some(zipped_result),
6555 comments: Vec::new(),
6556 inferred_type: None,
6557 })))
6558 }
6559
6560 "STRTOK" if f.args.len() == 3 => {
6564 let mut args = f.args.into_iter();
6565 let str_arg = args.next().unwrap();
6566 let delim_arg = args.next().unwrap();
6567 let pos_arg = args.next().unwrap();
6568
6569 let empty_str = || Expression::string("".to_string());
6571 let null_expr = || Expression::Null(crate::expressions::Null);
6573
6574 let when1_cond = Expression::And(Box::new(BinaryOp::new(
6576 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6577 Expression::Eq(Box::new(BinaryOp::new(str_arg.clone(), empty_str()))),
6578 )));
6579
6580 let when2_cond = Expression::And(Box::new(BinaryOp::new(
6582 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6583 Expression::Eq(Box::new(BinaryOp::new(
6584 pos_arg.clone(),
6585 Expression::number(1),
6586 ))),
6587 )));
6588
6589 let when3_cond =
6591 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str())));
6592
6593 let when4_cond = Expression::Lt(Box::new(BinaryOp::new(
6595 pos_arg.clone(),
6596 Expression::number(0),
6597 )));
6598
6599 let str_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6601 this: str_arg.clone(),
6602 not: false,
6603 postfix_form: false,
6604 }));
6605 let delim_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6606 this: delim_arg.clone(),
6607 not: false,
6608 postfix_form: false,
6609 }));
6610 let pos_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6611 this: pos_arg.clone(),
6612 not: false,
6613 postfix_form: false,
6614 }));
6615 let when5_cond = Expression::Or(Box::new(BinaryOp::new(
6616 Expression::Or(Box::new(BinaryOp::new(str_is_null, delim_is_null))),
6617 pos_is_null,
6618 )));
6619
6620 let regex_replace = Expression::Function(Box::new(Function::new(
6625 "REGEXP_REPLACE".to_string(),
6626 vec![
6627 delim_arg.clone(),
6628 Expression::string(r"([\[\]^.\-*+?(){}|$\\])".to_string()),
6629 Expression::string(r"\\\1".to_string()),
6630 Expression::string("g".to_string()),
6631 ],
6632 )));
6633
6634 let concat_regex = Expression::DPipe(Box::new(crate::expressions::DPipe {
6636 this: Box::new(Expression::DPipe(Box::new(crate::expressions::DPipe {
6637 this: Box::new(Expression::string("[".to_string())),
6638 expression: Box::new(regex_replace),
6639 safe: None,
6640 }))),
6641 expression: Box::new(Expression::string("]".to_string())),
6642 safe: None,
6643 }));
6644
6645 let inner_case = Expression::Case(Box::new(Case {
6646 operand: None,
6647 whens: vec![(
6648 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6649 empty_str(),
6650 )],
6651 else_: Some(concat_regex),
6652 comments: Vec::new(),
6653 inferred_type: None,
6654 }));
6655
6656 let regexp_split = Expression::Function(Box::new(Function::new(
6658 "REGEXP_SPLIT_TO_ARRAY".to_string(),
6659 vec![str_arg.clone(), inner_case],
6660 )));
6661
6662 let lambda = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6664 parameters: vec![Identifier::new("x".to_string())],
6665 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
6666 this: Expression::Eq(Box::new(BinaryOp::new(
6667 Expression::boxed_column(Column {
6668 table: None,
6669 name: Identifier::new("x".to_string()),
6670 join_mark: false,
6671 trailing_comments: Vec::new(),
6672 span: None,
6673 inferred_type: None,
6674 }),
6675 empty_str(),
6676 ))),
6677 inferred_type: None,
6678 })),
6679 colon: false,
6680 parameter_types: Vec::new(),
6681 }));
6682
6683 let list_filter = Expression::Function(Box::new(Function::new(
6685 "LIST_FILTER".to_string(),
6686 vec![regexp_split, lambda],
6687 )));
6688
6689 let subscripted = Expression::Subscript(Box::new(crate::expressions::Subscript {
6691 this: list_filter,
6692 index: pos_arg.clone(),
6693 }));
6694
6695 Ok(Expression::Case(Box::new(Case {
6696 operand: None,
6697 whens: vec![
6698 (when1_cond, null_expr()),
6699 (when2_cond, str_arg.clone()),
6700 (when3_cond, null_expr()),
6701 (when4_cond, null_expr()),
6702 (when5_cond, null_expr()),
6703 ],
6704 else_: Some(subscripted),
6705 comments: Vec::new(),
6706 inferred_type: None,
6707 })))
6708 }
6709
6710 _ => Ok(Expression::Function(Box::new(f))),
6712 }
6713 }
6714
6715 fn convert_snowflake_date_format(&self, fmt: Expression) -> Expression {
6717 match fmt {
6718 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6719 let Literal::String(s) = lit.as_ref() else {
6720 unreachable!()
6721 };
6722 let converted = Self::snowflake_to_strptime(&s);
6723 Expression::Literal(Box::new(Literal::String(converted)))
6724 }
6725 _ => fmt,
6726 }
6727 }
6728
6729 fn convert_snowflake_time_format(&self, fmt: Expression) -> Expression {
6731 match fmt {
6732 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6733 let Literal::String(s) = lit.as_ref() else {
6734 unreachable!()
6735 };
6736 let converted = Self::snowflake_to_strptime(&s);
6737 Expression::Literal(Box::new(Literal::String(converted)))
6738 }
6739 _ => fmt,
6740 }
6741 }
6742
6743 fn snowflake_to_strptime(s: &str) -> String {
6746 let mut result = String::new();
6747 let chars: Vec<char> = s.chars().collect();
6748 let len = chars.len();
6749 let mut i = 0;
6750 while i < len {
6751 let remaining = &s[i..];
6752 let remaining_upper: String =
6753 remaining.chars().take(8).collect::<String>().to_uppercase();
6754
6755 if remaining_upper.starts_with("HH24MISS") {
6757 result.push_str("%H%M%S");
6758 i += 8;
6759 } else if remaining_upper.starts_with("MMMM") {
6760 result.push_str("%B");
6761 i += 4;
6762 } else if remaining_upper.starts_with("YYYY") {
6763 result.push_str("%Y");
6764 i += 4;
6765 } else if remaining_upper.starts_with("YY") {
6766 result.push_str("%y");
6767 i += 2;
6768 } else if remaining_upper.starts_with("MON") {
6769 result.push_str("%b");
6770 i += 3;
6771 } else if remaining_upper.starts_with("HH24") {
6772 result.push_str("%H");
6773 i += 4;
6774 } else if remaining_upper.starts_with("HH12") {
6775 result.push_str("%I");
6776 i += 4;
6777 } else if remaining_upper.starts_with("HH") {
6778 result.push_str("%I");
6779 i += 2;
6780 } else if remaining_upper.starts_with("MISS") {
6781 result.push_str("%M%S");
6782 i += 4;
6783 } else if remaining_upper.starts_with("MI") {
6784 result.push_str("%M");
6785 i += 2;
6786 } else if remaining_upper.starts_with("MM") {
6787 result.push_str("%m");
6788 i += 2;
6789 } else if remaining_upper.starts_with("DD") {
6790 result.push_str("%d");
6791 i += 2;
6792 } else if remaining_upper.starts_with("DY") {
6793 result.push_str("%a");
6794 i += 2;
6795 } else if remaining_upper.starts_with("SS") {
6796 result.push_str("%S");
6797 i += 2;
6798 } else if remaining_upper.starts_with("FF") {
6799 let ff_pos = i + 2;
6802 if ff_pos < len && chars[ff_pos].is_ascii_digit() {
6803 let digit = chars[ff_pos].to_digit(10).unwrap_or(6);
6804 if digit >= 7 {
6805 result.push_str("%n");
6806 } else {
6807 result.push_str("%f");
6808 }
6809 i += 3; } else {
6811 result.push_str("%f");
6812 i += 2;
6813 }
6814 } else if remaining_upper.starts_with("PM") || remaining_upper.starts_with("AM") {
6815 result.push_str("%p");
6816 i += 2;
6817 } else if remaining_upper.starts_with("TZH") {
6818 result.push_str("%z");
6819 i += 3;
6820 } else if remaining_upper.starts_with("TZM") {
6821 i += 3;
6823 } else {
6824 result.push(chars[i]);
6825 i += 1;
6826 }
6827 }
6828 result
6829 }
6830
6831 fn convert_bq_to_strptime_format(&self, fmt: Expression) -> Expression {
6834 match fmt {
6835 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6836 let Literal::String(s) = lit.as_ref() else {
6837 unreachable!()
6838 };
6839 let converted = s.replace("%E6S", "%S.%f").replace("%E*S", "%S.%f");
6840 Expression::Literal(Box::new(Literal::String(converted)))
6841 }
6842 _ => fmt,
6843 }
6844 }
6845
6846 fn transform_date_part(&self, args: Vec<Expression>) -> Result<Expression> {
6848 let mut args = args;
6849 let unit_expr = args.remove(0);
6850 let date_expr = args.remove(0);
6851 let unit_name = match &unit_expr {
6852 Expression::Column(c) => c.name.name.to_uppercase(),
6853 Expression::Identifier(i) => i.name.to_uppercase(),
6854 Expression::Var(v) => v.this.to_uppercase(),
6855 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6856 let Literal::String(s) = lit.as_ref() else {
6857 unreachable!()
6858 };
6859 s.to_uppercase()
6860 }
6861 _ => {
6862 return Ok(Expression::Function(Box::new(Function::new(
6863 "DATE_PART".to_string(),
6864 vec![unit_expr, date_expr],
6865 ))))
6866 }
6867 };
6868 match unit_name.as_str() {
6869 "EPOCH_SECOND" | "EPOCH" => Ok(Expression::Cast(Box::new(Cast {
6870 this: Expression::Function(Box::new(Function::new(
6871 "EPOCH".to_string(),
6872 vec![date_expr],
6873 ))),
6874 to: DataType::BigInt { length: None },
6875 trailing_comments: Vec::new(),
6876 double_colon_syntax: false,
6877 format: None,
6878 default: None,
6879 inferred_type: None,
6880 }))),
6881 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Ok(Expression::Function(Box::new(
6882 Function::new("EPOCH_MS".to_string(), vec![date_expr]),
6883 ))),
6884 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Ok(Expression::Function(Box::new(
6885 Function::new("EPOCH_US".to_string(), vec![date_expr]),
6886 ))),
6887 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Ok(Expression::Function(Box::new(
6888 Function::new("EPOCH_NS".to_string(), vec![date_expr]),
6889 ))),
6890 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Extract(Box::new(
6891 crate::expressions::ExtractFunc {
6892 this: date_expr,
6893 field: crate::expressions::DateTimeField::Custom("ISODOW".to_string()),
6894 },
6895 ))),
6896 "YEAROFWEEK" | "YEAROFWEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6897 this: Expression::Function(Box::new(Function::new(
6898 "STRFTIME".to_string(),
6899 vec![
6900 date_expr,
6901 Expression::Literal(Box::new(Literal::String("%G".to_string()))),
6902 ],
6903 ))),
6904 to: DataType::Int {
6905 length: None,
6906 integer_spelling: false,
6907 },
6908 trailing_comments: Vec::new(),
6909 double_colon_syntax: false,
6910 format: None,
6911 default: None,
6912 inferred_type: None,
6913 }))),
6914 "WEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6915 this: Expression::Function(Box::new(Function::new(
6916 "STRFTIME".to_string(),
6917 vec![
6918 date_expr,
6919 Expression::Literal(Box::new(Literal::String("%V".to_string()))),
6920 ],
6921 ))),
6922 to: DataType::Int {
6923 length: None,
6924 integer_spelling: false,
6925 },
6926 trailing_comments: Vec::new(),
6927 double_colon_syntax: false,
6928 format: None,
6929 default: None,
6930 inferred_type: None,
6931 }))),
6932 "NANOSECOND" | "NANOSECONDS" | "NS" => Ok(Expression::Cast(Box::new(Cast {
6933 this: Expression::Function(Box::new(Function::new(
6934 "STRFTIME".to_string(),
6935 vec![
6936 Expression::Cast(Box::new(Cast {
6937 this: date_expr,
6938 to: DataType::Custom {
6939 name: "TIMESTAMP_NS".to_string(),
6940 },
6941 trailing_comments: Vec::new(),
6942 double_colon_syntax: false,
6943 format: None,
6944 default: None,
6945 inferred_type: None,
6946 })),
6947 Expression::Literal(Box::new(Literal::String("%n".to_string()))),
6948 ],
6949 ))),
6950 to: DataType::BigInt { length: None },
6951 trailing_comments: Vec::new(),
6952 double_colon_syntax: false,
6953 format: None,
6954 default: None,
6955 inferred_type: None,
6956 }))),
6957 "DAYOFMONTH" => Ok(Expression::Extract(Box::new(
6958 crate::expressions::ExtractFunc {
6959 this: date_expr,
6960 field: crate::expressions::DateTimeField::Day,
6961 },
6962 ))),
6963 _ => {
6964 let field = match unit_name.as_str() {
6965 "YEAR" | "YY" | "YYYY" => crate::expressions::DateTimeField::Year,
6966 "MONTH" | "MON" | "MM" => crate::expressions::DateTimeField::Month,
6967 "DAY" | "DD" | "D" => crate::expressions::DateTimeField::Day,
6968 "HOUR" | "HH" => crate::expressions::DateTimeField::Hour,
6969 "MINUTE" | "MI" | "MIN" => crate::expressions::DateTimeField::Minute,
6970 "SECOND" | "SEC" | "SS" => crate::expressions::DateTimeField::Second,
6971 "MILLISECOND" | "MS" => crate::expressions::DateTimeField::Millisecond,
6972 "MICROSECOND" | "US" => crate::expressions::DateTimeField::Microsecond,
6973 "QUARTER" | "QTR" => crate::expressions::DateTimeField::Quarter,
6974 "WEEK" | "WK" => crate::expressions::DateTimeField::Week,
6975 "DAYOFWEEK" | "DOW" => crate::expressions::DateTimeField::DayOfWeek,
6976 "DAYOFYEAR" | "DOY" => crate::expressions::DateTimeField::DayOfYear,
6977 "TIMEZONE_HOUR" => crate::expressions::DateTimeField::TimezoneHour,
6978 "TIMEZONE_MINUTE" => crate::expressions::DateTimeField::TimezoneMinute,
6979 _ => crate::expressions::DateTimeField::Custom(unit_name),
6980 };
6981 Ok(Expression::Extract(Box::new(
6982 crate::expressions::ExtractFunc {
6983 this: date_expr,
6984 field,
6985 },
6986 )))
6987 }
6988 }
6989 }
6990
6991 fn transform_dateadd(&self, args: Vec<Expression>) -> Result<Expression> {
6993 let mut args = args;
6994 let unit_expr = args.remove(0);
6995 let amount = args.remove(0);
6996 let date = args.remove(0);
6997 let unit_name = match &unit_expr {
6998 Expression::Column(c) => c.name.name.to_uppercase(),
6999 Expression::Identifier(i) => i.name.to_uppercase(),
7000 Expression::Var(v) => v.this.to_uppercase(),
7001 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
7002 let Literal::String(s) = lit.as_ref() else {
7003 unreachable!()
7004 };
7005 s.to_uppercase()
7006 }
7007 _ => String::new(),
7008 };
7009 if unit_name == "NANOSECOND" || unit_name == "NS" {
7010 let epoch_ns = Expression::Function(Box::new(Function::new(
7011 "EPOCH_NS".to_string(),
7012 vec![Expression::Cast(Box::new(Cast {
7013 this: date,
7014 to: DataType::Custom {
7015 name: "TIMESTAMP_NS".to_string(),
7016 },
7017 trailing_comments: Vec::new(),
7018 double_colon_syntax: false,
7019 format: None,
7020 default: None,
7021 inferred_type: None,
7022 }))],
7023 )));
7024 return Ok(Expression::Function(Box::new(Function::new(
7025 "MAKE_TIMESTAMP_NS".to_string(),
7026 vec![Expression::Add(Box::new(BinaryOp {
7027 left: epoch_ns,
7028 right: amount,
7029 left_comments: Vec::new(),
7030 operator_comments: Vec::new(),
7031 trailing_comments: Vec::new(),
7032 inferred_type: None,
7033 }))],
7034 ))));
7035 }
7036 let (interval_unit, multiplied_amount) = match unit_name.as_str() {
7037 "YEAR" | "YY" | "YYYY" => (IntervalUnit::Year, amount),
7038 "MONTH" | "MON" | "MM" => (IntervalUnit::Month, amount),
7039 "DAY" | "DD" | "D" => (IntervalUnit::Day, amount),
7040 "HOUR" | "HH" => (IntervalUnit::Hour, amount),
7041 "MINUTE" | "MI" | "MIN" => (IntervalUnit::Minute, amount),
7042 "SECOND" | "SEC" | "SS" => (IntervalUnit::Second, amount),
7043 "MILLISECOND" | "MS" => (IntervalUnit::Millisecond, amount),
7044 "MICROSECOND" | "US" => (IntervalUnit::Microsecond, amount),
7045 "WEEK" | "WK" => (
7046 IntervalUnit::Day,
7047 Expression::Mul(Box::new(BinaryOp {
7048 left: amount,
7049 right: Expression::number(7),
7050 left_comments: Vec::new(),
7051 operator_comments: Vec::new(),
7052 trailing_comments: Vec::new(),
7053 inferred_type: None,
7054 })),
7055 ),
7056 "QUARTER" | "QTR" => (
7057 IntervalUnit::Month,
7058 Expression::Mul(Box::new(BinaryOp {
7059 left: amount,
7060 right: Expression::number(3),
7061 left_comments: Vec::new(),
7062 operator_comments: Vec::new(),
7063 trailing_comments: Vec::new(),
7064 inferred_type: None,
7065 })),
7066 ),
7067 _ => (IntervalUnit::Day, amount),
7068 };
7069 Ok(Expression::Add(Box::new(BinaryOp {
7070 left: date,
7071 right: Expression::Interval(Box::new(Interval {
7072 this: Some(multiplied_amount),
7073 unit: Some(IntervalUnitSpec::Simple {
7074 unit: interval_unit,
7075 use_plural: false,
7076 }),
7077 })),
7078 left_comments: Vec::new(),
7079 operator_comments: Vec::new(),
7080 trailing_comments: Vec::new(),
7081 inferred_type: None,
7082 })))
7083 }
7084
7085 fn transform_datediff(&self, args: Vec<Expression>) -> Result<Expression> {
7087 let mut args = args;
7088 let unit_expr = args.remove(0);
7089 let start = args.remove(0);
7090 let end = args.remove(0);
7091 let unit_name = match &unit_expr {
7092 Expression::Column(c) => c.name.name.to_uppercase(),
7093 Expression::Identifier(i) => i.name.to_uppercase(),
7094 Expression::Var(v) => v.this.to_uppercase(),
7095 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
7096 let Literal::String(s) = lit.as_ref() else {
7097 unreachable!()
7098 };
7099 s.to_uppercase()
7100 }
7101 _ => String::new(),
7102 };
7103 if unit_name == "NANOSECOND" || unit_name == "NS" {
7104 let epoch_end = Expression::Function(Box::new(Function::new(
7105 "EPOCH_NS".to_string(),
7106 vec![Expression::Cast(Box::new(Cast {
7107 this: end,
7108 to: DataType::Custom {
7109 name: "TIMESTAMP_NS".to_string(),
7110 },
7111 trailing_comments: Vec::new(),
7112 double_colon_syntax: false,
7113 format: None,
7114 default: None,
7115 inferred_type: None,
7116 }))],
7117 )));
7118 let epoch_start = Expression::Function(Box::new(Function::new(
7119 "EPOCH_NS".to_string(),
7120 vec![Expression::Cast(Box::new(Cast {
7121 this: start,
7122 to: DataType::Custom {
7123 name: "TIMESTAMP_NS".to_string(),
7124 },
7125 trailing_comments: Vec::new(),
7126 double_colon_syntax: false,
7127 format: None,
7128 default: None,
7129 inferred_type: None,
7130 }))],
7131 )));
7132 return Ok(Expression::Sub(Box::new(BinaryOp {
7133 left: epoch_end,
7134 right: epoch_start,
7135 left_comments: Vec::new(),
7136 operator_comments: Vec::new(),
7137 trailing_comments: Vec::new(),
7138 inferred_type: None,
7139 })));
7140 }
7141 if unit_name == "WEEK" || unit_name == "WK" {
7142 let trunc_start = Expression::Function(Box::new(Function::new(
7143 "DATE_TRUNC".to_string(),
7144 vec![
7145 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7146 Expression::Cast(Box::new(Cast {
7147 this: start,
7148 to: DataType::Date,
7149 trailing_comments: Vec::new(),
7150 double_colon_syntax: false,
7151 format: None,
7152 default: None,
7153 inferred_type: None,
7154 })),
7155 ],
7156 )));
7157 let trunc_end = Expression::Function(Box::new(Function::new(
7158 "DATE_TRUNC".to_string(),
7159 vec![
7160 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7161 Expression::Cast(Box::new(Cast {
7162 this: end,
7163 to: DataType::Date,
7164 trailing_comments: Vec::new(),
7165 double_colon_syntax: false,
7166 format: None,
7167 default: None,
7168 inferred_type: None,
7169 })),
7170 ],
7171 )));
7172 return Ok(Expression::Function(Box::new(Function::new(
7173 "DATE_DIFF".to_string(),
7174 vec![
7175 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7176 trunc_start,
7177 trunc_end,
7178 ],
7179 ))));
7180 }
7181 let cast_if_string = |e: Expression| -> Expression {
7182 match &e {
7183 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
7184 Expression::Cast(Box::new(Cast {
7185 this: e,
7186 to: DataType::Date,
7187 trailing_comments: Vec::new(),
7188 double_colon_syntax: false,
7189 format: None,
7190 default: None,
7191 inferred_type: None,
7192 }))
7193 }
7194 _ => e,
7195 }
7196 };
7197 let start = cast_if_string(start);
7198 let end = cast_if_string(end);
7199 Ok(Expression::Function(Box::new(Function::new(
7200 "DATE_DIFF".to_string(),
7201 vec![
7202 Expression::Literal(Box::new(Literal::String(unit_name))),
7203 start,
7204 end,
7205 ],
7206 ))))
7207 }
7208
7209 fn transform_aggregate_function(
7210 &self,
7211 f: Box<crate::expressions::AggregateFunction>,
7212 ) -> Result<Expression> {
7213 let name_upper = f.name.to_uppercase();
7214 match name_upper.as_str() {
7215 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
7217 Function::new("LISTAGG".to_string(), f.args),
7218 ))),
7219
7220 "LISTAGG" => Ok(Expression::AggregateFunction(f)),
7222
7223 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
7225 Function::new("LISTAGG".to_string(), f.args),
7226 ))),
7227
7228 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
7230 "list".to_string(),
7231 f.args,
7232 )))),
7233
7234 "LOGICAL_OR" if !f.args.is_empty() => {
7236 let arg = f.args.into_iter().next().unwrap();
7237 Ok(Expression::Function(Box::new(Function::new(
7238 "BOOL_OR".to_string(),
7239 vec![Expression::Cast(Box::new(crate::expressions::Cast {
7240 this: arg,
7241 to: crate::expressions::DataType::Boolean,
7242 trailing_comments: Vec::new(),
7243 double_colon_syntax: false,
7244 format: None,
7245 default: None,
7246 inferred_type: None,
7247 }))],
7248 ))))
7249 }
7250
7251 "LOGICAL_AND" if !f.args.is_empty() => {
7253 let arg = f.args.into_iter().next().unwrap();
7254 Ok(Expression::Function(Box::new(Function::new(
7255 "BOOL_AND".to_string(),
7256 vec![Expression::Cast(Box::new(crate::expressions::Cast {
7257 this: arg,
7258 to: crate::expressions::DataType::Boolean,
7259 trailing_comments: Vec::new(),
7260 double_colon_syntax: false,
7261 format: None,
7262 default: None,
7263 inferred_type: None,
7264 }))],
7265 ))))
7266 }
7267
7268 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
7270 "SKEWNESS".to_string(),
7271 f.args,
7272 )))),
7273
7274 "REGR_VALX" if f.args.len() == 2 => {
7276 let mut args = f.args;
7277 let y = args.remove(0);
7278 let x = args.remove(0);
7279 Ok(Expression::Case(Box::new(Case {
7280 operand: None,
7281 whens: vec![(
7282 Expression::IsNull(Box::new(crate::expressions::IsNull {
7283 this: y,
7284 not: false,
7285 postfix_form: false,
7286 })),
7287 Expression::Cast(Box::new(Cast {
7288 this: Expression::Null(crate::expressions::Null),
7289 to: DataType::Double {
7290 precision: None,
7291 scale: None,
7292 },
7293 trailing_comments: Vec::new(),
7294 double_colon_syntax: false,
7295 format: None,
7296 default: None,
7297 inferred_type: None,
7298 })),
7299 )],
7300 else_: Some(x),
7301 comments: Vec::new(),
7302 inferred_type: None,
7303 })))
7304 }
7305
7306 "REGR_VALY" if f.args.len() == 2 => {
7308 let mut args = f.args;
7309 let y = args.remove(0);
7310 let x = args.remove(0);
7311 Ok(Expression::Case(Box::new(Case {
7312 operand: None,
7313 whens: vec![(
7314 Expression::IsNull(Box::new(crate::expressions::IsNull {
7315 this: x,
7316 not: false,
7317 postfix_form: false,
7318 })),
7319 Expression::Cast(Box::new(Cast {
7320 this: Expression::Null(crate::expressions::Null),
7321 to: DataType::Double {
7322 precision: None,
7323 scale: None,
7324 },
7325 trailing_comments: Vec::new(),
7326 double_colon_syntax: false,
7327 format: None,
7328 default: None,
7329 inferred_type: None,
7330 })),
7331 )],
7332 else_: Some(y),
7333 comments: Vec::new(),
7334 inferred_type: None,
7335 })))
7336 }
7337
7338 "BOOLAND_AGG" if !f.args.is_empty() => {
7340 let arg = f.args.into_iter().next().unwrap();
7341 Ok(Expression::Function(Box::new(Function::new(
7342 "BOOL_AND".to_string(),
7343 vec![Expression::Cast(Box::new(Cast {
7344 this: arg,
7345 to: DataType::Boolean,
7346 trailing_comments: Vec::new(),
7347 double_colon_syntax: false,
7348 format: None,
7349 default: None,
7350 inferred_type: None,
7351 }))],
7352 ))))
7353 }
7354
7355 "BOOLOR_AGG" if !f.args.is_empty() => {
7357 let arg = f.args.into_iter().next().unwrap();
7358 Ok(Expression::Function(Box::new(Function::new(
7359 "BOOL_OR".to_string(),
7360 vec![Expression::Cast(Box::new(Cast {
7361 this: arg,
7362 to: DataType::Boolean,
7363 trailing_comments: Vec::new(),
7364 double_colon_syntax: false,
7365 format: None,
7366 default: None,
7367 inferred_type: None,
7368 }))],
7369 ))))
7370 }
7371
7372 "BOOLXOR_AGG" if !f.args.is_empty() => {
7374 let arg = f.args.into_iter().next().unwrap();
7375 Ok(Expression::Eq(Box::new(BinaryOp {
7376 left: Expression::Function(Box::new(Function::new(
7377 "COUNT_IF".to_string(),
7378 vec![Expression::Cast(Box::new(Cast {
7379 this: arg,
7380 to: DataType::Boolean,
7381 trailing_comments: Vec::new(),
7382 double_colon_syntax: false,
7383 format: None,
7384 default: None,
7385 inferred_type: None,
7386 }))],
7387 ))),
7388 right: Expression::number(1),
7389 left_comments: Vec::new(),
7390 operator_comments: Vec::new(),
7391 trailing_comments: Vec::new(),
7392 inferred_type: None,
7393 })))
7394 }
7395
7396 "MAX_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
7398 crate::expressions::AggregateFunction {
7399 name: "ARG_MAX".to_string(),
7400 ..(*f)
7401 },
7402 ))),
7403
7404 "MIN_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
7406 crate::expressions::AggregateFunction {
7407 name: "ARG_MIN".to_string(),
7408 ..(*f)
7409 },
7410 ))),
7411
7412 "CORR" if f.args.len() == 2 => Ok(Expression::AggregateFunction(f)),
7414
7415 "BITMAP_CONSTRUCT_AGG" if f.args.len() == 1 => {
7417 let v_sql = Self::expr_to_sql(&f.args[0]);
7418
7419 let template = format!(
7420 "SELECT CASE WHEN l IS NULL OR LENGTH(l) = 0 THEN NULL WHEN LENGTH(l) <> LENGTH(LIST_FILTER(l, __v -> __v BETWEEN 0 AND 32767)) THEN NULL WHEN LENGTH(l) < 5 THEN UNHEX(PRINTF('%04X', LENGTH(l)) || h || REPEAT('00', GREATEST(0, 4 - LENGTH(l)) * 2)) ELSE UNHEX('08000000000000000000' || h) END FROM (SELECT l, COALESCE(LIST_REDUCE(LIST_TRANSFORM(l, __x -> PRINTF('%02X%02X', CAST(__x AS INT) & 255, (CAST(__x AS INT) >> 8) & 255)), (__a, __b) -> __a || __b, ''), '') AS h FROM (SELECT LIST_SORT(LIST_DISTINCT(LIST({v}) FILTER(WHERE NOT {v} IS NULL))) AS l))",
7421 v = v_sql
7422 );
7423
7424 Self::parse_as_subquery(&template)
7425 }
7426
7427 _ => Ok(Expression::AggregateFunction(f)),
7429 }
7430 }
7431
7432 fn convert_format_to_duckdb(expr: &Expression) -> Expression {
7436 if let Expression::Literal(lit) = expr {
7437 if let Literal::String(s) = lit.as_ref() {
7438 let duckdb_fmt = Self::presto_to_duckdb_format(s);
7439 Expression::Literal(Box::new(Literal::String(duckdb_fmt)))
7440 } else {
7441 expr.clone()
7442 }
7443 } else {
7444 expr.clone()
7445 }
7446 }
7447
7448 fn presto_to_duckdb_format(fmt: &str) -> String {
7450 let mut result = String::new();
7451 let chars: Vec<char> = fmt.chars().collect();
7452 let mut i = 0;
7453 while i < chars.len() {
7454 if chars[i] == '%' && i + 1 < chars.len() {
7455 match chars[i + 1] {
7456 'i' => {
7457 result.push_str("%M");
7459 i += 2;
7460 }
7461 'T' => {
7462 result.push_str("%H:%M:%S");
7464 i += 2;
7465 }
7466 'F' => {
7467 result.push_str("%Y-%m-%d");
7469 i += 2;
7470 }
7471 _ => {
7472 result.push('%');
7473 result.push(chars[i + 1]);
7474 i += 2;
7475 }
7476 }
7477 } else {
7478 result.push(chars[i]);
7479 i += 1;
7480 }
7481 }
7482 result
7483 }
7484}
7485
7486#[cfg(test)]
7487mod tests {
7488 use super::*;
7489 use crate::dialects::Dialect;
7490
7491 fn transpile_to_duckdb(sql: &str) -> String {
7492 transpile_to_duckdb_from(sql, DialectType::Generic)
7493 }
7494
7495 fn transpile_to_duckdb_from(sql: &str, read: DialectType) -> String {
7496 let dialect = Dialect::get(read);
7497 let result = dialect
7498 .transpile(sql, DialectType::DuckDB)
7499 .expect("Transpile failed");
7500 result[0].clone()
7501 }
7502
7503 #[test]
7504 fn test_ifnull_to_coalesce() {
7505 let result = transpile_to_duckdb("SELECT IFNULL(a, b)");
7506 assert!(
7507 result.contains("COALESCE"),
7508 "Expected COALESCE, got: {}",
7509 result
7510 );
7511 }
7512
7513 #[test]
7514 fn test_nvl_to_coalesce() {
7515 let result = transpile_to_duckdb("SELECT NVL(a, b)");
7516 assert!(
7517 result.contains("COALESCE"),
7518 "Expected COALESCE, got: {}",
7519 result
7520 );
7521 }
7522
7523 #[test]
7524 fn test_basic_select() {
7525 let result = transpile_to_duckdb("SELECT a, b FROM users WHERE id = 1");
7526 assert!(result.contains("SELECT"));
7527 assert!(result.contains("FROM users"));
7528 }
7529
7530 #[test]
7531 fn test_group_concat_to_listagg() {
7532 let result = transpile_to_duckdb("SELECT GROUP_CONCAT(name)");
7533 assert!(
7534 result.contains("LISTAGG"),
7535 "Expected LISTAGG, got: {}",
7536 result
7537 );
7538 }
7539
7540 #[test]
7541 fn test_listagg_preserved() {
7542 let result = transpile_to_duckdb("SELECT LISTAGG(name)");
7543 assert!(
7544 result.contains("LISTAGG"),
7545 "Expected LISTAGG, got: {}",
7546 result
7547 );
7548 }
7549
7550 #[test]
7551 fn test_ordered_string_agg_uses_duckdb_listagg_order_syntax() {
7552 let result = transpile_to_duckdb_from(
7553 "SELECT string_agg(nm, ',' ORDER BY id) AS v FROM t",
7554 DialectType::PostgreSQL,
7555 );
7556 assert_eq!(result, "SELECT LISTAGG(nm, ',' ORDER BY id) AS v FROM t");
7557 }
7558
7559 #[test]
7560 fn test_ordered_listagg_uses_duckdb_order_syntax() {
7561 let result = transpile_to_duckdb_from(
7562 "SELECT LISTAGG(col, '|SEPARATOR|') WITHIN GROUP (ORDER BY col2) FROM t",
7563 DialectType::Snowflake,
7564 );
7565 assert_eq!(
7566 result,
7567 "SELECT LISTAGG(col, '|SEPARATOR|' ORDER BY col2) FROM t"
7568 );
7569 }
7570
7571 #[test]
7572 fn test_ordered_group_concat_uses_duckdb_listagg_order_syntax() {
7573 let result = transpile_to_duckdb_from(
7574 "SELECT GROUP_CONCAT(nm ORDER BY id SEPARATOR ',') AS v FROM t",
7575 DialectType::MySQL,
7576 );
7577 assert_eq!(result, "SELECT LISTAGG(nm, ',' ORDER BY id) AS v FROM t");
7578 }
7579
7580 #[test]
7581 fn test_date_format_to_strftime() {
7582 let result = transpile_to_duckdb("SELECT DATE_FORMAT(d, '%Y-%m-%d')");
7583 assert!(
7585 result.to_uppercase().contains("STRFTIME"),
7586 "Expected STRFTIME, got: {}",
7587 result
7588 );
7589 }
7590
7591 #[test]
7592 fn test_regexp_like_to_regexp_matches() {
7593 let result = transpile_to_duckdb("SELECT REGEXP_LIKE(name, 'pattern')");
7594 assert!(
7596 result.to_uppercase().contains("REGEXP_MATCHES"),
7597 "Expected REGEXP_MATCHES, got: {}",
7598 result
7599 );
7600 }
7601
7602 #[test]
7603 fn test_double_quote_identifiers() {
7604 let dialect = Dialect::get(DialectType::DuckDB);
7606 let config = dialect.generator_config();
7607 assert_eq!(config.identifier_quote, '"');
7608 }
7609
7610 fn duckdb_identity(sql: &str) -> String {
7612 let dialect = Dialect::get(DialectType::DuckDB);
7613 let ast = dialect.parse(sql).expect("Parse failed");
7614 let transformed = dialect.transform(ast[0].clone()).expect("Transform failed");
7615 dialect.generate(&transformed).expect("Generate failed")
7616 }
7617
7618 #[test]
7619 fn test_interval_quoting() {
7620 let result = duckdb_identity("SELECT DATE_ADD(CAST('2020-01-01' AS DATE), INTERVAL 1 DAY)");
7622 assert_eq!(
7623 result, "SELECT CAST('2020-01-01' AS DATE) + INTERVAL '1' DAY",
7624 "Interval value should be quoted as string"
7625 );
7626 }
7627
7628 #[test]
7629 fn test_struct_pack_to_curly_brace() {
7630 let result = duckdb_identity("CAST([STRUCT_PACK(a := 1)] AS STRUCT(a BIGINT)[])");
7632 assert_eq!(
7633 result, "CAST([{'a': 1}] AS STRUCT(a BIGINT)[])",
7634 "STRUCT_PACK should be transformed to curly brace notation"
7635 );
7636 }
7637
7638 #[test]
7639 fn test_struct_pack_nested() {
7640 let result = duckdb_identity("CAST([[STRUCT_PACK(a := 1)]] AS STRUCT(a BIGINT)[][])");
7642 assert_eq!(
7643 result, "CAST([[{'a': 1}]] AS STRUCT(a BIGINT)[][])",
7644 "Nested STRUCT_PACK should be transformed"
7645 );
7646 }
7647
7648 #[test]
7649 fn test_struct_pack_cast() {
7650 let result = duckdb_identity("STRUCT_PACK(a := 'b')::json");
7652 assert_eq!(
7653 result, "CAST({'a': 'b'} AS JSON)",
7654 "STRUCT_PACK with cast should be transformed"
7655 );
7656 }
7657
7658 #[test]
7659 fn test_list_value_to_bracket() {
7660 let result = duckdb_identity("SELECT LIST_VALUE(1)[i]");
7662 assert_eq!(
7663 result, "SELECT [1][i]",
7664 "LIST_VALUE should be transformed to bracket notation"
7665 );
7666 }
7667
7668 #[test]
7669 fn test_list_value_in_struct_literal() {
7670 let result = duckdb_identity("{'x': LIST_VALUE(1)[i]}");
7672 assert_eq!(
7673 result, "{'x': [1][i]}",
7674 "LIST_VALUE inside struct literal should be transformed"
7675 );
7676 }
7677
7678 #[test]
7679 fn test_struct_pack_simple() {
7680 let result = duckdb_identity("SELECT STRUCT_PACK(a := 1)");
7682 eprintln!("STRUCT_PACK result: {}", result);
7683 assert!(
7684 result.contains("{"),
7685 "Expected curly brace, got: {}",
7686 result
7687 );
7688 }
7689
7690 #[test]
7691 fn test_not_in_position() {
7692 let result = duckdb_identity(
7695 "SELECT col FROM t WHERE JSON_EXTRACT_STRING(col, '$.id') NOT IN ('b')",
7696 );
7697 assert_eq!(
7698 result, "SELECT col FROM t WHERE NOT (col ->> '$.id') IN ('b')",
7699 "NOT IN should have NOT moved outside and JSON expression wrapped"
7700 );
7701 }
7702
7703 #[test]
7704 fn test_unnest_comma_join_to_join_on_true() {
7705 let result = duckdb_identity(
7707 "WITH _data AS (SELECT [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}] AS col) SELECT t.col['b'] FROM _data, UNNEST(_data.col) AS t(col) WHERE t.col['a'] = 1",
7708 );
7709 assert_eq!(
7710 result,
7711 "WITH _data AS (SELECT [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}] AS col) SELECT t.col['b'] FROM _data JOIN UNNEST(_data.col) AS t(col) ON TRUE WHERE t.col['a'] = 1",
7712 "Comma-join with UNNEST should become JOIN ON TRUE"
7713 );
7714 }
7715}