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