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 pre_alias_comments: Vec::new(),
1216 trailing_comments: Vec::new(),
1217 inferred_type: None,
1218 }))
1219 } else {
1220 e
1221 }
1222 }
1223 _ => e,
1224 }
1225 })
1226 .collect();
1227
1228 if let Some(ref mut from) = select.from {
1231 if from.expressions.len() > 1 {
1232 let mut new_from_exprs = Vec::new();
1234 let mut new_joins = Vec::new();
1235
1236 for (idx, expr) in from.expressions.drain(..).enumerate() {
1237 if idx == 0 {
1238 new_from_exprs.push(expr);
1240 } else {
1241 let is_unnest = match &expr {
1243 Expression::Unnest(_) => true,
1244 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
1245 _ => false,
1246 };
1247
1248 if is_unnest {
1249 new_joins.push(crate::expressions::Join {
1251 this: expr,
1252 on: Some(Expression::Boolean(
1253 crate::expressions::BooleanLiteral { value: true },
1254 )),
1255 using: Vec::new(),
1256 kind: crate::expressions::JoinKind::Inner,
1257 use_inner_keyword: false,
1258 use_outer_keyword: false,
1259 deferred_condition: false,
1260 join_hint: None,
1261 match_condition: None,
1262 pivots: Vec::new(),
1263 comments: Vec::new(),
1264 nesting_group: 0,
1265 directed: false,
1266 });
1267 } else {
1268 new_from_exprs.push(expr);
1270 }
1271 }
1272 }
1273
1274 from.expressions = new_from_exprs;
1275
1276 new_joins.append(&mut select.joins);
1278 select.joins = new_joins;
1279 }
1280 }
1281
1282 Ok(Expression::Select(select))
1283 }
1284
1285 Expression::Interval(interval) => self.transform_interval(*interval),
1290
1291 Expression::CreateFunction(mut cf) => {
1293 cf.parameters = cf
1295 .parameters
1296 .into_iter()
1297 .map(|mut p| {
1298 if let Ok(Expression::DataType(new_dt)) =
1299 self.transform_data_type(p.data_type.clone())
1300 {
1301 p.data_type = new_dt;
1302 }
1303 p
1304 })
1305 .collect();
1306
1307 if cf.returns_table_body.is_some()
1311 && !matches!(&cf.return_type, Some(DataType::Custom { ref name }) if name == "TABLE")
1312 {
1313 cf.return_type = Some(DataType::Custom {
1314 name: "TABLE".to_string(),
1315 });
1316 cf.returns_table_body = None;
1317 }
1318
1319 Ok(Expression::CreateFunction(cf))
1320 }
1321
1322 Expression::IfFunc(f) => Ok(Expression::Case(Box::new(Case {
1326 operand: None,
1327 whens: vec![(f.condition, f.true_value)],
1328 else_: f.false_value,
1329 comments: Vec::new(),
1330 inferred_type: None,
1331 }))),
1332
1333 Expression::VarSamp(f) => Ok(Expression::Function(Box::new(Function::new(
1335 "VARIANCE".to_string(),
1336 vec![f.this],
1337 )))),
1338
1339 Expression::Nvl2(f) => {
1341 let condition = Expression::IsNull(Box::new(crate::expressions::IsNull {
1342 this: f.this,
1343 not: true,
1344 postfix_form: false,
1345 }));
1346 Ok(Expression::Case(Box::new(Case {
1347 operand: None,
1348 whens: vec![(condition, f.true_value)],
1349 else_: Some(f.false_value),
1350 comments: Vec::new(),
1351 inferred_type: None,
1352 })))
1353 }
1354
1355 _ => Ok(expr),
1357 }
1358 }
1359}
1360
1361impl DuckDBDialect {
1362 fn extract_number_value(expr: &Expression) -> Option<f64> {
1364 match expr {
1365 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
1366 let Literal::Number(n) = lit.as_ref() else {
1367 unreachable!()
1368 };
1369 n.parse::<f64>().ok()
1370 }
1371 _ => None,
1372 }
1373 }
1374
1375 fn expr_to_sql(expr: &Expression) -> String {
1377 crate::generator::Generator::sql(expr).unwrap_or_default()
1378 }
1379
1380 fn extract_seed_info(gen: &Expression) -> (String, bool) {
1386 match gen {
1387 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
1388 if func.args.is_empty() {
1389 ("RANDOM()".to_string(), true)
1390 } else {
1391 (Self::expr_to_sql(&func.args[0]), false)
1393 }
1394 }
1395 Expression::Rand(r) => {
1396 if let Some(ref seed) = r.seed {
1397 (Self::expr_to_sql(seed), false)
1399 } else {
1400 ("RANDOM()".to_string(), true)
1401 }
1402 }
1403 Expression::Random(_) => ("RANDOM()".to_string(), true),
1404 _ => (Self::expr_to_sql(gen), false),
1405 }
1406 }
1407
1408 fn parse_as_subquery(sql: &str) -> Result<Expression> {
1411 let sql_owned = sql.to_string();
1412 let handle = std::thread::Builder::new()
1413 .stack_size(16 * 1024 * 1024) .spawn(move || match crate::parser::Parser::parse_sql(&sql_owned) {
1415 Ok(stmts) => {
1416 if let Some(stmt) = stmts.into_iter().next() {
1417 Ok(Expression::Subquery(Box::new(Subquery {
1418 this: stmt,
1419 alias: None,
1420 column_aliases: Vec::new(),
1421 order_by: None,
1422 limit: None,
1423 offset: None,
1424 distribute_by: None,
1425 sort_by: None,
1426 cluster_by: None,
1427 lateral: false,
1428 modifiers_inside: false,
1429 trailing_comments: Vec::new(),
1430 inferred_type: None,
1431 })))
1432 } else {
1433 Err(crate::error::Error::Generate(
1434 "Failed to parse template SQL".to_string(),
1435 ))
1436 }
1437 }
1438 Err(e) => Err(e),
1439 })
1440 .map_err(|e| {
1441 crate::error::Error::Internal(format!("Failed to spawn parser thread: {}", e))
1442 })?;
1443
1444 handle
1445 .join()
1446 .map_err(|_| crate::error::Error::Internal("Parser thread panicked".to_string()))?
1447 }
1448
1449 fn normalize_empty_map_expr(expr: Expression) -> Expression {
1451 match expr {
1452 Expression::Cast(mut c) if matches!(&c.to, DataType::Map { .. }) => {
1453 if matches!(&c.this, Expression::Struct(s) if s.fields.is_empty()) {
1454 c.this =
1455 Expression::Function(Box::new(Function::new("MAP".to_string(), vec![])));
1456 }
1457 Expression::Cast(c)
1458 }
1459 other => other,
1460 }
1461 }
1462
1463 fn convert_bracket_to_quoted_path(path: &str) -> String {
1467 let mut result = String::new();
1468 let mut chars = path.chars().peekable();
1469 while let Some(c) = chars.next() {
1470 if c == '[' && chars.peek() == Some(&'"') {
1471 chars.next(); let mut key = String::new();
1474 while let Some(kc) = chars.next() {
1475 if kc == '"' && chars.peek() == Some(&']') {
1476 chars.next(); break;
1478 }
1479 key.push(kc);
1480 }
1481 if !result.is_empty() && !result.ends_with('.') {
1483 result.push('.');
1484 }
1485 result.push('"');
1486 result.push_str(&key);
1487 result.push('"');
1488 } else {
1489 result.push(c);
1490 }
1491 }
1492 result
1493 }
1494
1495 fn transform_data_type(&self, dt: crate::expressions::DataType) -> Result<Expression> {
1497 use crate::expressions::DataType;
1498 let transformed = match dt {
1499 DataType::Binary { length } => DataType::VarBinary { length },
1501 DataType::Blob => DataType::VarBinary { length: None },
1504 DataType::Char { .. } | DataType::VarChar { .. } => dt,
1506 DataType::Float {
1508 precision, scale, ..
1509 } => DataType::Float {
1510 precision,
1511 scale,
1512 real_spelling: true,
1513 },
1514 DataType::JsonB => DataType::Json,
1516 DataType::Custom { ref name } => {
1518 let upper = name.to_uppercase();
1519 match upper.as_str() {
1520 "INT64" | "INT8" => DataType::BigInt { length: None },
1522 "INT32" | "INT4" | "SIGNED" => DataType::Int {
1524 length: None,
1525 integer_spelling: false,
1526 },
1527 "INT16" => DataType::SmallInt { length: None },
1529 "INT1" => DataType::TinyInt { length: None },
1531 "HUGEINT" => DataType::Custom {
1533 name: "INT128".to_string(),
1534 },
1535 "UHUGEINT" => DataType::Custom {
1537 name: "UINT128".to_string(),
1538 },
1539 "BPCHAR" => DataType::Text,
1541 "CHARACTER VARYING" | "CHAR VARYING" => DataType::Text,
1543 "FLOAT4" => DataType::Custom {
1545 name: "REAL".to_string(),
1546 },
1547 "LOGICAL" => DataType::Boolean,
1549 "TIMESTAMPNTZ" | "TIMESTAMP_NTZ" => DataType::Timestamp {
1551 precision: None,
1552 timezone: false,
1553 },
1554 "TIMESTAMP_US" => DataType::Timestamp {
1556 precision: None,
1557 timezone: false,
1558 },
1559 "TIMESTAMPLTZ" | "TIMESTAMP_LTZ" | "TIMESTAMPTZ" | "TIMESTAMP_TZ" => {
1561 DataType::Timestamp {
1562 precision: None,
1563 timezone: true,
1564 }
1565 }
1566 "DECFLOAT" => DataType::Decimal {
1568 precision: Some(38),
1569 scale: Some(5),
1570 },
1571 _ => dt,
1573 }
1574 }
1575 other => other,
1577 };
1578 Ok(Expression::DataType(transformed))
1579 }
1580
1581 fn transform_interval(&self, interval: Interval) -> Result<Expression> {
1584 if interval.unit.is_some() {
1588 return Ok(Expression::Interval(Box::new(interval)));
1590 }
1591
1592 if let Some(Expression::Literal(ref lit)) = interval.this {
1593 if let Literal::String(ref s) = lit.as_ref() {
1594 if let Some((value, unit)) = Self::parse_interval_string(s) {
1596 return Ok(Expression::Interval(Box::new(Interval {
1598 this: Some(Expression::Literal(Box::new(Literal::String(
1599 value.to_string(),
1600 )))),
1601 unit: Some(IntervalUnitSpec::Simple {
1602 unit,
1603 use_plural: false, }),
1605 })));
1606 }
1607 }
1608 }
1609
1610 Ok(Expression::Interval(Box::new(interval)))
1612 }
1613
1614 fn parse_interval_string(s: &str) -> Option<(&str, IntervalUnit)> {
1617 let s = s.trim();
1618
1619 let mut num_end = 0;
1622 let mut chars = s.chars().peekable();
1623
1624 if chars.peek() == Some(&'-') {
1626 chars.next();
1627 num_end += 1;
1628 }
1629
1630 while let Some(&c) = chars.peek() {
1632 if c.is_ascii_digit() {
1633 chars.next();
1634 num_end += 1;
1635 } else {
1636 break;
1637 }
1638 }
1639
1640 if chars.peek() == Some(&'.') {
1642 chars.next();
1643 num_end += 1;
1644 while let Some(&c) = chars.peek() {
1645 if c.is_ascii_digit() {
1646 chars.next();
1647 num_end += 1;
1648 } else {
1649 break;
1650 }
1651 }
1652 }
1653
1654 if num_end == 0 || (num_end == 1 && s.starts_with('-')) {
1655 return None; }
1657
1658 let value = &s[..num_end];
1659 let rest = s[num_end..].trim();
1660
1661 if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_alphabetic()) {
1663 return None;
1664 }
1665
1666 let unit = match rest.to_uppercase().as_str() {
1668 "YEAR" | "YEARS" | "Y" => IntervalUnit::Year,
1669 "MONTH" | "MONTHS" | "MON" | "MONS" => IntervalUnit::Month,
1670 "DAY" | "DAYS" | "D" => IntervalUnit::Day,
1671 "HOUR" | "HOURS" | "H" | "HR" | "HRS" => IntervalUnit::Hour,
1672 "MINUTE" | "MINUTES" | "MIN" | "MINS" | "M" => IntervalUnit::Minute,
1673 "SECOND" | "SECONDS" | "SEC" | "SECS" | "S" => IntervalUnit::Second,
1674 "MILLISECOND" | "MILLISECONDS" | "MS" => IntervalUnit::Millisecond,
1675 "MICROSECOND" | "MICROSECONDS" | "US" => IntervalUnit::Microsecond,
1676 "QUARTER" | "QUARTERS" | "Q" => IntervalUnit::Quarter,
1677 "WEEK" | "WEEKS" | "W" => IntervalUnit::Week,
1678 _ => return None, };
1680
1681 Some((value, unit))
1682 }
1683
1684 fn transform_function(&self, f: Function) -> Result<Expression> {
1685 let name_upper = f.name.to_uppercase();
1686 match name_upper.as_str() {
1687 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1689 original_name: None,
1690 expressions: f.args,
1691 inferred_type: None,
1692 }))),
1693
1694 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1696 original_name: None,
1697 expressions: f.args,
1698 inferred_type: None,
1699 }))),
1700
1701 "ISNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1703 original_name: None,
1704 expressions: f.args,
1705 inferred_type: None,
1706 }))),
1707
1708 "ARRAY_COMPACT" if f.args.len() == 1 => {
1710 let arr = f.args.into_iter().next().unwrap();
1711 let lambda = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
1712 parameters: vec![Identifier::new("_u".to_string())],
1713 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
1714 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
1715 this: Expression::boxed_column(Column {
1716 table: None,
1717 name: Identifier::new("_u".to_string()),
1718 join_mark: false,
1719 trailing_comments: Vec::new(),
1720 span: None,
1721 inferred_type: None,
1722 }),
1723 not: false,
1724 postfix_form: false,
1725 })),
1726 inferred_type: None,
1727 })),
1728 colon: false,
1729 parameter_types: Vec::new(),
1730 }));
1731 Ok(Expression::Function(Box::new(Function::new(
1732 "LIST_FILTER".to_string(),
1733 vec![arr, lambda],
1734 ))))
1735 }
1736
1737 "ARRAY_CONSTRUCT_COMPACT" => Ok(Expression::Function(Box::new(f))),
1739
1740 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1742 Function::new("LISTAGG".to_string(), f.args),
1743 ))),
1744
1745 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
1747
1748 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1750 Function::new("LISTAGG".to_string(), f.args),
1751 ))),
1752
1753 "ARRAY_UNIQUE_AGG" if f.args.len() == 1 => {
1755 let col = f.args.into_iter().next().unwrap();
1756 let filter_expr = Expression::Not(Box::new(UnaryOp {
1758 this: Expression::IsNull(Box::new(IsNull {
1759 this: col.clone(),
1760 not: false,
1761 postfix_form: false,
1762 })),
1763 inferred_type: None,
1764 }));
1765 Ok(Expression::ArrayAgg(Box::new(AggFunc {
1766 this: col,
1767 distinct: true,
1768 filter: Some(filter_expr),
1769 order_by: Vec::new(),
1770 name: Some("LIST".to_string()),
1771 ignore_nulls: None,
1772 having_max: None,
1773 limit: None,
1774 inferred_type: None,
1775 })))
1776 }
1777
1778 "CHECK_JSON" if f.args.len() == 1 => {
1780 let x = f.args.into_iter().next().unwrap();
1781 let is_null = Expression::IsNull(Box::new(IsNull {
1783 this: x.clone(),
1784 not: false,
1785 postfix_form: false,
1786 }));
1787 let eq_empty = Expression::Eq(Box::new(BinaryOp::new(
1789 x.clone(),
1790 Expression::Literal(Box::new(Literal::String(String::new()))),
1791 )));
1792 let json_valid = Expression::Function(Box::new(Function::new(
1794 "JSON_VALID".to_string(),
1795 vec![x],
1796 )));
1797 let or1 = Expression::Or(Box::new(BinaryOp::new(is_null, eq_empty)));
1799 let condition = Expression::Or(Box::new(BinaryOp::new(or1, json_valid)));
1801 Ok(Expression::Case(Box::new(Case {
1802 operand: None,
1803 whens: vec![(condition, Expression::Null(Null))],
1804 else_: Some(Expression::Literal(Box::new(Literal::String(
1805 "Invalid JSON".to_string(),
1806 )))),
1807 comments: Vec::new(),
1808 inferred_type: None,
1809 })))
1810 }
1811
1812 "SUBSTR" => Ok(Expression::Function(Box::new(f))),
1814
1815 "FLATTEN" => Ok(Expression::Function(Box::new(Function::new(
1817 "UNNEST".to_string(),
1818 f.args,
1819 )))),
1820
1821 "ARRAY_FLATTEN" => Ok(Expression::Function(Box::new(Function::new(
1823 "FLATTEN".to_string(),
1824 f.args,
1825 )))),
1826
1827 "RPAD" if f.args.len() == 2 => {
1829 let mut args = f.args;
1830 args.push(Expression::Literal(Box::new(Literal::String(
1831 " ".to_string(),
1832 ))));
1833 Ok(Expression::Function(Box::new(Function::new(
1834 "RPAD".to_string(),
1835 args,
1836 ))))
1837 }
1838
1839 "BASE64_DECODE_STRING" => {
1842 let mut args = f.args;
1843 let input = args.remove(0);
1844 let has_alphabet = !args.is_empty();
1845 let decoded_input = if has_alphabet {
1846 let r1 = Expression::Function(Box::new(Function::new(
1848 "REPLACE".to_string(),
1849 vec![
1850 input,
1851 Expression::Literal(Box::new(Literal::String("-".to_string()))),
1852 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1853 ],
1854 )));
1855 let r2 = Expression::Function(Box::new(Function::new(
1856 "REPLACE".to_string(),
1857 vec![
1858 r1,
1859 Expression::Literal(Box::new(Literal::String("_".to_string()))),
1860 Expression::Literal(Box::new(Literal::String("/".to_string()))),
1861 ],
1862 )));
1863 Expression::Function(Box::new(Function::new(
1864 "REPLACE".to_string(),
1865 vec![
1866 r2,
1867 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1868 Expression::Literal(Box::new(Literal::String("=".to_string()))),
1869 ],
1870 )))
1871 } else {
1872 input
1873 };
1874 let from_base64 = Expression::Function(Box::new(Function::new(
1875 "FROM_BASE64".to_string(),
1876 vec![decoded_input],
1877 )));
1878 Ok(Expression::Function(Box::new(Function::new(
1879 "DECODE".to_string(),
1880 vec![from_base64],
1881 ))))
1882 }
1883
1884 "BASE64_DECODE_BINARY" => {
1887 let mut args = f.args;
1888 let input = args.remove(0);
1889 let has_alphabet = !args.is_empty();
1890 let decoded_input = if has_alphabet {
1891 let r1 = Expression::Function(Box::new(Function::new(
1892 "REPLACE".to_string(),
1893 vec![
1894 input,
1895 Expression::Literal(Box::new(Literal::String("-".to_string()))),
1896 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1897 ],
1898 )));
1899 let r2 = Expression::Function(Box::new(Function::new(
1900 "REPLACE".to_string(),
1901 vec![
1902 r1,
1903 Expression::Literal(Box::new(Literal::String("_".to_string()))),
1904 Expression::Literal(Box::new(Literal::String("/".to_string()))),
1905 ],
1906 )));
1907 Expression::Function(Box::new(Function::new(
1908 "REPLACE".to_string(),
1909 vec![
1910 r2,
1911 Expression::Literal(Box::new(Literal::String("+".to_string()))),
1912 Expression::Literal(Box::new(Literal::String("=".to_string()))),
1913 ],
1914 )))
1915 } else {
1916 input
1917 };
1918 Ok(Expression::Function(Box::new(Function::new(
1919 "FROM_BASE64".to_string(),
1920 vec![decoded_input],
1921 ))))
1922 }
1923
1924 "SPACE" if f.args.len() == 1 => {
1926 let arg = f.args.into_iter().next().unwrap();
1927 let cast_arg = Expression::Cast(Box::new(Cast {
1928 this: arg,
1929 to: DataType::BigInt { length: None },
1930 trailing_comments: Vec::new(),
1931 double_colon_syntax: false,
1932 format: None,
1933 default: None,
1934 inferred_type: None,
1935 }));
1936 Ok(Expression::Function(Box::new(Function::new(
1937 "REPEAT".to_string(),
1938 vec![
1939 Expression::Literal(Box::new(Literal::String(" ".to_string()))),
1940 cast_arg,
1941 ],
1942 ))))
1943 }
1944
1945 "IS_ARRAY" if f.args.len() == 1 => {
1947 let arg = f.args.into_iter().next().unwrap();
1948 let json_type = Expression::Function(Box::new(Function::new(
1949 "JSON_TYPE".to_string(),
1950 vec![arg],
1951 )));
1952 Ok(Expression::Eq(Box::new(BinaryOp {
1953 left: json_type,
1954 right: Expression::Literal(Box::new(Literal::String("ARRAY".to_string()))),
1955 left_comments: Vec::new(),
1956 operator_comments: Vec::new(),
1957 trailing_comments: Vec::new(),
1958 inferred_type: None,
1959 })))
1960 }
1961
1962 "EXPLODE" => Ok(Expression::Function(Box::new(Function::new(
1964 "UNNEST".to_string(),
1965 f.args,
1966 )))),
1967
1968 "NOW" => Ok(Expression::CurrentTimestamp(
1970 crate::expressions::CurrentTimestamp {
1971 precision: None,
1972 sysdate: false,
1973 },
1974 )),
1975
1976 "GETDATE" => Ok(Expression::CurrentTimestamp(
1978 crate::expressions::CurrentTimestamp {
1979 precision: None,
1980 sysdate: false,
1981 },
1982 )),
1983
1984 "TODAY" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1986
1987 "CURDATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1989
1990 "GET_CURRENT_TIME" => Ok(Expression::CurrentTime(crate::expressions::CurrentTime {
1992 precision: None,
1993 })),
1994
1995 "CURRENT_LOCALTIMESTAMP" => Ok(Expression::Localtimestamp(Box::new(
1997 crate::expressions::Localtimestamp { this: None },
1998 ))),
1999
2000 "REGEXP_EXTRACT_ALL" if f.args.len() == 3 => {
2002 if matches!(&f.args[2], Expression::Literal(lit) if matches!(lit.as_ref(), crate::expressions::Literal::Number(n) if n == "0"))
2004 {
2005 Ok(Expression::Function(Box::new(Function::new(
2006 "REGEXP_EXTRACT_ALL".to_string(),
2007 vec![f.args[0].clone(), f.args[1].clone()],
2008 ))))
2009 } else {
2010 Ok(Expression::Function(Box::new(Function::new(
2011 "REGEXP_EXTRACT_ALL".to_string(),
2012 f.args,
2013 ))))
2014 }
2015 }
2016
2017 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
2019
2020 "TO_DATE" if f.args.len() == 1 => {
2022 let arg = f.args.into_iter().next().unwrap();
2023 Ok(Expression::Cast(Box::new(Cast {
2024 this: arg,
2025 to: DataType::Date,
2026 trailing_comments: Vec::new(),
2027 double_colon_syntax: false,
2028 format: None,
2029 default: None,
2030 inferred_type: None,
2031 })))
2032 }
2033
2034 "DATE_FORMAT" if f.args.len() >= 2 => {
2038 let mut args = f.args;
2039 args[1] = Self::convert_format_to_duckdb(&args[1]);
2040 Ok(Expression::Function(Box::new(Function::new(
2041 "STRFTIME".to_string(),
2042 args,
2043 ))))
2044 }
2045
2046 "DATE_PARSE" if f.args.len() >= 2 => {
2048 let mut args = f.args;
2049 args[1] = Self::convert_format_to_duckdb(&args[1]);
2050 Ok(Expression::Function(Box::new(Function::new(
2051 "STRPTIME".to_string(),
2052 args,
2053 ))))
2054 }
2055
2056 "FORMAT_DATE" if f.args.len() >= 2 => {
2058 let mut args = f.args;
2059 args[1] = Self::convert_format_to_duckdb(&args[1]);
2060 Ok(Expression::Function(Box::new(Function::new(
2061 "STRFTIME".to_string(),
2062 args,
2063 ))))
2064 }
2065
2066 "TO_CHAR" if f.args.len() >= 2 => {
2068 let mut args = f.args;
2069 args[1] = Self::convert_format_to_duckdb(&args[1]);
2070 Ok(Expression::Function(Box::new(Function::new(
2071 "STRFTIME".to_string(),
2072 args,
2073 ))))
2074 }
2075
2076 "EPOCH_MS" => Ok(Expression::Function(Box::new(f))),
2078
2079 "EPOCH" => Ok(Expression::Function(Box::new(f))),
2081
2082 "FROM_UNIXTIME" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
2084 Function::new("TO_TIMESTAMP".to_string(), f.args),
2085 ))),
2086
2087 "UNIX_TIMESTAMP" => Ok(Expression::Function(Box::new(Function::new(
2089 "EPOCH".to_string(),
2090 f.args,
2091 )))),
2092
2093 "JSON_EXTRACT" if f.args.len() == 2 => {
2095 let mut args = f.args;
2096 let path = args.pop().unwrap();
2097 let this = args.pop().unwrap();
2098 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2099 this,
2100 path,
2101 returning: None,
2102 arrow_syntax: true,
2103 hash_arrow_syntax: false,
2104 wrapper_option: None,
2105 quotes_option: None,
2106 on_scalar_string: false,
2107 on_error: None,
2108 })))
2109 }
2110
2111 "JSON_EXTRACT_STRING" if f.args.len() == 2 => {
2113 let mut args = f.args;
2114 let path = args.pop().unwrap();
2115 let this = args.pop().unwrap();
2116 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
2117 this,
2118 path,
2119 returning: None,
2120 arrow_syntax: true,
2121 hash_arrow_syntax: false,
2122 wrapper_option: None,
2123 quotes_option: None,
2124 on_scalar_string: false,
2125 on_error: None,
2126 })))
2127 }
2128
2129 "ARRAY_CONSTRUCT" => Ok(Expression::Function(Box::new(Function::new(
2131 "list_value".to_string(),
2132 f.args,
2133 )))),
2134
2135 "ARRAY" => {
2138 let has_query = f
2140 .args
2141 .iter()
2142 .any(|a| matches!(a, Expression::Subquery(_) | Expression::Select(_)));
2143 if has_query {
2144 Ok(Expression::Function(Box::new(Function::new(
2146 "ARRAY".to_string(),
2147 f.args,
2148 ))))
2149 } else {
2150 Ok(Expression::Function(Box::new(Function::new(
2151 "list_value".to_string(),
2152 f.args,
2153 ))))
2154 }
2155 }
2156
2157 "LIST_VALUE" => Ok(Expression::Array(Box::new(crate::expressions::Array {
2159 expressions: f.args,
2160 }))),
2161
2162 "ARRAY_AGG" => Ok(Expression::Function(Box::new(Function::new(
2164 "list".to_string(),
2165 f.args,
2166 )))),
2167
2168 "LIST_CONTAINS" | "ARRAY_CONTAINS" => Ok(Expression::Function(Box::new(
2170 Function::new("ARRAY_CONTAINS".to_string(), f.args),
2171 ))),
2172
2173 "ARRAY_SIZE" | "CARDINALITY" => Ok(Expression::Function(Box::new(Function::new(
2175 "ARRAY_LENGTH".to_string(),
2176 f.args,
2177 )))),
2178
2179 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
2181 f.args.into_iter().next().unwrap(),
2182 )))),
2183
2184 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
2186 this: f.args.into_iter().next().unwrap(),
2187 decimals: None,
2188 to: None,
2189 }))),
2190
2191 "LOGICAL_OR" if f.args.len() == 1 => {
2193 let arg = f.args.into_iter().next().unwrap();
2194 Ok(Expression::Function(Box::new(Function::new(
2195 "BOOL_OR".to_string(),
2196 vec![Expression::Cast(Box::new(crate::expressions::Cast {
2197 this: arg,
2198 to: crate::expressions::DataType::Boolean,
2199 trailing_comments: Vec::new(),
2200 double_colon_syntax: false,
2201 format: None,
2202 default: None,
2203 inferred_type: None,
2204 }))],
2205 ))))
2206 }
2207
2208 "LOGICAL_AND" if f.args.len() == 1 => {
2210 let arg = f.args.into_iter().next().unwrap();
2211 Ok(Expression::Function(Box::new(Function::new(
2212 "BOOL_AND".to_string(),
2213 vec![Expression::Cast(Box::new(crate::expressions::Cast {
2214 this: arg,
2215 to: crate::expressions::DataType::Boolean,
2216 trailing_comments: Vec::new(),
2217 double_colon_syntax: false,
2218 format: None,
2219 default: None,
2220 inferred_type: None,
2221 }))],
2222 ))))
2223 }
2224
2225 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(Function::new(
2227 "REGEXP_MATCHES".to_string(),
2228 f.args,
2229 )))),
2230
2231 "POSITION" => Ok(Expression::Function(Box::new(f))),
2233
2234 "CHARINDEX" if f.args.len() == 2 => {
2236 let mut args = f.args;
2237 let substr = args.remove(0);
2238 let str_expr = args.remove(0);
2239 Ok(Expression::Function(Box::new(Function::new(
2240 "STRPOS".to_string(),
2241 vec![str_expr, substr],
2242 ))))
2243 }
2244
2245 "CHARINDEX" if f.args.len() == 3 => {
2251 let mut args = f.args;
2252 let substr = args.remove(0);
2253 let str_expr = args.remove(0);
2254 let pos = args.remove(0);
2255
2256 let zero = Expression::Literal(Box::new(Literal::Number("0".to_string())));
2257 let one = Expression::Literal(Box::new(Literal::Number("1".to_string())));
2258
2259 let pos_case = Expression::Case(Box::new(Case {
2261 operand: None,
2262 whens: vec![(
2263 Expression::Lte(Box::new(BinaryOp::new(pos.clone(), zero.clone()))),
2264 one.clone(),
2265 )],
2266 else_: Some(pos.clone()),
2267 comments: Vec::new(),
2268 inferred_type: None,
2269 }));
2270
2271 let substring_expr = Expression::Substring(Box::new(SubstringFunc {
2273 this: str_expr,
2274 start: pos_case.clone(),
2275 length: None,
2276 from_for_syntax: false,
2277 }));
2278
2279 let strpos = Expression::Function(Box::new(Function::new(
2281 "STRPOS".to_string(),
2282 vec![substring_expr, substr],
2283 )));
2284
2285 let eq_zero = Expression::Eq(Box::new(BinaryOp::new(strpos.clone(), zero.clone())));
2287
2288 let add_pos = Expression::Add(Box::new(BinaryOp::new(strpos, pos_case)));
2290 let sub_one = Expression::Sub(Box::new(BinaryOp::new(add_pos, one)));
2291
2292 Ok(Expression::Case(Box::new(Case {
2293 operand: None,
2294 whens: vec![(eq_zero, zero)],
2295 else_: Some(sub_one),
2296 comments: Vec::new(),
2297 inferred_type: None,
2298 })))
2299 }
2300
2301 "SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2303 "STR_SPLIT".to_string(),
2304 f.args,
2305 )))),
2306
2307 "STRING_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2309 "STR_SPLIT".to_string(),
2310 f.args,
2311 )))),
2312
2313 "STRTOK_TO_ARRAY" => Ok(Expression::Function(Box::new(Function::new(
2315 "STR_SPLIT".to_string(),
2316 f.args,
2317 )))),
2318
2319 "REGEXP_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2321 "STR_SPLIT_REGEX".to_string(),
2322 f.args,
2323 )))),
2324
2325 "EDITDIST3" => Ok(Expression::Function(Box::new(Function::new(
2327 "LEVENSHTEIN".to_string(),
2328 f.args,
2329 )))),
2330
2331 "JSON_EXTRACT_PATH" if f.args.len() >= 2 => {
2333 let mut args = f.args;
2334 let this = args.remove(0);
2335 let path = args.remove(0);
2336 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2337 this,
2338 path,
2339 returning: None,
2340 arrow_syntax: true,
2341 hash_arrow_syntax: false,
2342 wrapper_option: None,
2343 quotes_option: None,
2344 on_scalar_string: false,
2345 on_error: None,
2346 })))
2347 }
2348
2349 "JSON_EXTRACT_PATH_TEXT" if f.args.len() >= 2 => {
2351 let mut args = f.args;
2352 let this = args.remove(0);
2353 let path = args.remove(0);
2354 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
2355 this,
2356 path,
2357 returning: None,
2358 arrow_syntax: true,
2359 hash_arrow_syntax: false,
2360 wrapper_option: None,
2361 quotes_option: None,
2362 on_scalar_string: false,
2363 on_error: None,
2364 })))
2365 }
2366
2367 "DATE_ADD" if f.args.len() == 2 => {
2369 let mut args = f.args;
2370 let date = args.remove(0);
2371 let interval = args.remove(0);
2372 Ok(Expression::Add(Box::new(BinaryOp {
2373 left: date,
2374 right: interval,
2375 left_comments: Vec::new(),
2376 operator_comments: Vec::new(),
2377 trailing_comments: Vec::new(),
2378 inferred_type: None,
2379 })))
2380 }
2381
2382 "DATE_SUB" if f.args.len() == 2 => {
2384 let mut args = f.args;
2385 let date = args.remove(0);
2386 let interval = args.remove(0);
2387 Ok(Expression::Sub(Box::new(BinaryOp {
2388 left: date,
2389 right: interval,
2390 left_comments: Vec::new(),
2391 operator_comments: Vec::new(),
2392 trailing_comments: Vec::new(),
2393 inferred_type: None,
2394 })))
2395 }
2396
2397 "RANGE" if f.args.len() == 1 => {
2399 let mut new_args = vec![Expression::number(0)];
2400 new_args.extend(f.args);
2401 Ok(Expression::Function(Box::new(Function::new(
2402 "RANGE".to_string(),
2403 new_args,
2404 ))))
2405 }
2406
2407 "GENERATE_SERIES" if f.args.len() == 1 => {
2409 let mut new_args = vec![Expression::number(0)];
2410 new_args.extend(f.args);
2411 Ok(Expression::Function(Box::new(Function::new(
2412 "GENERATE_SERIES".to_string(),
2413 new_args,
2414 ))))
2415 }
2416
2417 "REGEXP_EXTRACT" if f.args.len() == 3 => {
2420 let drop_group = match &f.args[2] {
2422 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
2423 let Literal::Number(n) = lit.as_ref() else {
2424 unreachable!()
2425 };
2426 n == "0"
2427 }
2428 _ => false,
2429 };
2430 if drop_group {
2431 Ok(Expression::Function(Box::new(Function::new(
2432 "REGEXP_EXTRACT".to_string(),
2433 vec![f.args[0].clone(), f.args[1].clone()],
2434 ))))
2435 } else {
2436 Ok(Expression::Function(Box::new(f)))
2437 }
2438 }
2439
2440 "STRUCT_PACK" => {
2442 let mut fields = Vec::new();
2443 for arg in f.args {
2444 match arg {
2445 Expression::NamedArgument(na) => {
2446 fields.push((Some(na.name.name.clone()), na.value));
2447 }
2448 other => {
2450 fields.push((None, other));
2451 }
2452 }
2453 }
2454 Ok(Expression::Struct(Box::new(Struct { fields })))
2455 }
2456
2457 "REPLACE" if f.args.len() == 2 => {
2459 let mut args = f.args;
2460 args.push(Expression::Literal(Box::new(
2461 Literal::String(String::new()),
2462 )));
2463 Ok(Expression::Function(Box::new(Function::new(
2464 "REPLACE".to_string(),
2465 args,
2466 ))))
2467 }
2468
2469 "TO_UNIXTIME" => Ok(Expression::Function(Box::new(Function::new(
2471 "EPOCH".to_string(),
2472 f.args,
2473 )))),
2474
2475 "FROM_ISO8601_TIMESTAMP" if f.args.len() == 1 => {
2477 use crate::expressions::{Cast, DataType};
2478 Ok(Expression::Cast(Box::new(Cast {
2479 this: f.args.into_iter().next().unwrap(),
2480 to: DataType::Timestamp {
2481 precision: None,
2482 timezone: true,
2483 },
2484 trailing_comments: Vec::new(),
2485 double_colon_syntax: false,
2486 format: None,
2487 default: None,
2488 inferred_type: None,
2489 })))
2490 }
2491
2492 "APPROX_DISTINCT" => {
2494 let args = if f.args.len() > 1 {
2496 vec![f.args.into_iter().next().unwrap()]
2497 } else {
2498 f.args
2499 };
2500 Ok(Expression::Function(Box::new(Function::new(
2501 "APPROX_COUNT_DISTINCT".to_string(),
2502 args,
2503 ))))
2504 }
2505
2506 "ARRAY_SORT" => {
2508 let args = vec![f.args.into_iter().next().unwrap()];
2509 Ok(Expression::Function(Box::new(Function::new(
2510 "ARRAY_SORT".to_string(),
2511 args,
2512 ))))
2513 }
2514
2515 "TO_UTF8" => Ok(Expression::Function(Box::new(Function::new(
2517 "ENCODE".to_string(),
2518 f.args,
2519 )))),
2520
2521 "FROM_UTF8" => Ok(Expression::Function(Box::new(Function::new(
2523 "DECODE".to_string(),
2524 f.args,
2525 )))),
2526
2527 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
2529 "ANY_VALUE".to_string(),
2530 f.args,
2531 )))),
2532
2533 "MAX_BY" => Ok(Expression::Function(Box::new(Function::new(
2535 "ARG_MAX".to_string(),
2536 f.args,
2537 )))),
2538
2539 "MIN_BY" => Ok(Expression::Function(Box::new(Function::new(
2541 "ARG_MIN".to_string(),
2542 f.args,
2543 )))),
2544
2545 "IFF" if f.args.len() == 3 => {
2547 let mut args = f.args;
2548 let cond = args.remove(0);
2549 let true_val = args.remove(0);
2550 let false_val = args.remove(0);
2551 Ok(Expression::Case(Box::new(Case {
2552 operand: None,
2553 whens: vec![(cond, true_val)],
2554 else_: Some(false_val),
2555 comments: Vec::new(),
2556 inferred_type: None,
2557 })))
2558 }
2559 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
2560 "SKEWNESS".to_string(),
2561 f.args,
2562 )))),
2563 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2564 "VARIANCE".to_string(),
2565 f.args,
2566 )))),
2567 "VARIANCE_POP" => Ok(Expression::Function(Box::new(Function::new(
2568 "VAR_POP".to_string(),
2569 f.args,
2570 )))),
2571 "REGR_VALX" if f.args.len() == 2 => {
2572 let mut args = f.args;
2573 let y = args.remove(0);
2574 let x = args.remove(0);
2575 Ok(Expression::Case(Box::new(Case {
2576 operand: None,
2577 whens: vec![(
2578 Expression::IsNull(Box::new(crate::expressions::IsNull {
2579 this: y,
2580 not: false,
2581 postfix_form: false,
2582 })),
2583 Expression::Cast(Box::new(Cast {
2584 this: Expression::Null(crate::expressions::Null),
2585 to: DataType::Double {
2586 precision: None,
2587 scale: None,
2588 },
2589 trailing_comments: Vec::new(),
2590 double_colon_syntax: false,
2591 format: None,
2592 default: None,
2593 inferred_type: None,
2594 })),
2595 )],
2596 else_: Some(x),
2597 comments: Vec::new(),
2598 inferred_type: None,
2599 })))
2600 }
2601 "REGR_VALY" if f.args.len() == 2 => {
2602 let mut args = f.args;
2603 let y = args.remove(0);
2604 let x = args.remove(0);
2605 Ok(Expression::Case(Box::new(Case {
2606 operand: None,
2607 whens: vec![(
2608 Expression::IsNull(Box::new(crate::expressions::IsNull {
2609 this: x,
2610 not: false,
2611 postfix_form: false,
2612 })),
2613 Expression::Cast(Box::new(Cast {
2614 this: Expression::Null(crate::expressions::Null),
2615 to: DataType::Double {
2616 precision: None,
2617 scale: None,
2618 },
2619 trailing_comments: Vec::new(),
2620 double_colon_syntax: false,
2621 format: None,
2622 default: None,
2623 inferred_type: None,
2624 })),
2625 )],
2626 else_: Some(y),
2627 comments: Vec::new(),
2628 inferred_type: None,
2629 })))
2630 }
2631 "BOOLNOT" if f.args.len() == 1 => {
2632 let arg = f.args.into_iter().next().unwrap();
2633 let rounded = Expression::Function(Box::new(Function::new(
2635 "ROUND".to_string(),
2636 vec![arg, Expression::number(0)],
2637 )));
2638 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
2639 this: Expression::Paren(Box::new(Paren {
2640 this: rounded,
2641 trailing_comments: Vec::new(),
2642 })),
2643 inferred_type: None,
2644 })))
2645 }
2646 "BITMAP_BIT_POSITION" if f.args.len() == 1 => {
2647 let n = f.args.into_iter().next().unwrap();
2648 let case_expr = Expression::Case(Box::new(Case {
2649 operand: None,
2650 whens: vec![(
2651 Expression::Gt(Box::new(BinaryOp {
2652 left: n.clone(),
2653 right: Expression::number(0),
2654 left_comments: Vec::new(),
2655 operator_comments: Vec::new(),
2656 trailing_comments: Vec::new(),
2657 inferred_type: None,
2658 })),
2659 Expression::Sub(Box::new(BinaryOp {
2660 left: n.clone(),
2661 right: Expression::number(1),
2662 left_comments: Vec::new(),
2663 operator_comments: Vec::new(),
2664 trailing_comments: Vec::new(),
2665 inferred_type: None,
2666 })),
2667 )],
2668 else_: Some(Expression::Abs(Box::new(UnaryFunc {
2669 this: n,
2670 original_name: None,
2671 inferred_type: None,
2672 }))),
2673 comments: Vec::new(),
2674 inferred_type: None,
2675 }));
2676 Ok(Expression::Mod(Box::new(BinaryOp {
2677 left: Expression::Paren(Box::new(Paren {
2678 this: case_expr,
2679 trailing_comments: Vec::new(),
2680 })),
2681 right: Expression::number(32768),
2682 left_comments: Vec::new(),
2683 operator_comments: Vec::new(),
2684 trailing_comments: Vec::new(),
2685 inferred_type: None,
2686 })))
2687 }
2688 "GREATEST" | "LEAST" => Ok(Expression::Function(Box::new(f))),
2690 "GREATEST_IGNORE_NULLS" => Ok(Expression::Greatest(Box::new(VarArgFunc {
2691 expressions: f.args,
2692 original_name: None,
2693 inferred_type: None,
2694 }))),
2695 "LEAST_IGNORE_NULLS" => Ok(Expression::Least(Box::new(VarArgFunc {
2696 expressions: f.args,
2697 original_name: None,
2698 inferred_type: None,
2699 }))),
2700 "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
2701 "JSON".to_string(),
2702 f.args,
2703 )))),
2704 "TRY_PARSE_JSON" if f.args.len() == 1 => {
2706 let x = f.args.into_iter().next().unwrap();
2707 let json_valid = Expression::Function(Box::new(Function::new(
2708 "JSON_VALID".to_string(),
2709 vec![x.clone()],
2710 )));
2711 let cast_json = Expression::Cast(Box::new(crate::expressions::Cast {
2712 this: x,
2713 to: DataType::Json,
2714 double_colon_syntax: false,
2715 trailing_comments: Vec::new(),
2716 format: None,
2717 default: None,
2718 inferred_type: None,
2719 }));
2720 Ok(Expression::Case(Box::new(crate::expressions::Case {
2721 operand: None,
2722 whens: vec![(json_valid, cast_json)],
2723 else_: Some(Expression::Null(crate::expressions::Null)),
2724 comments: Vec::new(),
2725 inferred_type: None,
2726 })))
2727 }
2728 "OBJECT_CONSTRUCT_KEEP_NULL" => {
2729 Ok(Expression::Function(Box::new(Function::new(
2731 "JSON_OBJECT".to_string(),
2732 f.args,
2733 ))))
2734 }
2735 "OBJECT_CONSTRUCT" => {
2736 let args = f.args;
2738 if args.is_empty() {
2739 Ok(Expression::Function(Box::new(Function::new(
2741 "STRUCT_PACK".to_string(),
2742 vec![],
2743 ))))
2744 } else {
2745 let mut fields = Vec::new();
2747 let mut i = 0;
2748 while i + 1 < args.len() {
2749 let key = &args[i];
2750 let value = args[i + 1].clone();
2751 let key_name = match key {
2752 Expression::Literal(lit)
2753 if matches!(lit.as_ref(), Literal::String(_)) =>
2754 {
2755 let Literal::String(s) = lit.as_ref() else {
2756 unreachable!()
2757 };
2758 Some(s.clone())
2759 }
2760 _ => None,
2761 };
2762 fields.push((key_name, value));
2763 i += 2;
2764 }
2765 Ok(Expression::Struct(Box::new(Struct { fields })))
2766 }
2767 }
2768 "IS_NULL_VALUE" if f.args.len() == 1 => {
2769 let arg = f.args.into_iter().next().unwrap();
2770 Ok(Expression::Eq(Box::new(BinaryOp {
2771 left: Expression::Function(Box::new(Function::new(
2772 "JSON_TYPE".to_string(),
2773 vec![arg],
2774 ))),
2775 right: Expression::Literal(Box::new(Literal::String("NULL".to_string()))),
2776 left_comments: Vec::new(),
2777 operator_comments: Vec::new(),
2778 trailing_comments: Vec::new(),
2779 inferred_type: None,
2780 })))
2781 }
2782 "TRY_TO_DOUBLE" | "TRY_TO_NUMBER" | "TRY_TO_NUMERIC" | "TRY_TO_DECIMAL"
2783 if f.args.len() == 1 =>
2784 {
2785 let arg = f.args.into_iter().next().unwrap();
2786 Ok(Expression::TryCast(Box::new(Cast {
2787 this: arg,
2788 to: DataType::Double {
2789 precision: None,
2790 scale: None,
2791 },
2792 trailing_comments: Vec::new(),
2793 double_colon_syntax: false,
2794 format: None,
2795 default: None,
2796 inferred_type: None,
2797 })))
2798 }
2799 "TRY_TO_TIME" if f.args.len() == 1 => {
2800 let arg = f.args.into_iter().next().unwrap();
2801 Ok(Expression::TryCast(Box::new(Cast {
2802 this: arg,
2803 to: DataType::Time {
2804 precision: None,
2805 timezone: false,
2806 },
2807 trailing_comments: Vec::new(),
2808 double_colon_syntax: false,
2809 format: None,
2810 default: None,
2811 inferred_type: None,
2812 })))
2813 }
2814 "TRY_TO_TIME" if f.args.len() == 2 => {
2815 let mut args = f.args;
2816 let value = args.remove(0);
2817 let fmt = self.convert_snowflake_time_format(args.remove(0));
2818 Ok(Expression::TryCast(Box::new(Cast {
2819 this: Expression::Function(Box::new(Function::new(
2820 "TRY_STRPTIME".to_string(),
2821 vec![value, fmt],
2822 ))),
2823 to: DataType::Time {
2824 precision: None,
2825 timezone: false,
2826 },
2827 trailing_comments: Vec::new(),
2828 double_colon_syntax: false,
2829 format: None,
2830 default: None,
2831 inferred_type: None,
2832 })))
2833 }
2834 "TRY_TO_TIMESTAMP" if f.args.len() == 1 => {
2835 let arg = f.args.into_iter().next().unwrap();
2836 Ok(Expression::TryCast(Box::new(Cast {
2837 this: arg,
2838 to: DataType::Timestamp {
2839 precision: None,
2840 timezone: false,
2841 },
2842 trailing_comments: Vec::new(),
2843 double_colon_syntax: false,
2844 format: None,
2845 default: None,
2846 inferred_type: None,
2847 })))
2848 }
2849 "TRY_TO_TIMESTAMP" if f.args.len() == 2 => {
2850 let mut args = f.args;
2851 let value = args.remove(0);
2852 let fmt = self.convert_snowflake_time_format(args.remove(0));
2853 Ok(Expression::Cast(Box::new(Cast {
2854 this: Expression::Function(Box::new(Function::new(
2855 "TRY_STRPTIME".to_string(),
2856 vec![value, fmt],
2857 ))),
2858 to: DataType::Timestamp {
2859 precision: None,
2860 timezone: false,
2861 },
2862 trailing_comments: Vec::new(),
2863 double_colon_syntax: false,
2864 format: None,
2865 default: None,
2866 inferred_type: None,
2867 })))
2868 }
2869 "TRY_TO_DATE" if f.args.len() == 1 => {
2870 let arg = f.args.into_iter().next().unwrap();
2871 Ok(Expression::TryCast(Box::new(Cast {
2872 this: arg,
2873 to: DataType::Date,
2874 trailing_comments: Vec::new(),
2875 double_colon_syntax: false,
2876 format: None,
2877 default: None,
2878 inferred_type: None,
2879 })))
2880 }
2881 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Function(Box::new(Function::new(
2882 "ISODOW".to_string(),
2883 f.args,
2884 )))),
2885 "YEAROFWEEK" | "YEAROFWEEKISO" if f.args.len() == 1 => {
2886 let arg = f.args.into_iter().next().unwrap();
2887 Ok(Expression::Extract(Box::new(
2888 crate::expressions::ExtractFunc {
2889 this: arg,
2890 field: crate::expressions::DateTimeField::Custom("ISOYEAR".to_string()),
2891 },
2892 )))
2893 }
2894 "WEEKISO" => Ok(Expression::Function(Box::new(Function::new(
2895 "WEEKOFYEAR".to_string(),
2896 f.args,
2897 )))),
2898 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 3 => {
2899 let args_ref = &f.args;
2900 let all_in_range = if let (Some(h_val), Some(m_val), Some(s_val)) = (
2902 Self::extract_number_value(&args_ref[0]),
2903 Self::extract_number_value(&args_ref[1]),
2904 Self::extract_number_value(&args_ref[2]),
2905 ) {
2906 h_val >= 0.0
2907 && h_val < 24.0
2908 && m_val >= 0.0
2909 && m_val < 60.0
2910 && s_val >= 0.0
2911 && s_val < 60.0
2912 } else {
2913 false
2914 };
2915 if all_in_range {
2916 Ok(Expression::Function(Box::new(Function::new(
2918 "MAKE_TIME".to_string(),
2919 f.args,
2920 ))))
2921 } else {
2922 let mut args = f.args;
2925 let h = args.remove(0);
2926 let m = args.remove(0);
2927 let s = args.remove(0);
2928 let seconds_expr = Expression::Add(Box::new(BinaryOp {
2929 left: Expression::Add(Box::new(BinaryOp {
2930 left: Expression::Paren(Box::new(Paren {
2931 this: Expression::Mul(Box::new(BinaryOp {
2932 left: h,
2933 right: Expression::number(3600),
2934 left_comments: Vec::new(),
2935 operator_comments: Vec::new(),
2936 trailing_comments: Vec::new(),
2937 inferred_type: None,
2938 })),
2939 trailing_comments: Vec::new(),
2940 })),
2941 right: Expression::Paren(Box::new(Paren {
2942 this: Expression::Mul(Box::new(BinaryOp {
2943 left: m,
2944 right: Expression::number(60),
2945 left_comments: Vec::new(),
2946 operator_comments: Vec::new(),
2947 trailing_comments: Vec::new(),
2948 inferred_type: None,
2949 })),
2950 trailing_comments: Vec::new(),
2951 })),
2952 left_comments: Vec::new(),
2953 operator_comments: Vec::new(),
2954 trailing_comments: Vec::new(),
2955 inferred_type: None,
2956 })),
2957 right: s,
2958 left_comments: Vec::new(),
2959 operator_comments: Vec::new(),
2960 trailing_comments: Vec::new(),
2961 inferred_type: None,
2962 }));
2963 let base_time = Expression::Cast(Box::new(Cast {
2964 this: Expression::Literal(Box::new(Literal::String(
2965 "00:00:00".to_string(),
2966 ))),
2967 to: DataType::Time {
2968 precision: None,
2969 timezone: false,
2970 },
2971 trailing_comments: Vec::new(),
2972 double_colon_syntax: false,
2973 format: None,
2974 default: None,
2975 inferred_type: None,
2976 }));
2977 Ok(Expression::Add(Box::new(BinaryOp {
2978 left: base_time,
2979 right: Expression::Interval(Box::new(Interval {
2980 this: Some(Expression::Paren(Box::new(crate::expressions::Paren {
2981 this: seconds_expr,
2982 trailing_comments: Vec::new(),
2983 }))),
2984 unit: Some(IntervalUnitSpec::Simple {
2985 unit: IntervalUnit::Second,
2986 use_plural: false,
2987 }),
2988 })),
2989 left_comments: Vec::new(),
2990 operator_comments: Vec::new(),
2991 trailing_comments: Vec::new(),
2992 inferred_type: None,
2993 })))
2994 }
2995 }
2996 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 4 => {
2997 let mut args = f.args;
2998 let h = args.remove(0);
2999 let m = args.remove(0);
3000 let s = args.remove(0);
3001 let ns = args.remove(0);
3002 let seconds_expr = Expression::Add(Box::new(BinaryOp {
3003 left: Expression::Add(Box::new(BinaryOp {
3004 left: Expression::Add(Box::new(BinaryOp {
3005 left: Expression::Paren(Box::new(Paren {
3006 this: Expression::Mul(Box::new(BinaryOp {
3007 left: h,
3008 right: Expression::number(3600),
3009 left_comments: Vec::new(),
3010 operator_comments: Vec::new(),
3011 trailing_comments: Vec::new(),
3012 inferred_type: None,
3013 })),
3014 trailing_comments: Vec::new(),
3015 })),
3016 right: Expression::Paren(Box::new(Paren {
3017 this: Expression::Mul(Box::new(BinaryOp {
3018 left: m,
3019 right: Expression::number(60),
3020 left_comments: Vec::new(),
3021 operator_comments: Vec::new(),
3022 trailing_comments: Vec::new(),
3023 inferred_type: None,
3024 })),
3025 trailing_comments: Vec::new(),
3026 })),
3027 left_comments: Vec::new(),
3028 operator_comments: Vec::new(),
3029 trailing_comments: Vec::new(),
3030 inferred_type: None,
3031 })),
3032 right: s,
3033 left_comments: Vec::new(),
3034 operator_comments: Vec::new(),
3035 trailing_comments: Vec::new(),
3036 inferred_type: None,
3037 })),
3038 right: Expression::Paren(Box::new(Paren {
3039 this: Expression::Div(Box::new(BinaryOp {
3040 left: ns,
3041 right: Expression::Literal(Box::new(Literal::Number(
3042 "1000000000.0".to_string(),
3043 ))),
3044 left_comments: Vec::new(),
3045 operator_comments: Vec::new(),
3046 trailing_comments: Vec::new(),
3047 inferred_type: None,
3048 })),
3049 trailing_comments: Vec::new(),
3050 })),
3051 left_comments: Vec::new(),
3052 operator_comments: Vec::new(),
3053 trailing_comments: Vec::new(),
3054 inferred_type: None,
3055 }));
3056 let base_time = Expression::Cast(Box::new(Cast {
3057 this: Expression::Literal(Box::new(Literal::String("00:00:00".to_string()))),
3058 to: DataType::Time {
3059 precision: None,
3060 timezone: false,
3061 },
3062 trailing_comments: Vec::new(),
3063 double_colon_syntax: false,
3064 format: None,
3065 default: None,
3066 inferred_type: None,
3067 }));
3068 Ok(Expression::Add(Box::new(BinaryOp {
3069 left: base_time,
3070 right: Expression::Interval(Box::new(Interval {
3071 this: Some(Expression::Paren(Box::new(crate::expressions::Paren {
3072 this: seconds_expr,
3073 trailing_comments: Vec::new(),
3074 }))),
3075 unit: Some(IntervalUnitSpec::Simple {
3076 unit: IntervalUnit::Second,
3077 use_plural: false,
3078 }),
3079 })),
3080 left_comments: Vec::new(),
3081 operator_comments: Vec::new(),
3082 trailing_comments: Vec::new(),
3083 inferred_type: None,
3084 })))
3085 }
3086 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" if f.args.len() == 6 => {
3087 Ok(Expression::Function(Box::new(Function::new(
3088 "MAKE_TIMESTAMP".to_string(),
3089 f.args,
3090 ))))
3091 }
3092 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMP_NTZ_FROM_PARTS"
3093 if f.args.len() == 2 =>
3094 {
3095 let mut args = f.args;
3096 let d = args.remove(0);
3097 let t = args.remove(0);
3098 Ok(Expression::Add(Box::new(BinaryOp {
3099 left: d,
3100 right: t,
3101 left_comments: Vec::new(),
3102 operator_comments: Vec::new(),
3103 trailing_comments: Vec::new(),
3104 inferred_type: None,
3105 })))
3106 }
3107 "TIMESTAMP_LTZ_FROM_PARTS" if f.args.len() == 6 => {
3108 Ok(Expression::Cast(Box::new(Cast {
3109 this: Expression::Function(Box::new(Function::new(
3110 "MAKE_TIMESTAMP".to_string(),
3111 f.args,
3112 ))),
3113 to: DataType::Timestamp {
3114 precision: None,
3115 timezone: true,
3116 },
3117 trailing_comments: Vec::new(),
3118 double_colon_syntax: false,
3119 format: None,
3120 default: None,
3121 inferred_type: None,
3122 })))
3123 }
3124 "TIMESTAMP_TZ_FROM_PARTS" if f.args.len() == 8 => {
3125 let mut args = f.args;
3126 let ts_args = vec![
3127 args.remove(0),
3128 args.remove(0),
3129 args.remove(0),
3130 args.remove(0),
3131 args.remove(0),
3132 args.remove(0),
3133 ];
3134 let _nano = args.remove(0);
3135 let tz = args.remove(0);
3136 Ok(Expression::AtTimeZone(Box::new(
3137 crate::expressions::AtTimeZone {
3138 this: Expression::Function(Box::new(Function::new(
3139 "MAKE_TIMESTAMP".to_string(),
3140 ts_args,
3141 ))),
3142 zone: tz,
3143 },
3144 )))
3145 }
3146 "BOOLAND_AGG" if f.args.len() == 1 => {
3147 let arg = f.args.into_iter().next().unwrap();
3148 Ok(Expression::Function(Box::new(Function::new(
3149 "BOOL_AND".to_string(),
3150 vec![Expression::Cast(Box::new(Cast {
3151 this: arg,
3152 to: DataType::Boolean,
3153 trailing_comments: Vec::new(),
3154 double_colon_syntax: false,
3155 format: None,
3156 default: None,
3157 inferred_type: None,
3158 }))],
3159 ))))
3160 }
3161 "BOOLOR_AGG" if f.args.len() == 1 => {
3162 let arg = f.args.into_iter().next().unwrap();
3163 Ok(Expression::Function(Box::new(Function::new(
3164 "BOOL_OR".to_string(),
3165 vec![Expression::Cast(Box::new(Cast {
3166 this: arg,
3167 to: DataType::Boolean,
3168 trailing_comments: Vec::new(),
3169 double_colon_syntax: false,
3170 format: None,
3171 default: None,
3172 inferred_type: None,
3173 }))],
3174 ))))
3175 }
3176 "NVL2" if f.args.len() == 3 => {
3177 let mut args = f.args;
3178 let a = args.remove(0);
3179 let b = args.remove(0);
3180 let c = args.remove(0);
3181 Ok(Expression::Case(Box::new(Case {
3182 operand: None,
3183 whens: vec![(
3184 Expression::Not(Box::new(crate::expressions::UnaryOp {
3185 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3186 this: a,
3187 not: false,
3188 postfix_form: false,
3189 })),
3190 inferred_type: None,
3191 })),
3192 b,
3193 )],
3194 else_: Some(c),
3195 comments: Vec::new(),
3196 inferred_type: None,
3197 })))
3198 }
3199 "EQUAL_NULL" if f.args.len() == 2 => {
3200 let mut args = f.args;
3201 let a = args.remove(0);
3202 let b = args.remove(0);
3203 Ok(Expression::NullSafeEq(Box::new(BinaryOp {
3204 left: a,
3205 right: b,
3206 left_comments: Vec::new(),
3207 operator_comments: Vec::new(),
3208 trailing_comments: Vec::new(),
3209 inferred_type: None,
3210 })))
3211 }
3212 "EDITDISTANCE" if f.args.len() == 3 => {
3213 let mut args = f.args;
3215 let a = args.remove(0);
3216 let b = args.remove(0);
3217 let max_dist = args.remove(0);
3218 let lev = Expression::Function(Box::new(Function::new(
3219 "LEVENSHTEIN".to_string(),
3220 vec![a, b],
3221 )));
3222 let lev_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
3223 this: lev.clone(),
3224 not: false,
3225 postfix_form: false,
3226 }));
3227 let max_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
3228 this: max_dist.clone(),
3229 not: false,
3230 postfix_form: false,
3231 }));
3232 let null_check = Expression::Or(Box::new(BinaryOp {
3233 left: lev_is_null,
3234 right: max_is_null,
3235 left_comments: Vec::new(),
3236 operator_comments: Vec::new(),
3237 trailing_comments: Vec::new(),
3238 inferred_type: None,
3239 }));
3240 let least = Expression::Least(Box::new(VarArgFunc {
3241 expressions: vec![lev, max_dist],
3242 original_name: None,
3243 inferred_type: None,
3244 }));
3245 Ok(Expression::Case(Box::new(Case {
3246 operand: None,
3247 whens: vec![(null_check, Expression::Null(crate::expressions::Null))],
3248 else_: Some(least),
3249 comments: Vec::new(),
3250 inferred_type: None,
3251 })))
3252 }
3253 "EDITDISTANCE" => Ok(Expression::Function(Box::new(Function::new(
3254 "LEVENSHTEIN".to_string(),
3255 f.args,
3256 )))),
3257 "BITAND" if f.args.len() == 2 => {
3258 let mut args = f.args;
3259 let left = args.remove(0);
3260 let right = args.remove(0);
3261 let wrap = |e: Expression| -> Expression {
3263 match &e {
3264 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) => {
3265 Expression::Paren(Box::new(Paren {
3266 this: e,
3267 trailing_comments: Vec::new(),
3268 }))
3269 }
3270 _ => e,
3271 }
3272 };
3273 Ok(Expression::BitwiseAnd(Box::new(BinaryOp {
3274 left: wrap(left),
3275 right: wrap(right),
3276 left_comments: Vec::new(),
3277 operator_comments: Vec::new(),
3278 trailing_comments: Vec::new(),
3279 inferred_type: None,
3280 })))
3281 }
3282 "BITOR" if f.args.len() == 2 => {
3283 let mut args = f.args;
3284 let left = args.remove(0);
3285 let right = args.remove(0);
3286 let wrap = |e: Expression| -> Expression {
3288 match &e {
3289 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) => {
3290 Expression::Paren(Box::new(Paren {
3291 this: e,
3292 trailing_comments: Vec::new(),
3293 }))
3294 }
3295 _ => e,
3296 }
3297 };
3298 Ok(Expression::BitwiseOr(Box::new(BinaryOp {
3299 left: wrap(left),
3300 right: wrap(right),
3301 left_comments: Vec::new(),
3302 operator_comments: Vec::new(),
3303 trailing_comments: Vec::new(),
3304 inferred_type: None,
3305 })))
3306 }
3307 "BITXOR" if f.args.len() == 2 => {
3308 let mut args = f.args;
3309 Ok(Expression::BitwiseXor(Box::new(BinaryOp {
3310 left: args.remove(0),
3311 right: args.remove(0),
3312 left_comments: Vec::new(),
3313 operator_comments: Vec::new(),
3314 trailing_comments: Vec::new(),
3315 inferred_type: None,
3316 })))
3317 }
3318 "BITNOT" if f.args.len() == 1 => {
3319 let arg = f.args.into_iter().next().unwrap();
3320 Ok(Expression::BitwiseNot(Box::new(
3321 crate::expressions::UnaryOp {
3322 this: Expression::Paren(Box::new(Paren {
3323 this: arg,
3324 trailing_comments: Vec::new(),
3325 })),
3326 inferred_type: None,
3327 },
3328 )))
3329 }
3330 "BITSHIFTLEFT" if f.args.len() == 2 => {
3331 let mut args = f.args;
3332 let a = args.remove(0);
3333 let b = args.remove(0);
3334 let is_binary = if let Expression::Cast(ref c) = a {
3336 matches!(
3337 &c.to,
3338 DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob
3339 ) || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
3340 } else {
3341 false
3342 };
3343 if is_binary {
3344 let cast_to_bit = Expression::Cast(Box::new(Cast {
3346 this: a,
3347 to: DataType::Custom {
3348 name: "BIT".to_string(),
3349 },
3350 trailing_comments: Vec::new(),
3351 double_colon_syntax: false,
3352 format: None,
3353 default: None,
3354 inferred_type: None,
3355 }));
3356 let shift = Expression::BitwiseLeftShift(Box::new(BinaryOp {
3357 left: cast_to_bit,
3358 right: b,
3359 left_comments: Vec::new(),
3360 operator_comments: Vec::new(),
3361 trailing_comments: Vec::new(),
3362 inferred_type: None,
3363 }));
3364 Ok(Expression::Cast(Box::new(Cast {
3365 this: shift,
3366 to: DataType::Custom {
3367 name: "BLOB".to_string(),
3368 },
3369 trailing_comments: Vec::new(),
3370 double_colon_syntax: false,
3371 format: None,
3372 default: None,
3373 inferred_type: None,
3374 })))
3375 } else {
3376 Ok(Expression::BitwiseLeftShift(Box::new(BinaryOp {
3377 left: Expression::Cast(Box::new(Cast {
3378 this: a,
3379 to: DataType::Custom {
3380 name: "INT128".to_string(),
3381 },
3382 trailing_comments: Vec::new(),
3383 double_colon_syntax: false,
3384 format: None,
3385 default: None,
3386 inferred_type: None,
3387 })),
3388 right: b,
3389 left_comments: Vec::new(),
3390 operator_comments: Vec::new(),
3391 trailing_comments: Vec::new(),
3392 inferred_type: None,
3393 })))
3394 }
3395 }
3396 "BITSHIFTRIGHT" if f.args.len() == 2 => {
3397 let mut args = f.args;
3398 let a = args.remove(0);
3399 let b = args.remove(0);
3400 let is_binary = if let Expression::Cast(ref c) = a {
3402 matches!(
3403 &c.to,
3404 DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob
3405 ) || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
3406 } else {
3407 false
3408 };
3409 if is_binary {
3410 let cast_to_bit = Expression::Cast(Box::new(Cast {
3412 this: a,
3413 to: DataType::Custom {
3414 name: "BIT".to_string(),
3415 },
3416 trailing_comments: Vec::new(),
3417 double_colon_syntax: false,
3418 format: None,
3419 default: None,
3420 inferred_type: None,
3421 }));
3422 let shift = Expression::BitwiseRightShift(Box::new(BinaryOp {
3423 left: cast_to_bit,
3424 right: b,
3425 left_comments: Vec::new(),
3426 operator_comments: Vec::new(),
3427 trailing_comments: Vec::new(),
3428 inferred_type: None,
3429 }));
3430 Ok(Expression::Cast(Box::new(Cast {
3431 this: shift,
3432 to: DataType::Custom {
3433 name: "BLOB".to_string(),
3434 },
3435 trailing_comments: Vec::new(),
3436 double_colon_syntax: false,
3437 format: None,
3438 default: None,
3439 inferred_type: None,
3440 })))
3441 } else {
3442 Ok(Expression::BitwiseRightShift(Box::new(BinaryOp {
3443 left: Expression::Cast(Box::new(Cast {
3444 this: a,
3445 to: DataType::Custom {
3446 name: "INT128".to_string(),
3447 },
3448 trailing_comments: Vec::new(),
3449 double_colon_syntax: false,
3450 format: None,
3451 default: None,
3452 inferred_type: None,
3453 })),
3454 right: b,
3455 left_comments: Vec::new(),
3456 operator_comments: Vec::new(),
3457 trailing_comments: Vec::new(),
3458 inferred_type: None,
3459 })))
3460 }
3461 }
3462 "SQUARE" if f.args.len() == 1 => {
3463 let arg = f.args.into_iter().next().unwrap();
3464 Ok(Expression::Function(Box::new(Function::new(
3465 "POWER".to_string(),
3466 vec![arg, Expression::number(2)],
3467 ))))
3468 }
3469 "LIST"
3470 if f.args.len() == 1 && !matches!(f.args.first(), Some(Expression::Select(_))) =>
3471 {
3472 Ok(Expression::Function(Box::new(Function::new(
3473 "ARRAY_AGG".to_string(),
3474 f.args,
3475 ))))
3476 }
3477 "UUID_STRING" => {
3478 if f.args.is_empty() {
3479 Ok(Expression::Function(Box::new(Function::new(
3480 "UUID".to_string(),
3481 vec![],
3482 ))))
3483 } else {
3484 Ok(Expression::Function(Box::new(Function::new(
3485 "UUID_STRING".to_string(),
3486 f.args,
3487 ))))
3488 }
3489 }
3490 "ENDSWITH" => Ok(Expression::Function(Box::new(Function::new(
3491 "ENDS_WITH".to_string(),
3492 f.args,
3493 )))),
3494 "REGEXP_REPLACE" if f.args.len() == 2 => {
3498 let mut args = f.args;
3500 args.push(Expression::Literal(Box::new(
3501 Literal::String(String::new()),
3502 )));
3503 Ok(Expression::Function(Box::new(Function::new(
3504 "REGEXP_REPLACE".to_string(),
3505 args,
3506 ))))
3507 }
3508 "DIV0" if f.args.len() == 2 => {
3509 let mut args = f.args;
3510 let a = args.remove(0);
3511 let b = args.remove(0);
3512 Ok(Expression::Case(Box::new(Case {
3513 operand: None,
3514 whens: vec![(
3515 Expression::And(Box::new(BinaryOp {
3516 left: Expression::Eq(Box::new(BinaryOp {
3517 left: b.clone(),
3518 right: Expression::number(0),
3519 left_comments: Vec::new(),
3520 operator_comments: Vec::new(),
3521 trailing_comments: Vec::new(),
3522 inferred_type: None,
3523 })),
3524 right: Expression::Not(Box::new(crate::expressions::UnaryOp {
3525 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3526 this: a.clone(),
3527 not: false,
3528 postfix_form: false,
3529 })),
3530 inferred_type: None,
3531 })),
3532 left_comments: Vec::new(),
3533 operator_comments: Vec::new(),
3534 trailing_comments: Vec::new(),
3535 inferred_type: None,
3536 })),
3537 Expression::number(0),
3538 )],
3539 else_: Some(Expression::Div(Box::new(BinaryOp {
3540 left: a,
3541 right: b,
3542 left_comments: Vec::new(),
3543 operator_comments: Vec::new(),
3544 trailing_comments: Vec::new(),
3545 inferred_type: None,
3546 }))),
3547 comments: Vec::new(),
3548 inferred_type: None,
3549 })))
3550 }
3551 "DIV0NULL" if f.args.len() == 2 => {
3552 let mut args = f.args;
3553 let a = args.remove(0);
3554 let b = args.remove(0);
3555 Ok(Expression::Case(Box::new(Case {
3556 operand: None,
3557 whens: vec![(
3558 Expression::Or(Box::new(BinaryOp {
3559 left: Expression::Eq(Box::new(BinaryOp {
3560 left: b.clone(),
3561 right: Expression::number(0),
3562 left_comments: Vec::new(),
3563 operator_comments: Vec::new(),
3564 trailing_comments: Vec::new(),
3565 inferred_type: None,
3566 })),
3567 right: Expression::IsNull(Box::new(crate::expressions::IsNull {
3568 this: b.clone(),
3569 not: false,
3570 postfix_form: false,
3571 })),
3572 left_comments: Vec::new(),
3573 operator_comments: Vec::new(),
3574 trailing_comments: Vec::new(),
3575 inferred_type: None,
3576 })),
3577 Expression::number(0),
3578 )],
3579 else_: Some(Expression::Div(Box::new(BinaryOp {
3580 left: a,
3581 right: b,
3582 left_comments: Vec::new(),
3583 operator_comments: Vec::new(),
3584 trailing_comments: Vec::new(),
3585 inferred_type: None,
3586 }))),
3587 comments: Vec::new(),
3588 inferred_type: None,
3589 })))
3590 }
3591 "ZEROIFNULL" if f.args.len() == 1 => {
3592 let x = f.args.into_iter().next().unwrap();
3593 Ok(Expression::Case(Box::new(Case {
3594 operand: None,
3595 whens: vec![(
3596 Expression::IsNull(Box::new(crate::expressions::IsNull {
3597 this: x.clone(),
3598 not: false,
3599 postfix_form: false,
3600 })),
3601 Expression::number(0),
3602 )],
3603 else_: Some(x),
3604 comments: Vec::new(),
3605 inferred_type: None,
3606 })))
3607 }
3608 "NULLIFZERO" if f.args.len() == 1 => {
3609 let x = f.args.into_iter().next().unwrap();
3610 Ok(Expression::Case(Box::new(Case {
3611 operand: None,
3612 whens: vec![(
3613 Expression::Eq(Box::new(BinaryOp {
3614 left: x.clone(),
3615 right: Expression::number(0),
3616 left_comments: Vec::new(),
3617 operator_comments: Vec::new(),
3618 trailing_comments: Vec::new(),
3619 inferred_type: None,
3620 })),
3621 Expression::Null(crate::expressions::Null),
3622 )],
3623 else_: Some(x),
3624 comments: Vec::new(),
3625 inferred_type: None,
3626 })))
3627 }
3628 "TO_DOUBLE" if f.args.len() == 1 => {
3629 let arg = f.args.into_iter().next().unwrap();
3630 Ok(Expression::Cast(Box::new(Cast {
3631 this: arg,
3632 to: DataType::Double {
3633 precision: None,
3634 scale: None,
3635 },
3636 trailing_comments: Vec::new(),
3637 double_colon_syntax: false,
3638 format: None,
3639 default: None,
3640 inferred_type: None,
3641 })))
3642 }
3643 "DATE" if f.args.len() == 1 => {
3644 let arg = f.args.into_iter().next().unwrap();
3645 Ok(Expression::Cast(Box::new(Cast {
3646 this: arg,
3647 to: DataType::Date,
3648 trailing_comments: Vec::new(),
3649 double_colon_syntax: false,
3650 format: None,
3651 default: None,
3652 inferred_type: None,
3653 })))
3654 }
3655 "DATE" if f.args.len() == 2 => {
3656 let mut args = f.args;
3657 let value = args.remove(0);
3658 let fmt = self.convert_snowflake_date_format(args.remove(0));
3659 Ok(Expression::Cast(Box::new(Cast {
3660 this: Expression::Function(Box::new(Function::new(
3661 "STRPTIME".to_string(),
3662 vec![value, fmt],
3663 ))),
3664 to: DataType::Date,
3665 trailing_comments: Vec::new(),
3666 double_colon_syntax: false,
3667 format: None,
3668 default: None,
3669 inferred_type: None,
3670 })))
3671 }
3672 "SYSDATE" => Ok(Expression::AtTimeZone(Box::new(
3673 crate::expressions::AtTimeZone {
3674 this: Expression::CurrentTimestamp(crate::expressions::CurrentTimestamp {
3675 precision: None,
3676 sysdate: false,
3677 }),
3678 zone: Expression::Literal(Box::new(Literal::String("UTC".to_string()))),
3679 },
3680 ))),
3681 "HEX_DECODE_BINARY" => Ok(Expression::Function(Box::new(Function::new(
3682 "UNHEX".to_string(),
3683 f.args,
3684 )))),
3685 "CONVERT_TIMEZONE" if f.args.len() == 3 => {
3686 let mut args = f.args;
3687 let src_tz = args.remove(0);
3688 let tgt_tz = args.remove(0);
3689 let ts = args.remove(0);
3690 let cast_ts = Expression::Cast(Box::new(Cast {
3691 this: ts,
3692 to: DataType::Timestamp {
3693 precision: None,
3694 timezone: false,
3695 },
3696 trailing_comments: Vec::new(),
3697 double_colon_syntax: false,
3698 format: None,
3699 default: None,
3700 inferred_type: None,
3701 }));
3702 Ok(Expression::AtTimeZone(Box::new(
3703 crate::expressions::AtTimeZone {
3704 this: Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone {
3705 this: cast_ts,
3706 zone: src_tz,
3707 })),
3708 zone: tgt_tz,
3709 },
3710 )))
3711 }
3712 "CONVERT_TIMEZONE" if f.args.len() == 2 => {
3713 let mut args = f.args;
3714 let tgt_tz = args.remove(0);
3715 let ts = args.remove(0);
3716 let cast_ts = Expression::Cast(Box::new(Cast {
3717 this: ts,
3718 to: DataType::Timestamp {
3719 precision: None,
3720 timezone: false,
3721 },
3722 trailing_comments: Vec::new(),
3723 double_colon_syntax: false,
3724 format: None,
3725 default: None,
3726 inferred_type: None,
3727 }));
3728 Ok(Expression::AtTimeZone(Box::new(
3729 crate::expressions::AtTimeZone {
3730 this: cast_ts,
3731 zone: tgt_tz,
3732 },
3733 )))
3734 }
3735 "DATE_PART" | "DATEPART" if f.args.len() == 2 => self.transform_date_part(f.args),
3736 "DATEADD" | "TIMEADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3737 "TIMESTAMPADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3738 "DATEDIFF" | "TIMEDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3739 "TIMESTAMPDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3740 "CORR" if f.args.len() == 2 => {
3741 Ok(Expression::Function(Box::new(f)))
3743 }
3744 "TO_TIMESTAMP" | "TO_TIMESTAMP_NTZ" if f.args.len() == 2 => {
3745 let mut args = f.args;
3746 let value = args.remove(0);
3747 let second_arg = args.remove(0);
3748 match &second_arg {
3749 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => Ok(
3750 Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone {
3751 this: Expression::Function(Box::new(Function::new(
3752 "TO_TIMESTAMP".to_string(),
3753 vec![Expression::Div(Box::new(BinaryOp {
3754 left: value,
3755 right: Expression::Function(Box::new(Function::new(
3756 "POWER".to_string(),
3757 vec![Expression::number(10), second_arg],
3758 ))),
3759 left_comments: Vec::new(),
3760 operator_comments: Vec::new(),
3761 trailing_comments: Vec::new(),
3762 inferred_type: None,
3763 }))],
3764 ))),
3765 zone: Expression::Literal(Box::new(Literal::String("UTC".to_string()))),
3766 })),
3767 ),
3768 _ => {
3769 let fmt = self.convert_snowflake_time_format(second_arg);
3770 Ok(Expression::Function(Box::new(Function::new(
3771 "STRPTIME".to_string(),
3772 vec![value, fmt],
3773 ))))
3774 }
3775 }
3776 }
3777 "TO_TIME" if f.args.len() == 1 => {
3778 let arg = f.args.into_iter().next().unwrap();
3779 Ok(Expression::Cast(Box::new(Cast {
3780 this: arg,
3781 to: DataType::Time {
3782 precision: None,
3783 timezone: false,
3784 },
3785 trailing_comments: Vec::new(),
3786 double_colon_syntax: false,
3787 format: None,
3788 default: None,
3789 inferred_type: None,
3790 })))
3791 }
3792 "TO_TIME" if f.args.len() == 2 => {
3793 let mut args = f.args;
3794 let value = args.remove(0);
3795 let fmt = self.convert_snowflake_time_format(args.remove(0));
3796 Ok(Expression::Cast(Box::new(Cast {
3797 this: Expression::Function(Box::new(Function::new(
3798 "STRPTIME".to_string(),
3799 vec![value, fmt],
3800 ))),
3801 to: DataType::Time {
3802 precision: None,
3803 timezone: false,
3804 },
3805 trailing_comments: Vec::new(),
3806 double_colon_syntax: false,
3807 format: None,
3808 default: None,
3809 inferred_type: None,
3810 })))
3811 }
3812 "TO_DATE" if f.args.len() == 2 => {
3813 let mut args = f.args;
3814 let value = args.remove(0);
3815 let fmt = self.convert_snowflake_date_format(args.remove(0));
3816 Ok(Expression::Cast(Box::new(Cast {
3817 this: Expression::Function(Box::new(Function::new(
3818 "STRPTIME".to_string(),
3819 vec![value, fmt],
3820 ))),
3821 to: DataType::Date,
3822 trailing_comments: Vec::new(),
3823 double_colon_syntax: false,
3824 format: None,
3825 default: None,
3826 inferred_type: None,
3827 })))
3828 }
3829 "SAFE_DIVIDE" if f.args.len() == 2 => {
3833 let mut args = f.args;
3834 let x = args.remove(0);
3835 let y = args.remove(0);
3836 Ok(Expression::Case(Box::new(Case {
3837 operand: None,
3838 whens: vec![(
3839 Expression::Neq(Box::new(BinaryOp {
3840 left: y.clone(),
3841 right: Expression::number(0),
3842 left_comments: Vec::new(),
3843 operator_comments: Vec::new(),
3844 trailing_comments: Vec::new(),
3845 inferred_type: None,
3846 })),
3847 Expression::Div(Box::new(BinaryOp {
3848 left: x,
3849 right: y,
3850 left_comments: Vec::new(),
3851 operator_comments: Vec::new(),
3852 trailing_comments: Vec::new(),
3853 inferred_type: None,
3854 })),
3855 )],
3856 else_: Some(Expression::Null(crate::expressions::Null)),
3857 comments: Vec::new(),
3858 inferred_type: None,
3859 })))
3860 }
3861
3862 "TO_HEX" if f.args.len() == 1 => {
3864 let arg = f.args.into_iter().next().unwrap();
3865 Ok(Expression::Lower(Box::new(UnaryFunc::new(
3866 Expression::Function(Box::new(Function::new("HEX".to_string(), vec![arg]))),
3867 ))))
3868 }
3869
3870 "EDIT_DISTANCE" if f.args.len() >= 2 => {
3872 let mut args = f.args;
3874 let a = args.remove(0);
3875 let b = args.remove(0);
3876 Ok(Expression::Function(Box::new(Function::new(
3877 "LEVENSHTEIN".to_string(),
3878 vec![a, b],
3879 ))))
3880 }
3881
3882 "UNIX_DATE" if f.args.len() == 1 => {
3884 let arg = f.args.into_iter().next().unwrap();
3885 Ok(Expression::Function(Box::new(Function::new(
3886 "DATE_DIFF".to_string(),
3887 vec![
3888 Expression::Literal(Box::new(Literal::String("DAY".to_string()))),
3889 Expression::Cast(Box::new(Cast {
3890 this: Expression::Literal(Box::new(Literal::String(
3891 "1970-01-01".to_string(),
3892 ))),
3893 to: DataType::Date,
3894 trailing_comments: Vec::new(),
3895 double_colon_syntax: false,
3896 format: None,
3897 default: None,
3898 inferred_type: None,
3899 })),
3900 arg,
3901 ],
3902 ))))
3903 }
3904
3905 "TIMESTAMP" if f.args.len() == 1 => {
3907 let arg = f.args.into_iter().next().unwrap();
3908 Ok(Expression::Cast(Box::new(Cast {
3909 this: arg,
3910 to: DataType::Custom {
3911 name: "TIMESTAMPTZ".to_string(),
3912 },
3913 trailing_comments: Vec::new(),
3914 double_colon_syntax: false,
3915 format: None,
3916 default: None,
3917 inferred_type: None,
3918 })))
3919 }
3920
3921 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3923 "MAKE_TIME".to_string(),
3924 f.args,
3925 )))),
3926
3927 "DATE" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3929 "MAKE_DATE".to_string(),
3930 f.args,
3931 )))),
3932
3933 "DATETIME" if f.args.len() == 6 => Ok(Expression::Function(Box::new(Function::new(
3935 "MAKE_TIMESTAMP".to_string(),
3936 f.args,
3937 )))),
3938
3939 "PARSE_TIMESTAMP" if f.args.len() >= 2 => {
3941 let mut args = f.args;
3942 let fmt = args.remove(0);
3943 let value = args.remove(0);
3944 let duckdb_fmt = self.convert_bq_to_strptime_format(fmt);
3946 Ok(Expression::Function(Box::new(Function::new(
3947 "STRPTIME".to_string(),
3948 vec![value, duckdb_fmt],
3949 ))))
3950 }
3951
3952 "BOOLAND" if f.args.len() == 2 => {
3954 let mut args = f.args;
3955 let a = args.remove(0);
3956 let b = args.remove(0);
3957 let ra = Expression::Function(Box::new(Function::new(
3958 "ROUND".to_string(),
3959 vec![a, Expression::number(0)],
3960 )));
3961 let rb = Expression::Function(Box::new(Function::new(
3962 "ROUND".to_string(),
3963 vec![b, Expression::number(0)],
3964 )));
3965 Ok(Expression::Paren(Box::new(Paren {
3966 this: Expression::And(Box::new(BinaryOp {
3967 left: Expression::Paren(Box::new(Paren {
3968 this: ra,
3969 trailing_comments: Vec::new(),
3970 })),
3971 right: Expression::Paren(Box::new(Paren {
3972 this: rb,
3973 trailing_comments: Vec::new(),
3974 })),
3975 left_comments: Vec::new(),
3976 operator_comments: Vec::new(),
3977 trailing_comments: Vec::new(),
3978 inferred_type: None,
3979 })),
3980 trailing_comments: Vec::new(),
3981 })))
3982 }
3983
3984 "BOOLOR" if f.args.len() == 2 => {
3986 let mut args = f.args;
3987 let a = args.remove(0);
3988 let b = args.remove(0);
3989 let ra = Expression::Function(Box::new(Function::new(
3990 "ROUND".to_string(),
3991 vec![a, Expression::number(0)],
3992 )));
3993 let rb = Expression::Function(Box::new(Function::new(
3994 "ROUND".to_string(),
3995 vec![b, Expression::number(0)],
3996 )));
3997 Ok(Expression::Paren(Box::new(Paren {
3998 this: Expression::Or(Box::new(BinaryOp {
3999 left: Expression::Paren(Box::new(Paren {
4000 this: ra,
4001 trailing_comments: Vec::new(),
4002 })),
4003 right: Expression::Paren(Box::new(Paren {
4004 this: rb,
4005 trailing_comments: Vec::new(),
4006 })),
4007 left_comments: Vec::new(),
4008 operator_comments: Vec::new(),
4009 trailing_comments: Vec::new(),
4010 inferred_type: None,
4011 })),
4012 trailing_comments: Vec::new(),
4013 })))
4014 }
4015
4016 "BOOLXOR" if f.args.len() == 2 => {
4018 let mut args = f.args;
4019 let a = args.remove(0);
4020 let b = args.remove(0);
4021 let ra = Expression::Function(Box::new(Function::new(
4022 "ROUND".to_string(),
4023 vec![a, Expression::number(0)],
4024 )));
4025 let rb = Expression::Function(Box::new(Function::new(
4026 "ROUND".to_string(),
4027 vec![b, Expression::number(0)],
4028 )));
4029 let not_rb = Expression::Not(Box::new(crate::expressions::UnaryOp {
4031 this: rb.clone(),
4032 inferred_type: None,
4033 }));
4034 let not_ra = Expression::Not(Box::new(crate::expressions::UnaryOp {
4035 this: ra.clone(),
4036 inferred_type: None,
4037 }));
4038 let left_and = Expression::And(Box::new(BinaryOp {
4039 left: ra,
4040 right: Expression::Paren(Box::new(Paren {
4041 this: not_rb,
4042 trailing_comments: Vec::new(),
4043 })),
4044 left_comments: Vec::new(),
4045 operator_comments: Vec::new(),
4046 trailing_comments: Vec::new(),
4047 inferred_type: None,
4048 }));
4049 let right_and = Expression::And(Box::new(BinaryOp {
4050 left: Expression::Paren(Box::new(Paren {
4051 this: not_ra,
4052 trailing_comments: Vec::new(),
4053 })),
4054 right: rb,
4055 left_comments: Vec::new(),
4056 operator_comments: Vec::new(),
4057 trailing_comments: Vec::new(),
4058 inferred_type: None,
4059 }));
4060 Ok(Expression::Or(Box::new(BinaryOp {
4061 left: Expression::Paren(Box::new(Paren {
4062 this: left_and,
4063 trailing_comments: Vec::new(),
4064 })),
4065 right: Expression::Paren(Box::new(Paren {
4066 this: right_and,
4067 trailing_comments: Vec::new(),
4068 })),
4069 left_comments: Vec::new(),
4070 operator_comments: Vec::new(),
4071 trailing_comments: Vec::new(),
4072 inferred_type: None,
4073 })))
4074 }
4075
4076 "DECODE" if f.args.len() >= 3 => {
4079 let mut args = f.args;
4080 let expr = args.remove(0);
4081 let mut whens = Vec::new();
4082 let mut else_expr = None;
4083 while args.len() >= 2 {
4084 let search = args.remove(0);
4085 let result = args.remove(0);
4086 let condition = if matches!(&search, Expression::Null(_)) {
4088 Expression::IsNull(Box::new(crate::expressions::IsNull {
4089 this: expr.clone(),
4090 not: false,
4091 postfix_form: false,
4092 }))
4093 } else {
4094 Expression::Eq(Box::new(BinaryOp {
4095 left: expr.clone(),
4096 right: search,
4097 left_comments: Vec::new(),
4098 operator_comments: Vec::new(),
4099 trailing_comments: Vec::new(),
4100 inferred_type: None,
4101 }))
4102 };
4103 whens.push((condition, result));
4104 }
4105 if !args.is_empty() {
4106 else_expr = Some(args.remove(0));
4107 }
4108 Ok(Expression::Case(Box::new(Case {
4109 operand: None,
4110 whens,
4111 else_: else_expr,
4112 comments: Vec::new(),
4113 inferred_type: None,
4114 })))
4115 }
4116
4117 "TRY_TO_BOOLEAN" if f.args.len() == 1 => {
4119 let arg = f.args.into_iter().next().unwrap();
4120 let cast_text = Expression::Cast(Box::new(Cast {
4121 this: arg.clone(),
4122 to: DataType::Text,
4123 trailing_comments: Vec::new(),
4124 double_colon_syntax: false,
4125 format: None,
4126 default: None,
4127 inferred_type: None,
4128 }));
4129 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
4130 Ok(Expression::Case(Box::new(Case {
4131 operand: None,
4132 whens: vec![
4133 (
4134 Expression::Eq(Box::new(BinaryOp {
4135 left: upper_text.clone(),
4136 right: Expression::Literal(Box::new(Literal::String(
4137 "ON".to_string(),
4138 ))),
4139 left_comments: Vec::new(),
4140 operator_comments: Vec::new(),
4141 trailing_comments: Vec::new(),
4142 inferred_type: None,
4143 })),
4144 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
4145 ),
4146 (
4147 Expression::Eq(Box::new(BinaryOp {
4148 left: upper_text,
4149 right: Expression::Literal(Box::new(Literal::String(
4150 "OFF".to_string(),
4151 ))),
4152 left_comments: Vec::new(),
4153 operator_comments: Vec::new(),
4154 trailing_comments: Vec::new(),
4155 inferred_type: None,
4156 })),
4157 Expression::Boolean(crate::expressions::BooleanLiteral {
4158 value: false,
4159 }),
4160 ),
4161 ],
4162 else_: Some(Expression::TryCast(Box::new(Cast {
4163 this: arg,
4164 to: DataType::Boolean,
4165 trailing_comments: Vec::new(),
4166 double_colon_syntax: false,
4167 format: None,
4168 default: None,
4169 inferred_type: None,
4170 }))),
4171 comments: Vec::new(),
4172 inferred_type: None,
4173 })))
4174 }
4175
4176 "TO_BOOLEAN" if f.args.len() == 1 => {
4178 let arg = f.args.into_iter().next().unwrap();
4179 let cast_text = Expression::Cast(Box::new(Cast {
4180 this: arg.clone(),
4181 to: DataType::Text,
4182 trailing_comments: Vec::new(),
4183 double_colon_syntax: false,
4184 format: None,
4185 default: None,
4186 inferred_type: None,
4187 }));
4188 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
4189 Ok(Expression::Case(Box::new(Case {
4190 operand: None,
4191 whens: vec![
4192 (
4193 Expression::Eq(Box::new(BinaryOp {
4194 left: upper_text.clone(),
4195 right: Expression::Literal(Box::new(Literal::String(
4196 "ON".to_string(),
4197 ))),
4198 left_comments: Vec::new(),
4199 operator_comments: Vec::new(),
4200 trailing_comments: Vec::new(),
4201 inferred_type: None,
4202 })),
4203 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
4204 ),
4205 (
4206 Expression::Eq(Box::new(BinaryOp {
4207 left: upper_text,
4208 right: Expression::Literal(Box::new(Literal::String(
4209 "OFF".to_string(),
4210 ))),
4211 left_comments: Vec::new(),
4212 operator_comments: Vec::new(),
4213 trailing_comments: Vec::new(),
4214 inferred_type: None,
4215 })),
4216 Expression::Boolean(crate::expressions::BooleanLiteral {
4217 value: false,
4218 }),
4219 ),
4220 (
4221 Expression::Or(Box::new(BinaryOp {
4222 left: Expression::Function(Box::new(Function::new(
4223 "ISNAN".to_string(),
4224 vec![Expression::TryCast(Box::new(Cast {
4225 this: arg.clone(),
4226 to: DataType::Custom {
4227 name: "REAL".to_string(),
4228 },
4229 trailing_comments: Vec::new(),
4230 double_colon_syntax: false,
4231 format: None,
4232 default: None,
4233 inferred_type: None,
4234 }))],
4235 ))),
4236 right: Expression::Function(Box::new(Function::new(
4237 "ISINF".to_string(),
4238 vec![Expression::TryCast(Box::new(Cast {
4239 this: arg.clone(),
4240 to: DataType::Custom {
4241 name: "REAL".to_string(),
4242 },
4243 trailing_comments: Vec::new(),
4244 double_colon_syntax: false,
4245 format: None,
4246 default: None,
4247 inferred_type: None,
4248 }))],
4249 ))),
4250 left_comments: Vec::new(),
4251 operator_comments: Vec::new(),
4252 trailing_comments: Vec::new(),
4253 inferred_type: None,
4254 })),
4255 Expression::Function(Box::new(Function::new(
4256 "ERROR".to_string(),
4257 vec![Expression::Literal(Box::new(Literal::String(
4258 "TO_BOOLEAN: Non-numeric values NaN and INF are not supported"
4259 .to_string(),
4260 )))],
4261 ))),
4262 ),
4263 ],
4264 else_: Some(Expression::Cast(Box::new(Cast {
4265 this: arg,
4266 to: DataType::Boolean,
4267 trailing_comments: Vec::new(),
4268 double_colon_syntax: false,
4269 format: None,
4270 default: None,
4271 inferred_type: None,
4272 }))),
4273 comments: Vec::new(),
4274 inferred_type: None,
4275 })))
4276 }
4277
4278 "OBJECT_INSERT" if f.args.len() == 3 => {
4281 let mut args = f.args;
4282 let obj = args.remove(0);
4283 let key = args.remove(0);
4284 let value = args.remove(0);
4285 let key_name = match &key {
4287 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4288 let Literal::String(s) = lit.as_ref() else {
4289 unreachable!()
4290 };
4291 s.clone()
4292 }
4293 _ => "key".to_string(),
4294 };
4295 let named_arg =
4296 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
4297 name: Identifier::new(&key_name),
4298 value,
4299 separator: crate::expressions::NamedArgSeparator::ColonEq,
4300 }));
4301 let is_empty_struct = match &obj {
4303 Expression::Struct(s) if s.fields.is_empty() => true,
4304 Expression::Function(f) => {
4305 let n = f.name.to_uppercase();
4306 (n == "STRUCT_PACK" || n == "OBJECT_CONSTRUCT") && f.args.is_empty()
4307 }
4308 _ => false,
4309 };
4310 if is_empty_struct {
4311 Ok(Expression::Function(Box::new(Function::new(
4313 "STRUCT_PACK".to_string(),
4314 vec![named_arg],
4315 ))))
4316 } else {
4317 Ok(Expression::Function(Box::new(Function::new(
4318 "STRUCT_INSERT".to_string(),
4319 vec![obj, named_arg],
4320 ))))
4321 }
4322 }
4323
4324 "GET" if f.args.len() == 2 => {
4326 let mut args = f.args;
4327 let this = args.remove(0);
4328 let key = args.remove(0);
4329 match &key {
4330 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4332 let Literal::String(s) = lit.as_ref() else {
4333 unreachable!()
4334 };
4335 let json_path = format!("$.{}", s);
4336 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4337 this,
4338 path: Expression::Literal(Box::new(Literal::String(json_path))),
4339 returning: None,
4340 arrow_syntax: true,
4341 hash_arrow_syntax: false,
4342 wrapper_option: None,
4343 quotes_option: None,
4344 on_scalar_string: false,
4345 on_error: None,
4346 })))
4347 }
4348 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4352 let Literal::Number(n) = lit.as_ref() else {
4353 unreachable!()
4354 };
4355 let idx: i64 = n.parse().unwrap_or(0);
4356 let is_map = matches!(&this, Expression::Cast(c) if matches!(c.to, DataType::Map { .. }));
4357 let index_val = if is_map { idx } else { idx + 1 };
4358 Ok(Expression::Subscript(Box::new(
4359 crate::expressions::Subscript {
4360 this,
4361 index: Expression::number(index_val),
4362 },
4363 )))
4364 }
4365 _ => {
4366 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4368 this,
4369 path: Expression::JSONPath(Box::new(JSONPath {
4370 expressions: vec![
4371 Expression::JSONPathRoot(JSONPathRoot),
4372 Expression::JSONPathKey(Box::new(JSONPathKey {
4373 this: Box::new(key),
4374 })),
4375 ],
4376 escape: None,
4377 })),
4378 returning: None,
4379 arrow_syntax: true,
4380 hash_arrow_syntax: false,
4381 wrapper_option: None,
4382 quotes_option: None,
4383 on_scalar_string: false,
4384 on_error: None,
4385 })))
4386 }
4387 }
4388 }
4389
4390 "GET_PATH" if f.args.len() == 2 => {
4392 let mut args = f.args;
4393 let this = args.remove(0);
4394 let path = args.remove(0);
4395 let json_path = match &path {
4397 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4398 let Literal::String(s) = lit.as_ref() else {
4399 unreachable!()
4400 };
4401 let s = Self::convert_bracket_to_quoted_path(s);
4403 let normalized = if s.starts_with('$') {
4405 s
4406 } else if s.starts_with('[') {
4407 format!("${}", s)
4408 } else {
4409 format!("$.{}", s)
4410 };
4411 Expression::Literal(Box::new(Literal::String(normalized)))
4412 }
4413 _ => path,
4414 };
4415 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4416 this,
4417 path: json_path,
4418 returning: None,
4419 arrow_syntax: true,
4420 hash_arrow_syntax: false,
4421 wrapper_option: None,
4422 quotes_option: None,
4423 on_scalar_string: false,
4424 on_error: None,
4425 })))
4426 }
4427
4428 "BASE64_ENCODE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
4430 Function::new("TO_BASE64".to_string(), f.args),
4431 ))),
4432
4433 "BASE64_ENCODE" if f.args.len() >= 2 => {
4435 let mut args = f.args;
4436 let x = args.remove(0);
4437 let line_len = args.remove(0);
4438 let line_len_str = match &line_len {
4439 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4440 let Literal::Number(n) = lit.as_ref() else {
4441 unreachable!()
4442 };
4443 n.clone()
4444 }
4445 _ => "76".to_string(),
4446 };
4447 let to_base64 =
4448 Expression::Function(Box::new(Function::new("TO_BASE64".to_string(), vec![x])));
4449 let pattern = format!("(.{{{}}})", line_len_str);
4450 let chr_10 = Expression::Function(Box::new(Function::new(
4451 "CHR".to_string(),
4452 vec![Expression::number(10)],
4453 )));
4454 let replacement = Expression::Concat(Box::new(BinaryOp {
4455 left: Expression::Literal(Box::new(Literal::String("\\1".to_string()))),
4456 right: chr_10.clone(),
4457 left_comments: Vec::new(),
4458 operator_comments: Vec::new(),
4459 trailing_comments: Vec::new(),
4460 inferred_type: None,
4461 }));
4462 let regexp_replace = Expression::Function(Box::new(Function::new(
4463 "REGEXP_REPLACE".to_string(),
4464 vec![
4465 to_base64,
4466 Expression::Literal(Box::new(Literal::String(pattern))),
4467 replacement,
4468 Expression::Literal(Box::new(Literal::String("g".to_string()))),
4469 ],
4470 )));
4471 Ok(Expression::Function(Box::new(Function::new(
4472 "RTRIM".to_string(),
4473 vec![regexp_replace, chr_10],
4474 ))))
4475 }
4476
4477 "TRY_TO_DATE" if f.args.len() == 2 => {
4479 let mut args = f.args;
4480 let value = args.remove(0);
4481 let fmt = self.convert_snowflake_date_format(args.remove(0));
4482 Ok(Expression::Cast(Box::new(Cast {
4483 this: Expression::Cast(Box::new(Cast {
4484 this: Expression::Function(Box::new(Function::new(
4485 "TRY_STRPTIME".to_string(),
4486 vec![value, fmt],
4487 ))),
4488 to: DataType::Timestamp {
4489 precision: None,
4490 timezone: false,
4491 },
4492 trailing_comments: Vec::new(),
4493 double_colon_syntax: false,
4494 format: None,
4495 default: None,
4496 inferred_type: None,
4497 })),
4498 to: DataType::Date,
4499 trailing_comments: Vec::new(),
4500 double_colon_syntax: false,
4501 format: None,
4502 default: None,
4503 inferred_type: None,
4504 })))
4505 }
4506
4507 "REGEXP_REPLACE" if f.args.len() == 4 => {
4510 let is_snowflake_position = matches!(&f.args[3], Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)));
4511 if is_snowflake_position {
4512 let mut args = f.args;
4514 let subject = args.remove(0);
4515 let pattern = args.remove(0);
4516 let replacement = args.remove(0);
4517 Ok(Expression::Function(Box::new(Function::new(
4518 "REGEXP_REPLACE".to_string(),
4519 vec![
4520 subject,
4521 pattern,
4522 replacement,
4523 Expression::Literal(Box::new(Literal::String("g".to_string()))),
4524 ],
4525 ))))
4526 } else {
4527 Ok(Expression::Function(Box::new(f)))
4529 }
4530 }
4531
4532 "REGEXP_REPLACE" if f.args.len() >= 5 => {
4534 let mut args = f.args;
4535 let subject = args.remove(0);
4536 let pattern = args.remove(0);
4537 let replacement = args.remove(0);
4538 let _position = args.remove(0);
4539 let occurrence = if !args.is_empty() {
4540 Some(args.remove(0))
4541 } else {
4542 None
4543 };
4544 let params = if !args.is_empty() {
4545 Some(args.remove(0))
4546 } else {
4547 None
4548 };
4549
4550 let mut flags = String::new();
4551 if let Some(Expression::Literal(lit)) = ¶ms {
4552 if let Literal::String(p) = lit.as_ref() {
4553 flags = p.clone();
4554 }
4555 }
4556 let is_global = match &occurrence {
4557 Some(Expression::Literal(lit))
4558 if matches!(lit.as_ref(), Literal::Number(_)) =>
4559 {
4560 let Literal::Number(n) = lit.as_ref() else {
4561 unreachable!()
4562 };
4563 n == "0"
4564 }
4565 None => true,
4566 _ => false,
4567 };
4568 if is_global && !flags.contains('g') {
4569 flags.push('g');
4570 }
4571
4572 Ok(Expression::Function(Box::new(Function::new(
4573 "REGEXP_REPLACE".to_string(),
4574 vec![
4575 subject,
4576 pattern,
4577 replacement,
4578 Expression::Literal(Box::new(Literal::String(flags))),
4579 ],
4580 ))))
4581 }
4582
4583 "ROUND"
4585 if f.args
4586 .iter()
4587 .any(|a| matches!(a, Expression::NamedArgument(_))) =>
4588 {
4589 let mut expr_val = None;
4590 let mut scale_val = None;
4591 let mut rounding_mode = None;
4592 for arg in &f.args {
4593 if let Expression::NamedArgument(na) = arg {
4594 match na.name.name.to_uppercase().as_str() {
4595 "EXPR" => expr_val = Some(na.value.clone()),
4596 "SCALE" => scale_val = Some(na.value.clone()),
4597 "ROUNDING_MODE" => rounding_mode = Some(na.value.clone()),
4598 _ => {}
4599 }
4600 }
4601 }
4602 if let Some(expr) = expr_val {
4603 let scale = scale_val.unwrap_or(Expression::number(0));
4604 let is_half_to_even = match &rounding_mode {
4605 Some(Expression::Literal(lit))
4606 if matches!(lit.as_ref(), Literal::String(_)) =>
4607 {
4608 let Literal::String(s) = lit.as_ref() else {
4609 unreachable!()
4610 };
4611 s == "HALF_TO_EVEN"
4612 }
4613 _ => false,
4614 };
4615 if is_half_to_even {
4616 Ok(Expression::Function(Box::new(Function::new(
4617 "ROUND_EVEN".to_string(),
4618 vec![expr, scale],
4619 ))))
4620 } else {
4621 Ok(Expression::Function(Box::new(Function::new(
4622 "ROUND".to_string(),
4623 vec![expr, scale],
4624 ))))
4625 }
4626 } else {
4627 Ok(Expression::Function(Box::new(f)))
4628 }
4629 }
4630
4631 "ROUND" if f.args.len() == 3 => {
4634 let mut args = f.args;
4635 let x = args.remove(0);
4636 let scale = args.remove(0);
4637 let mode = args.remove(0);
4638 let is_half_to_even = match &mode {
4639 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4640 let Literal::String(s) = lit.as_ref() else {
4641 unreachable!()
4642 };
4643 s == "HALF_TO_EVEN"
4644 }
4645 _ => false,
4646 };
4647 if is_half_to_even {
4648 Ok(Expression::Function(Box::new(Function::new(
4649 "ROUND_EVEN".to_string(),
4650 vec![x, scale],
4651 ))))
4652 } else {
4653 Ok(Expression::Function(Box::new(Function::new(
4655 "ROUND".to_string(),
4656 vec![x, scale],
4657 ))))
4658 }
4659 }
4660
4661 "ROUND" if f.args.len() == 2 => {
4663 let mut args = f.args;
4664 let x = args.remove(0);
4665 let scale = args.remove(0);
4666 let needs_cast = match &scale {
4667 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4668 let Literal::Number(n) = lit.as_ref() else {
4669 unreachable!()
4670 };
4671 n.contains('.')
4672 }
4673 Expression::Cast(_) => {
4674 true
4676 }
4677 _ => false,
4678 };
4679 if needs_cast {
4680 Ok(Expression::Function(Box::new(Function::new(
4681 "ROUND".to_string(),
4682 vec![
4683 x,
4684 Expression::Cast(Box::new(Cast {
4685 this: scale,
4686 to: DataType::Int {
4687 length: None,
4688 integer_spelling: false,
4689 },
4690 trailing_comments: Vec::new(),
4691 double_colon_syntax: false,
4692 format: None,
4693 default: None,
4694 inferred_type: None,
4695 })),
4696 ],
4697 ))))
4698 } else {
4699 Ok(Expression::Function(Box::new(Function::new(
4700 "ROUND".to_string(),
4701 vec![x, scale],
4702 ))))
4703 }
4704 }
4705
4706 "FLOOR" if f.args.len() == 2 => {
4708 let mut args = f.args;
4709 let x = args.remove(0);
4710 let scale = args.remove(0);
4711 let needs_cast = match &scale {
4713 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4714 let Literal::Number(n) = lit.as_ref() else {
4715 unreachable!()
4716 };
4717 n.contains('.')
4718 }
4719 _ => false,
4720 };
4721 let int_scale = if needs_cast {
4722 Expression::Cast(Box::new(Cast {
4723 this: scale.clone(),
4724 to: DataType::Int {
4725 length: None,
4726 integer_spelling: false,
4727 },
4728 trailing_comments: Vec::new(),
4729 double_colon_syntax: false,
4730 format: None,
4731 default: None,
4732 inferred_type: None,
4733 }))
4734 } else {
4735 scale.clone()
4736 };
4737 let power_10 = Expression::Function(Box::new(Function::new(
4738 "POWER".to_string(),
4739 vec![Expression::number(10), int_scale.clone()],
4740 )));
4741 let x_paren = match &x {
4742 Expression::Add(_)
4743 | Expression::Sub(_)
4744 | Expression::Mul(_)
4745 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4746 this: x,
4747 trailing_comments: Vec::new(),
4748 })),
4749 _ => x,
4750 };
4751 let multiplied = Expression::Mul(Box::new(BinaryOp {
4752 left: x_paren,
4753 right: power_10.clone(),
4754 left_comments: Vec::new(),
4755 operator_comments: Vec::new(),
4756 trailing_comments: Vec::new(),
4757 inferred_type: None,
4758 }));
4759 let floored = Expression::Function(Box::new(Function::new(
4760 "FLOOR".to_string(),
4761 vec![multiplied],
4762 )));
4763 let divided = Expression::Div(Box::new(BinaryOp {
4764 left: floored,
4765 right: power_10,
4766 left_comments: Vec::new(),
4767 operator_comments: Vec::new(),
4768 trailing_comments: Vec::new(),
4769 inferred_type: None,
4770 }));
4771 Ok(Expression::Function(Box::new(Function::new(
4772 "ROUND".to_string(),
4773 vec![divided, int_scale],
4774 ))))
4775 }
4776
4777 "CEIL" | "CEILING" if f.args.len() == 2 => {
4779 let mut args = f.args;
4780 let x = args.remove(0);
4781 let scale = args.remove(0);
4782 let needs_cast = match &scale {
4783 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4784 let Literal::Number(n) = lit.as_ref() else {
4785 unreachable!()
4786 };
4787 n.contains('.')
4788 }
4789 _ => false,
4790 };
4791 let int_scale = if needs_cast {
4792 Expression::Cast(Box::new(Cast {
4793 this: scale.clone(),
4794 to: DataType::Int {
4795 length: None,
4796 integer_spelling: false,
4797 },
4798 trailing_comments: Vec::new(),
4799 double_colon_syntax: false,
4800 format: None,
4801 default: None,
4802 inferred_type: None,
4803 }))
4804 } else {
4805 scale.clone()
4806 };
4807 let power_10 = Expression::Function(Box::new(Function::new(
4808 "POWER".to_string(),
4809 vec![Expression::number(10), int_scale.clone()],
4810 )));
4811 let x_paren = match &x {
4812 Expression::Add(_)
4813 | Expression::Sub(_)
4814 | Expression::Mul(_)
4815 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4816 this: x,
4817 trailing_comments: Vec::new(),
4818 })),
4819 _ => x,
4820 };
4821 let multiplied = Expression::Mul(Box::new(BinaryOp {
4822 left: x_paren,
4823 right: power_10.clone(),
4824 left_comments: Vec::new(),
4825 operator_comments: Vec::new(),
4826 trailing_comments: Vec::new(),
4827 inferred_type: None,
4828 }));
4829 let ceiled = Expression::Function(Box::new(Function::new(
4830 "CEIL".to_string(),
4831 vec![multiplied],
4832 )));
4833 let divided = Expression::Div(Box::new(BinaryOp {
4834 left: ceiled,
4835 right: power_10,
4836 left_comments: Vec::new(),
4837 operator_comments: Vec::new(),
4838 trailing_comments: Vec::new(),
4839 inferred_type: None,
4840 }));
4841 Ok(Expression::Function(Box::new(Function::new(
4842 "ROUND".to_string(),
4843 vec![divided, int_scale],
4844 ))))
4845 }
4846
4847 "ADD_MONTHS" if f.args.len() == 2 => {
4849 let mut args = f.args;
4850 let date_expr_raw = args.remove(0);
4851 let months_expr = args.remove(0);
4852
4853 let was_string_literal = matches!(&date_expr_raw, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)));
4855
4856 let date_expr = match &date_expr_raw {
4858 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4859 Expression::Cast(Box::new(Cast {
4860 this: date_expr_raw,
4861 to: DataType::Timestamp {
4862 precision: None,
4863 timezone: false,
4864 },
4865 trailing_comments: Vec::new(),
4866 double_colon_syntax: false,
4867 format: None,
4868 default: None,
4869 inferred_type: None,
4870 }))
4871 }
4872 _ => date_expr_raw,
4873 };
4874
4875 let date_type = if was_string_literal {
4878 None
4879 } else {
4880 match &date_expr {
4881 Expression::Cast(c) => Some(c.to.clone()),
4882 _ => None,
4883 }
4884 };
4885
4886 let is_non_integer_months = match &months_expr {
4888 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4889 let Literal::Number(n) = lit.as_ref() else {
4890 unreachable!()
4891 };
4892 n.contains('.')
4893 }
4894 Expression::Neg(_) => {
4895 if let Expression::Neg(um) = &months_expr {
4896 matches!(&um.this, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(n) if n.contains('.')))
4897 } else {
4898 false
4899 }
4900 }
4901 Expression::Cast(c) => matches!(&c.to, DataType::Decimal { .. }),
4903 _ => false,
4904 };
4905
4906 let is_negative = match &months_expr {
4907 Expression::Neg(_) => true,
4908 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4909 let Literal::Number(n) = lit.as_ref() else {
4910 unreachable!()
4911 };
4912 n.starts_with('-')
4913 }
4914 _ => false,
4915 };
4916 let is_null = matches!(&months_expr, Expression::Null(_));
4917
4918 let interval_expr = if is_non_integer_months {
4919 Expression::Function(Box::new(Function::new(
4921 "TO_MONTHS".to_string(),
4922 vec![Expression::Cast(Box::new(Cast {
4923 this: Expression::Function(Box::new(Function::new(
4924 "ROUND".to_string(),
4925 vec![months_expr.clone()],
4926 ))),
4927 to: DataType::Int {
4928 length: None,
4929 integer_spelling: false,
4930 },
4931 trailing_comments: Vec::new(),
4932 double_colon_syntax: false,
4933 format: None,
4934 default: None,
4935 inferred_type: None,
4936 }))],
4937 )))
4938 } else if is_negative || is_null {
4939 Expression::Interval(Box::new(Interval {
4941 this: Some(Expression::Paren(Box::new(Paren {
4942 this: months_expr.clone(),
4943 trailing_comments: Vec::new(),
4944 }))),
4945 unit: Some(IntervalUnitSpec::Simple {
4946 unit: IntervalUnit::Month,
4947 use_plural: false,
4948 }),
4949 }))
4950 } else {
4951 Expression::Interval(Box::new(Interval {
4953 this: Some(months_expr.clone()),
4954 unit: Some(IntervalUnitSpec::Simple {
4955 unit: IntervalUnit::Month,
4956 use_plural: false,
4957 }),
4958 }))
4959 };
4960
4961 let date_plus_interval = Expression::Add(Box::new(BinaryOp {
4962 left: date_expr.clone(),
4963 right: interval_expr.clone(),
4964 left_comments: Vec::new(),
4965 operator_comments: Vec::new(),
4966 trailing_comments: Vec::new(),
4967 inferred_type: None,
4968 }));
4969
4970 let case_expr = Expression::Case(Box::new(Case {
4971 operand: None,
4972 whens: vec![(
4973 Expression::Eq(Box::new(BinaryOp {
4974 left: Expression::Function(Box::new(Function::new(
4975 "LAST_DAY".to_string(),
4976 vec![date_expr.clone()],
4977 ))),
4978 right: date_expr.clone(),
4979 left_comments: Vec::new(),
4980 operator_comments: Vec::new(),
4981 trailing_comments: Vec::new(),
4982 inferred_type: None,
4983 })),
4984 Expression::Function(Box::new(Function::new(
4985 "LAST_DAY".to_string(),
4986 vec![date_plus_interval.clone()],
4987 ))),
4988 )],
4989 else_: Some(date_plus_interval),
4990 comments: Vec::new(),
4991 inferred_type: None,
4992 }));
4993
4994 if let Some(dt) = date_type {
4996 Ok(Expression::Cast(Box::new(Cast {
4997 this: case_expr,
4998 to: dt,
4999 trailing_comments: Vec::new(),
5000 double_colon_syntax: false,
5001 format: None,
5002 default: None,
5003 inferred_type: None,
5004 })))
5005 } else {
5006 Ok(case_expr)
5007 }
5008 }
5009
5010 "TIME_SLICE" if f.args.len() >= 3 => {
5013 let mut args = f.args;
5014 let date_expr = args.remove(0);
5015 let n = args.remove(0);
5016 let unit_str = args.remove(0);
5017 let alignment = if !args.is_empty() {
5018 Some(args.remove(0))
5019 } else {
5020 None
5021 };
5022
5023 let unit = match &unit_str {
5025 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5026 let Literal::String(s) = lit.as_ref() else {
5027 unreachable!()
5028 };
5029 s.to_uppercase()
5030 }
5031 Expression::Column(c) => c.name.name.to_uppercase(),
5032 Expression::Identifier(i) => i.name.to_uppercase(),
5033 _ => "DAY".to_string(),
5034 };
5035
5036 let interval_unit = match unit.as_str() {
5037 "YEAR" => IntervalUnit::Year,
5038 "QUARTER" => IntervalUnit::Quarter,
5039 "MONTH" => IntervalUnit::Month,
5040 "WEEK" => IntervalUnit::Week,
5041 "DAY" => IntervalUnit::Day,
5042 "HOUR" => IntervalUnit::Hour,
5043 "MINUTE" => IntervalUnit::Minute,
5044 "SECOND" => IntervalUnit::Second,
5045 _ => IntervalUnit::Day,
5046 };
5047
5048 let interval = Expression::Interval(Box::new(Interval {
5049 this: Some(n.clone()),
5050 unit: Some(IntervalUnitSpec::Simple {
5051 unit: interval_unit.clone(),
5052 use_plural: false,
5053 }),
5054 }));
5055
5056 let time_bucket = Expression::Function(Box::new(Function::new(
5057 "TIME_BUCKET".to_string(),
5058 vec![interval.clone(), date_expr.clone()],
5059 )));
5060
5061 let is_end = match &alignment {
5062 Some(Expression::Literal(lit))
5063 if matches!(lit.as_ref(), Literal::String(_)) =>
5064 {
5065 let Literal::String(s) = lit.as_ref() else {
5066 unreachable!()
5067 };
5068 s.to_uppercase() == "END"
5069 }
5070 _ => false,
5071 };
5072
5073 let is_date_type = match &date_expr {
5075 Expression::Cast(c) => matches!(&c.to, DataType::Date),
5076 _ => false,
5077 };
5078
5079 if is_end {
5080 let bucket_plus = Expression::Add(Box::new(BinaryOp {
5081 left: time_bucket,
5082 right: Expression::Interval(Box::new(Interval {
5083 this: Some(n),
5084 unit: Some(IntervalUnitSpec::Simple {
5085 unit: interval_unit,
5086 use_plural: false,
5087 }),
5088 })),
5089 left_comments: Vec::new(),
5090 operator_comments: Vec::new(),
5091 trailing_comments: Vec::new(),
5092 inferred_type: None,
5093 }));
5094 if is_date_type {
5095 Ok(Expression::Cast(Box::new(Cast {
5096 this: bucket_plus,
5097 to: DataType::Date,
5098 trailing_comments: Vec::new(),
5099 double_colon_syntax: false,
5100 format: None,
5101 default: None,
5102 inferred_type: None,
5103 })))
5104 } else {
5105 Ok(bucket_plus)
5106 }
5107 } else {
5108 Ok(time_bucket)
5109 }
5110 }
5111
5112 "DATE_FROM_PARTS" | "DATEFROMPARTS" if f.args.len() == 3 => {
5114 let mut args = f.args;
5115 let year = args.remove(0);
5116 let month = args.remove(0);
5117 let day = args.remove(0);
5118
5119 let make_date = Expression::Function(Box::new(Function::new(
5120 "MAKE_DATE".to_string(),
5121 vec![year, Expression::number(1), Expression::number(1)],
5122 )));
5123
5124 let month_wrapped = match &month {
5126 Expression::Add(_)
5127 | Expression::Sub(_)
5128 | Expression::Mul(_)
5129 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
5130 this: month,
5131 trailing_comments: Vec::new(),
5132 })),
5133 _ => month,
5134 };
5135 let day_wrapped = match &day {
5136 Expression::Add(_)
5137 | Expression::Sub(_)
5138 | Expression::Mul(_)
5139 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
5140 this: day,
5141 trailing_comments: Vec::new(),
5142 })),
5143 _ => day,
5144 };
5145 let month_minus_1 = Expression::Sub(Box::new(BinaryOp {
5146 left: month_wrapped,
5147 right: Expression::number(1),
5148 left_comments: Vec::new(),
5149 operator_comments: Vec::new(),
5150 trailing_comments: Vec::new(),
5151 inferred_type: None,
5152 }));
5153 let month_interval = Expression::Interval(Box::new(Interval {
5154 this: Some(Expression::Paren(Box::new(Paren {
5155 this: month_minus_1,
5156 trailing_comments: Vec::new(),
5157 }))),
5158 unit: Some(IntervalUnitSpec::Simple {
5159 unit: IntervalUnit::Month,
5160 use_plural: false,
5161 }),
5162 }));
5163
5164 let day_minus_1 = Expression::Sub(Box::new(BinaryOp {
5165 left: day_wrapped,
5166 right: Expression::number(1),
5167 left_comments: Vec::new(),
5168 operator_comments: Vec::new(),
5169 trailing_comments: Vec::new(),
5170 inferred_type: None,
5171 }));
5172 let day_interval = Expression::Interval(Box::new(Interval {
5173 this: Some(Expression::Paren(Box::new(Paren {
5174 this: day_minus_1,
5175 trailing_comments: Vec::new(),
5176 }))),
5177 unit: Some(IntervalUnitSpec::Simple {
5178 unit: IntervalUnit::Day,
5179 use_plural: false,
5180 }),
5181 }));
5182
5183 let result = Expression::Add(Box::new(BinaryOp {
5184 left: Expression::Add(Box::new(BinaryOp {
5185 left: make_date,
5186 right: month_interval,
5187 left_comments: Vec::new(),
5188 operator_comments: Vec::new(),
5189 trailing_comments: Vec::new(),
5190 inferred_type: None,
5191 })),
5192 right: day_interval,
5193 left_comments: Vec::new(),
5194 operator_comments: Vec::new(),
5195 trailing_comments: Vec::new(),
5196 inferred_type: None,
5197 }));
5198
5199 Ok(Expression::Cast(Box::new(Cast {
5200 this: result,
5201 to: DataType::Date,
5202 trailing_comments: Vec::new(),
5203 double_colon_syntax: false,
5204 format: None,
5205 default: None,
5206 inferred_type: None,
5207 })))
5208 }
5209
5210 "NEXT_DAY" if f.args.len() == 2 => {
5212 let mut args = f.args;
5213 let date = args.remove(0);
5214 let day_name = args.remove(0);
5215
5216 let day_num = match &day_name {
5218 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5219 let Literal::String(s) = lit.as_ref() else {
5220 unreachable!()
5221 };
5222 let upper = s.to_uppercase();
5223 if upper.starts_with("MO") {
5224 Some(1)
5225 } else if upper.starts_with("TU") {
5226 Some(2)
5227 } else if upper.starts_with("WE") {
5228 Some(3)
5229 } else if upper.starts_with("TH") {
5230 Some(4)
5231 } else if upper.starts_with("FR") {
5232 Some(5)
5233 } else if upper.starts_with("SA") {
5234 Some(6)
5235 } else if upper.starts_with("SU") {
5236 Some(7)
5237 } else {
5238 None
5239 }
5240 }
5241 _ => None,
5242 };
5243
5244 let target_day_expr = if let Some(n) = day_num {
5245 Expression::number(n)
5246 } else {
5247 Expression::Case(Box::new(Case {
5249 operand: None,
5250 whens: vec![
5251 (
5252 Expression::Function(Box::new(Function::new(
5253 "STARTS_WITH".to_string(),
5254 vec![
5255 Expression::Upper(Box::new(UnaryFunc::new(
5256 day_name.clone(),
5257 ))),
5258 Expression::Literal(Box::new(Literal::String(
5259 "MO".to_string(),
5260 ))),
5261 ],
5262 ))),
5263 Expression::number(1),
5264 ),
5265 (
5266 Expression::Function(Box::new(Function::new(
5267 "STARTS_WITH".to_string(),
5268 vec![
5269 Expression::Upper(Box::new(UnaryFunc::new(
5270 day_name.clone(),
5271 ))),
5272 Expression::Literal(Box::new(Literal::String(
5273 "TU".to_string(),
5274 ))),
5275 ],
5276 ))),
5277 Expression::number(2),
5278 ),
5279 (
5280 Expression::Function(Box::new(Function::new(
5281 "STARTS_WITH".to_string(),
5282 vec![
5283 Expression::Upper(Box::new(UnaryFunc::new(
5284 day_name.clone(),
5285 ))),
5286 Expression::Literal(Box::new(Literal::String(
5287 "WE".to_string(),
5288 ))),
5289 ],
5290 ))),
5291 Expression::number(3),
5292 ),
5293 (
5294 Expression::Function(Box::new(Function::new(
5295 "STARTS_WITH".to_string(),
5296 vec![
5297 Expression::Upper(Box::new(UnaryFunc::new(
5298 day_name.clone(),
5299 ))),
5300 Expression::Literal(Box::new(Literal::String(
5301 "TH".to_string(),
5302 ))),
5303 ],
5304 ))),
5305 Expression::number(4),
5306 ),
5307 (
5308 Expression::Function(Box::new(Function::new(
5309 "STARTS_WITH".to_string(),
5310 vec![
5311 Expression::Upper(Box::new(UnaryFunc::new(
5312 day_name.clone(),
5313 ))),
5314 Expression::Literal(Box::new(Literal::String(
5315 "FR".to_string(),
5316 ))),
5317 ],
5318 ))),
5319 Expression::number(5),
5320 ),
5321 (
5322 Expression::Function(Box::new(Function::new(
5323 "STARTS_WITH".to_string(),
5324 vec![
5325 Expression::Upper(Box::new(UnaryFunc::new(
5326 day_name.clone(),
5327 ))),
5328 Expression::Literal(Box::new(Literal::String(
5329 "SA".to_string(),
5330 ))),
5331 ],
5332 ))),
5333 Expression::number(6),
5334 ),
5335 (
5336 Expression::Function(Box::new(Function::new(
5337 "STARTS_WITH".to_string(),
5338 vec![
5339 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
5340 Expression::Literal(Box::new(Literal::String(
5341 "SU".to_string(),
5342 ))),
5343 ],
5344 ))),
5345 Expression::number(7),
5346 ),
5347 ],
5348 else_: None,
5349 comments: Vec::new(),
5350 inferred_type: None,
5351 }))
5352 };
5353
5354 let isodow = Expression::Function(Box::new(Function::new(
5355 "ISODOW".to_string(),
5356 vec![date.clone()],
5357 )));
5358 let diff = Expression::Add(Box::new(BinaryOp {
5360 left: Expression::Paren(Box::new(Paren {
5361 this: Expression::Mod(Box::new(BinaryOp {
5362 left: Expression::Paren(Box::new(Paren {
5363 this: Expression::Add(Box::new(BinaryOp {
5364 left: Expression::Paren(Box::new(Paren {
5365 this: Expression::Sub(Box::new(BinaryOp {
5366 left: target_day_expr,
5367 right: isodow,
5368 left_comments: Vec::new(),
5369 operator_comments: Vec::new(),
5370 trailing_comments: Vec::new(),
5371 inferred_type: None,
5372 })),
5373 trailing_comments: Vec::new(),
5374 })),
5375 right: Expression::number(6),
5376 left_comments: Vec::new(),
5377 operator_comments: Vec::new(),
5378 trailing_comments: Vec::new(),
5379 inferred_type: None,
5380 })),
5381 trailing_comments: Vec::new(),
5382 })),
5383 right: Expression::number(7),
5384 left_comments: Vec::new(),
5385 operator_comments: Vec::new(),
5386 trailing_comments: Vec::new(),
5387 inferred_type: None,
5388 })),
5389 trailing_comments: Vec::new(),
5390 })),
5391 right: Expression::number(1),
5392 left_comments: Vec::new(),
5393 operator_comments: Vec::new(),
5394 trailing_comments: Vec::new(),
5395 inferred_type: None,
5396 }));
5397
5398 let result = Expression::Add(Box::new(BinaryOp {
5399 left: date,
5400 right: Expression::Interval(Box::new(Interval {
5401 this: Some(Expression::Paren(Box::new(Paren {
5402 this: diff,
5403 trailing_comments: Vec::new(),
5404 }))),
5405 unit: Some(IntervalUnitSpec::Simple {
5406 unit: IntervalUnit::Day,
5407 use_plural: false,
5408 }),
5409 })),
5410 left_comments: Vec::new(),
5411 operator_comments: Vec::new(),
5412 trailing_comments: Vec::new(),
5413 inferred_type: None,
5414 }));
5415
5416 Ok(Expression::Cast(Box::new(Cast {
5417 this: result,
5418 to: DataType::Date,
5419 trailing_comments: Vec::new(),
5420 double_colon_syntax: false,
5421 format: None,
5422 default: None,
5423 inferred_type: None,
5424 })))
5425 }
5426
5427 "PREVIOUS_DAY" if f.args.len() == 2 => {
5429 let mut args = f.args;
5430 let date = args.remove(0);
5431 let day_name = args.remove(0);
5432
5433 let day_num = match &day_name {
5434 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5435 let Literal::String(s) = lit.as_ref() else {
5436 unreachable!()
5437 };
5438 let upper = s.to_uppercase();
5439 if upper.starts_with("MO") {
5440 Some(1)
5441 } else if upper.starts_with("TU") {
5442 Some(2)
5443 } else if upper.starts_with("WE") {
5444 Some(3)
5445 } else if upper.starts_with("TH") {
5446 Some(4)
5447 } else if upper.starts_with("FR") {
5448 Some(5)
5449 } else if upper.starts_with("SA") {
5450 Some(6)
5451 } else if upper.starts_with("SU") {
5452 Some(7)
5453 } else {
5454 None
5455 }
5456 }
5457 _ => None,
5458 };
5459
5460 let target_day_expr = if let Some(n) = day_num {
5461 Expression::number(n)
5462 } else {
5463 Expression::Case(Box::new(Case {
5464 operand: None,
5465 whens: vec![
5466 (
5467 Expression::Function(Box::new(Function::new(
5468 "STARTS_WITH".to_string(),
5469 vec![
5470 Expression::Upper(Box::new(UnaryFunc::new(
5471 day_name.clone(),
5472 ))),
5473 Expression::Literal(Box::new(Literal::String(
5474 "MO".to_string(),
5475 ))),
5476 ],
5477 ))),
5478 Expression::number(1),
5479 ),
5480 (
5481 Expression::Function(Box::new(Function::new(
5482 "STARTS_WITH".to_string(),
5483 vec![
5484 Expression::Upper(Box::new(UnaryFunc::new(
5485 day_name.clone(),
5486 ))),
5487 Expression::Literal(Box::new(Literal::String(
5488 "TU".to_string(),
5489 ))),
5490 ],
5491 ))),
5492 Expression::number(2),
5493 ),
5494 (
5495 Expression::Function(Box::new(Function::new(
5496 "STARTS_WITH".to_string(),
5497 vec![
5498 Expression::Upper(Box::new(UnaryFunc::new(
5499 day_name.clone(),
5500 ))),
5501 Expression::Literal(Box::new(Literal::String(
5502 "WE".to_string(),
5503 ))),
5504 ],
5505 ))),
5506 Expression::number(3),
5507 ),
5508 (
5509 Expression::Function(Box::new(Function::new(
5510 "STARTS_WITH".to_string(),
5511 vec![
5512 Expression::Upper(Box::new(UnaryFunc::new(
5513 day_name.clone(),
5514 ))),
5515 Expression::Literal(Box::new(Literal::String(
5516 "TH".to_string(),
5517 ))),
5518 ],
5519 ))),
5520 Expression::number(4),
5521 ),
5522 (
5523 Expression::Function(Box::new(Function::new(
5524 "STARTS_WITH".to_string(),
5525 vec![
5526 Expression::Upper(Box::new(UnaryFunc::new(
5527 day_name.clone(),
5528 ))),
5529 Expression::Literal(Box::new(Literal::String(
5530 "FR".to_string(),
5531 ))),
5532 ],
5533 ))),
5534 Expression::number(5),
5535 ),
5536 (
5537 Expression::Function(Box::new(Function::new(
5538 "STARTS_WITH".to_string(),
5539 vec![
5540 Expression::Upper(Box::new(UnaryFunc::new(
5541 day_name.clone(),
5542 ))),
5543 Expression::Literal(Box::new(Literal::String(
5544 "SA".to_string(),
5545 ))),
5546 ],
5547 ))),
5548 Expression::number(6),
5549 ),
5550 (
5551 Expression::Function(Box::new(Function::new(
5552 "STARTS_WITH".to_string(),
5553 vec![
5554 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
5555 Expression::Literal(Box::new(Literal::String(
5556 "SU".to_string(),
5557 ))),
5558 ],
5559 ))),
5560 Expression::number(7),
5561 ),
5562 ],
5563 else_: None,
5564 comments: Vec::new(),
5565 inferred_type: None,
5566 }))
5567 };
5568
5569 let isodow = Expression::Function(Box::new(Function::new(
5570 "ISODOW".to_string(),
5571 vec![date.clone()],
5572 )));
5573 let diff = Expression::Add(Box::new(BinaryOp {
5575 left: Expression::Paren(Box::new(Paren {
5576 this: Expression::Mod(Box::new(BinaryOp {
5577 left: Expression::Paren(Box::new(Paren {
5578 this: Expression::Add(Box::new(BinaryOp {
5579 left: Expression::Paren(Box::new(Paren {
5580 this: Expression::Sub(Box::new(BinaryOp {
5581 left: isodow,
5582 right: target_day_expr,
5583 left_comments: Vec::new(),
5584 operator_comments: Vec::new(),
5585 trailing_comments: Vec::new(),
5586 inferred_type: None,
5587 })),
5588 trailing_comments: Vec::new(),
5589 })),
5590 right: Expression::number(6),
5591 left_comments: Vec::new(),
5592 operator_comments: Vec::new(),
5593 trailing_comments: Vec::new(),
5594 inferred_type: None,
5595 })),
5596 trailing_comments: Vec::new(),
5597 })),
5598 right: Expression::number(7),
5599 left_comments: Vec::new(),
5600 operator_comments: Vec::new(),
5601 trailing_comments: Vec::new(),
5602 inferred_type: None,
5603 })),
5604 trailing_comments: Vec::new(),
5605 })),
5606 right: Expression::number(1),
5607 left_comments: Vec::new(),
5608 operator_comments: Vec::new(),
5609 trailing_comments: Vec::new(),
5610 inferred_type: None,
5611 }));
5612
5613 let result = Expression::Sub(Box::new(BinaryOp {
5614 left: date,
5615 right: Expression::Interval(Box::new(Interval {
5616 this: Some(Expression::Paren(Box::new(Paren {
5617 this: diff,
5618 trailing_comments: Vec::new(),
5619 }))),
5620 unit: Some(IntervalUnitSpec::Simple {
5621 unit: IntervalUnit::Day,
5622 use_plural: false,
5623 }),
5624 })),
5625 left_comments: Vec::new(),
5626 operator_comments: Vec::new(),
5627 trailing_comments: Vec::new(),
5628 inferred_type: None,
5629 }));
5630
5631 Ok(Expression::Cast(Box::new(Cast {
5632 this: result,
5633 to: DataType::Date,
5634 trailing_comments: Vec::new(),
5635 double_colon_syntax: false,
5636 format: None,
5637 default: None,
5638 inferred_type: None,
5639 })))
5640 }
5641
5642 "LAST_DAY" if f.args.len() == 2 => {
5646 let mut args = f.args;
5647 let date = args.remove(0);
5648 let unit = args.remove(0);
5649 let unit_str = match &unit {
5650 Expression::Column(c) => c.name.name.to_uppercase(),
5651 Expression::Identifier(i) => i.name.to_uppercase(),
5652 _ => String::new(),
5653 };
5654
5655 match unit_str.as_str() {
5656 "MONTH" => Ok(Expression::Function(Box::new(Function::new(
5657 "LAST_DAY".to_string(),
5658 vec![date],
5659 )))),
5660 "YEAR" => Ok(Expression::Function(Box::new(Function::new(
5661 "MAKE_DATE".to_string(),
5662 vec![
5663 Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5664 this: date,
5665 field: crate::expressions::DateTimeField::Year,
5666 })),
5667 Expression::number(12),
5668 Expression::number(31),
5669 ],
5670 )))),
5671 "QUARTER" => {
5672 let year = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5673 this: date.clone(),
5674 field: crate::expressions::DateTimeField::Year,
5675 }));
5676 let quarter_month = Expression::Mul(Box::new(BinaryOp {
5677 left: Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5678 this: date,
5679 field: crate::expressions::DateTimeField::Custom(
5680 "QUARTER".to_string(),
5681 ),
5682 })),
5683 right: Expression::number(3),
5684 left_comments: Vec::new(),
5685 operator_comments: Vec::new(),
5686 trailing_comments: Vec::new(),
5687 inferred_type: None,
5688 }));
5689 let make_date = Expression::Function(Box::new(Function::new(
5690 "MAKE_DATE".to_string(),
5691 vec![year, quarter_month, Expression::number(1)],
5692 )));
5693 Ok(Expression::Function(Box::new(Function::new(
5694 "LAST_DAY".to_string(),
5695 vec![make_date],
5696 ))))
5697 }
5698 "WEEK" => {
5699 let dow = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5700 this: date.clone(),
5701 field: crate::expressions::DateTimeField::Custom(
5702 "DAYOFWEEK".to_string(),
5703 ),
5704 }));
5705 let diff = Expression::Mod(Box::new(BinaryOp {
5706 left: Expression::Paren(Box::new(Paren {
5707 this: Expression::Sub(Box::new(BinaryOp {
5708 left: Expression::number(7),
5709 right: dow,
5710 left_comments: Vec::new(),
5711 operator_comments: Vec::new(),
5712 trailing_comments: Vec::new(),
5713 inferred_type: None,
5714 })),
5715 trailing_comments: Vec::new(),
5716 })),
5717 right: Expression::number(7),
5718 left_comments: Vec::new(),
5719 operator_comments: Vec::new(),
5720 trailing_comments: Vec::new(),
5721 inferred_type: None,
5722 }));
5723 let result = Expression::Add(Box::new(BinaryOp {
5724 left: date,
5725 right: Expression::Interval(Box::new(Interval {
5726 this: Some(Expression::Paren(Box::new(Paren {
5727 this: diff,
5728 trailing_comments: Vec::new(),
5729 }))),
5730 unit: Some(IntervalUnitSpec::Simple {
5731 unit: IntervalUnit::Day,
5732 use_plural: false,
5733 }),
5734 })),
5735 left_comments: Vec::new(),
5736 operator_comments: Vec::new(),
5737 trailing_comments: Vec::new(),
5738 inferred_type: None,
5739 }));
5740 Ok(Expression::Cast(Box::new(Cast {
5741 this: result,
5742 to: DataType::Date,
5743 trailing_comments: Vec::new(),
5744 double_colon_syntax: false,
5745 format: None,
5746 default: None,
5747 inferred_type: None,
5748 })))
5749 }
5750 _ => Ok(Expression::Function(Box::new(Function::new(
5751 "LAST_DAY".to_string(),
5752 vec![date, unit],
5753 )))),
5754 }
5755 }
5756
5757 "SEQ1" | "SEQ2" | "SEQ4" | "SEQ8" => {
5760 let (range, half): (u128, u128) = match name_upper.as_str() {
5761 "SEQ1" => (256, 128),
5762 "SEQ2" => (65536, 32768),
5763 "SEQ4" => (4294967296, 2147483648),
5764 "SEQ8" => (18446744073709551616, 9223372036854775808),
5765 _ => unreachable!("sequence type already matched in caller"),
5766 };
5767
5768 let is_signed = match f.args.first() {
5769 Some(Expression::Literal(lit))
5770 if matches!(lit.as_ref(), Literal::Number(_)) =>
5771 {
5772 let Literal::Number(n) = lit.as_ref() else {
5773 unreachable!()
5774 };
5775 n == "1"
5776 }
5777 _ => false,
5778 };
5779
5780 let row_num = Expression::Sub(Box::new(BinaryOp {
5781 left: Expression::WindowFunction(Box::new(
5782 crate::expressions::WindowFunction {
5783 this: Expression::Function(Box::new(Function::new(
5784 "ROW_NUMBER".to_string(),
5785 vec![],
5786 ))),
5787 over: crate::expressions::Over {
5788 window_name: None,
5789 partition_by: vec![],
5790 order_by: vec![crate::expressions::Ordered {
5791 this: Expression::number(1),
5792 desc: false,
5793 nulls_first: Some(true),
5794 explicit_asc: false,
5795 with_fill: None,
5796 }],
5797 frame: None,
5798 alias: None,
5799 },
5800 keep: None,
5801 inferred_type: None,
5802 },
5803 )),
5804 right: Expression::number(1),
5805 left_comments: Vec::new(),
5806 operator_comments: Vec::new(),
5807 trailing_comments: Vec::new(),
5808 inferred_type: None,
5809 }));
5810
5811 let modded = Expression::Mod(Box::new(BinaryOp {
5812 left: Expression::Paren(Box::new(Paren {
5813 this: row_num,
5814 trailing_comments: Vec::new(),
5815 })),
5816 right: Expression::Literal(Box::new(Literal::Number(range.to_string()))),
5817 left_comments: Vec::new(),
5818 operator_comments: Vec::new(),
5819 trailing_comments: Vec::new(),
5820 inferred_type: None,
5821 }));
5822
5823 if is_signed {
5824 let cond = Expression::Gte(Box::new(BinaryOp {
5826 left: modded.clone(),
5827 right: Expression::Literal(Box::new(Literal::Number(half.to_string()))),
5828 left_comments: Vec::new(),
5829 operator_comments: Vec::new(),
5830 trailing_comments: Vec::new(),
5831 inferred_type: None,
5832 }));
5833 let signed_val = Expression::Sub(Box::new(BinaryOp {
5834 left: modded.clone(),
5835 right: Expression::Literal(Box::new(Literal::Number(range.to_string()))),
5836 left_comments: Vec::new(),
5837 operator_comments: Vec::new(),
5838 trailing_comments: Vec::new(),
5839 inferred_type: None,
5840 }));
5841 Ok(Expression::Paren(Box::new(Paren {
5842 this: Expression::Case(Box::new(Case {
5843 operand: None,
5844 whens: vec![(cond, signed_val)],
5845 else_: Some(modded),
5846 comments: Vec::new(),
5847 inferred_type: None,
5848 })),
5849 trailing_comments: Vec::new(),
5850 })))
5851 } else {
5852 Ok(modded)
5853 }
5854 }
5855
5856 "TABLE" if f.args.len() == 1 => {
5859 let inner = f.args.into_iter().next().unwrap();
5860 if let Expression::Function(ref gen_f) = inner {
5862 if gen_f.name.to_uppercase() == "GENERATOR" {
5863 let mut rowcount = None;
5864 for arg in &gen_f.args {
5865 if let Expression::NamedArgument(na) = arg {
5866 if na.name.name.to_uppercase() == "ROWCOUNT" {
5867 rowcount = Some(na.value.clone());
5868 }
5869 }
5870 }
5871 if let Some(n) = rowcount {
5872 return Ok(Expression::Function(Box::new(Function::new(
5873 "RANGE".to_string(),
5874 vec![n],
5875 ))));
5876 }
5877 }
5878 }
5879 Ok(inner)
5880 }
5881
5882 "GENERATOR" => {
5884 let mut rowcount = None;
5885 for arg in &f.args {
5886 if let Expression::NamedArgument(na) = arg {
5887 if na.name.name.to_uppercase() == "ROWCOUNT" {
5888 rowcount = Some(na.value.clone());
5889 }
5890 }
5891 }
5892 if let Some(n) = rowcount {
5893 Ok(Expression::Function(Box::new(Function::new(
5894 "RANGE".to_string(),
5895 vec![n],
5896 ))))
5897 } else {
5898 Ok(Expression::Function(Box::new(f)))
5899 }
5900 }
5901
5902 "UNIFORM" if f.args.len() == 3 => {
5905 let mut args = f.args;
5906 let low = args.remove(0);
5907 let high = args.remove(0);
5908 let gen = args.remove(0);
5909
5910 let range = Expression::Add(Box::new(BinaryOp {
5911 left: Expression::Sub(Box::new(BinaryOp {
5912 left: high,
5913 right: low.clone(),
5914 left_comments: Vec::new(),
5915 operator_comments: Vec::new(),
5916 trailing_comments: Vec::new(),
5917 inferred_type: None,
5918 })),
5919 right: Expression::number(1),
5920 left_comments: Vec::new(),
5921 operator_comments: Vec::new(),
5922 trailing_comments: Vec::new(),
5923 inferred_type: None,
5924 }));
5925
5926 let random_val = match &gen {
5928 Expression::Rand(_) | Expression::Random(_) => {
5929 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5931 }
5932 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
5933 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5935 }
5936 _ => {
5937 let hash = Expression::Function(Box::new(Function::new(
5939 "HASH".to_string(),
5940 vec![gen],
5941 )));
5942 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
5943 let modded = Expression::Mod(Box::new(BinaryOp {
5944 left: abs_hash,
5945 right: Expression::number(1000000),
5946 left_comments: Vec::new(),
5947 operator_comments: Vec::new(),
5948 trailing_comments: Vec::new(),
5949 inferred_type: None,
5950 }));
5951 let paren_modded = Expression::Paren(Box::new(Paren {
5952 this: modded,
5953 trailing_comments: Vec::new(),
5954 }));
5955 Expression::Div(Box::new(BinaryOp {
5956 left: paren_modded,
5957 right: Expression::Literal(Box::new(Literal::Number(
5958 "1000000.0".to_string(),
5959 ))),
5960 left_comments: Vec::new(),
5961 operator_comments: Vec::new(),
5962 trailing_comments: Vec::new(),
5963 inferred_type: None,
5964 }))
5965 }
5966 };
5967
5968 let inner = Expression::Function(Box::new(Function::new(
5969 "FLOOR".to_string(),
5970 vec![Expression::Add(Box::new(BinaryOp {
5971 left: low,
5972 right: Expression::Mul(Box::new(BinaryOp {
5973 left: random_val,
5974 right: Expression::Paren(Box::new(Paren {
5975 this: range,
5976 trailing_comments: Vec::new(),
5977 })),
5978 left_comments: Vec::new(),
5979 operator_comments: Vec::new(),
5980 trailing_comments: Vec::new(),
5981 inferred_type: None,
5982 })),
5983 left_comments: Vec::new(),
5984 operator_comments: Vec::new(),
5985 trailing_comments: Vec::new(),
5986 inferred_type: None,
5987 }))],
5988 )));
5989
5990 Ok(Expression::Cast(Box::new(Cast {
5991 this: inner,
5992 to: DataType::BigInt { length: None },
5993 trailing_comments: Vec::new(),
5994 double_colon_syntax: false,
5995 format: None,
5996 default: None,
5997 inferred_type: None,
5998 })))
5999 }
6000
6001 "NORMAL" if f.args.len() == 3 => {
6005 let mut args = f.args;
6006 let mean = args.remove(0);
6007 let stddev = args.remove(0);
6008 let gen = args.remove(0);
6009
6010 let make_seed_random = |seed: Expression| -> Expression {
6012 let hash = Expression::Function(Box::new(Function::new(
6013 "HASH".to_string(),
6014 vec![seed],
6015 )));
6016 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
6017 let modded = Expression::Mod(Box::new(BinaryOp {
6018 left: abs_hash,
6019 right: Expression::number(1000000),
6020 left_comments: Vec::new(),
6021 operator_comments: Vec::new(),
6022 trailing_comments: Vec::new(),
6023 inferred_type: None,
6024 }));
6025 let paren_modded = Expression::Paren(Box::new(Paren {
6026 this: modded,
6027 trailing_comments: Vec::new(),
6028 }));
6029 Expression::Div(Box::new(BinaryOp {
6030 left: paren_modded,
6031 right: Expression::Literal(Box::new(Literal::Number(
6032 "1000000.0".to_string(),
6033 ))),
6034 left_comments: Vec::new(),
6035 operator_comments: Vec::new(),
6036 trailing_comments: Vec::new(),
6037 inferred_type: None,
6038 }))
6039 };
6040
6041 let is_random_no_seed = match &gen {
6043 Expression::Random(_) => true,
6044 Expression::Rand(r) => r.seed.is_none(),
6045 _ => false,
6046 };
6047 let (u1, u2) = if is_random_no_seed {
6048 let u1 =
6050 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
6051 let u2 =
6052 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
6053 (u1, u2)
6054 } else {
6055 let seed = match gen {
6057 Expression::Rand(r) => r.seed.map(|s| *s).unwrap_or(Expression::number(0)),
6058 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
6059 if func.args.len() == 1 {
6060 func.args.into_iter().next().unwrap()
6061 } else {
6062 Expression::number(0)
6063 }
6064 }
6065 other => other,
6066 };
6067 let u1 = make_seed_random(seed.clone());
6068 let seed_plus_1 = Expression::Add(Box::new(BinaryOp {
6069 left: seed,
6070 right: Expression::number(1),
6071 left_comments: Vec::new(),
6072 operator_comments: Vec::new(),
6073 trailing_comments: Vec::new(),
6074 inferred_type: None,
6075 }));
6076 let u2 = make_seed_random(seed_plus_1);
6077 (u1, u2)
6078 };
6079
6080 let greatest = Expression::Greatest(Box::new(VarArgFunc {
6082 expressions: vec![
6083 u1,
6084 Expression::Literal(Box::new(Literal::Number("1e-10".to_string()))),
6085 ],
6086 original_name: None,
6087 inferred_type: None,
6088 }));
6089
6090 let neg2 = Expression::Neg(Box::new(crate::expressions::UnaryOp {
6092 this: Expression::number(2),
6093 inferred_type: None,
6094 }));
6095 let ln_greatest =
6096 Expression::Function(Box::new(Function::new("LN".to_string(), vec![greatest])));
6097 let neg2_times_ln = Expression::Mul(Box::new(BinaryOp {
6098 left: neg2,
6099 right: ln_greatest,
6100 left_comments: Vec::new(),
6101 operator_comments: Vec::new(),
6102 trailing_comments: Vec::new(),
6103 inferred_type: None,
6104 }));
6105 let sqrt_part = Expression::Function(Box::new(Function::new(
6106 "SQRT".to_string(),
6107 vec![neg2_times_ln],
6108 )));
6109
6110 let pi = Expression::Function(Box::new(Function::new("PI".to_string(), vec![])));
6112 let two_pi = Expression::Mul(Box::new(BinaryOp {
6113 left: Expression::number(2),
6114 right: pi,
6115 left_comments: Vec::new(),
6116 operator_comments: Vec::new(),
6117 trailing_comments: Vec::new(),
6118 inferred_type: None,
6119 }));
6120 let two_pi_u2 = Expression::Mul(Box::new(BinaryOp {
6121 left: two_pi,
6122 right: u2,
6123 left_comments: Vec::new(),
6124 operator_comments: Vec::new(),
6125 trailing_comments: Vec::new(),
6126 inferred_type: None,
6127 }));
6128 let cos_part = Expression::Function(Box::new(Function::new(
6129 "COS".to_string(),
6130 vec![two_pi_u2],
6131 )));
6132
6133 let stddev_times_sqrt = Expression::Mul(Box::new(BinaryOp {
6135 left: stddev,
6136 right: sqrt_part,
6137 left_comments: Vec::new(),
6138 operator_comments: Vec::new(),
6139 trailing_comments: Vec::new(),
6140 inferred_type: None,
6141 }));
6142 let inner = Expression::Mul(Box::new(BinaryOp {
6143 left: stddev_times_sqrt,
6144 right: cos_part,
6145 left_comments: Vec::new(),
6146 operator_comments: Vec::new(),
6147 trailing_comments: Vec::new(),
6148 inferred_type: None,
6149 }));
6150 let paren_inner = Expression::Paren(Box::new(Paren {
6151 this: inner,
6152 trailing_comments: Vec::new(),
6153 }));
6154
6155 Ok(Expression::Add(Box::new(BinaryOp {
6157 left: mean,
6158 right: paren_inner,
6159 left_comments: Vec::new(),
6160 operator_comments: Vec::new(),
6161 trailing_comments: Vec::new(),
6162 inferred_type: None,
6163 })))
6164 }
6165
6166 "ZIPF" if f.args.len() == 3 => {
6176 let mut args = f.args;
6177 let s_expr = args.remove(0);
6178 let n_expr = args.remove(0);
6179 let gen_expr = args.remove(0);
6180
6181 let s_sql = Self::expr_to_sql(&s_expr);
6182 let n_sql = Self::expr_to_sql(&n_expr);
6183 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
6184
6185 let rand_sql = if is_random {
6186 format!("SELECT {} AS r", seed_sql)
6187 } else {
6188 format!(
6189 "SELECT (ABS(HASH({})) % 1000000) / 1000000.0 AS r",
6190 seed_sql
6191 )
6192 };
6193
6194 let template = format!(
6195 "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)",
6196 rand_sql, s_sql, n_sql
6197 );
6198
6199 Self::parse_as_subquery(&template)
6200 }
6201
6202 "RANDSTR" if f.args.len() == 2 => {
6204 let mut args = f.args;
6205 let len_expr = args.remove(0);
6206 let gen_expr = args.remove(0);
6207
6208 let len_sql = Self::expr_to_sql(&len_expr);
6209 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
6210
6211 let random_value_sql = if is_random {
6212 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
6213 } else {
6214 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
6215 };
6216
6217 let template = format!(
6218 "SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT {} AS random_value FROM RANGE({}) AS t(i))",
6219 random_value_sql, len_sql
6220 );
6221
6222 Self::parse_as_subquery(&template)
6223 }
6224
6225 "MAP_CAT" if f.args.len() == 2 => {
6227 let mut args = f.args;
6228 let left = Self::normalize_empty_map_expr(args.remove(0));
6229 let right = Self::normalize_empty_map_expr(args.remove(0));
6230 let left_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6231 this: left.clone(),
6232 not: false,
6233 postfix_form: false,
6234 }));
6235 let right_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6236 this: right.clone(),
6237 not: false,
6238 postfix_form: false,
6239 }));
6240 let null_cond = Expression::Or(Box::new(BinaryOp {
6241 left: left_is_null,
6242 right: right_is_null,
6243 left_comments: Vec::new(),
6244 operator_comments: Vec::new(),
6245 trailing_comments: Vec::new(),
6246 inferred_type: None,
6247 }));
6248
6249 let list_concat = Expression::Function(Box::new(Function::new(
6250 "LIST_CONCAT".to_string(),
6251 vec![
6252 Expression::Function(Box::new(Function::new(
6253 "MAP_KEYS".to_string(),
6254 vec![left.clone()],
6255 ))),
6256 Expression::Function(Box::new(Function::new(
6257 "MAP_KEYS".to_string(),
6258 vec![right.clone()],
6259 ))),
6260 ],
6261 )));
6262 let list_distinct = Expression::Function(Box::new(Function::new(
6263 "LIST_DISTINCT".to_string(),
6264 vec![list_concat],
6265 )));
6266
6267 let k_ident = Identifier::new("__k");
6268 let k_ref = Expression::boxed_column(Column {
6269 table: None,
6270 name: k_ident.clone(),
6271 join_mark: false,
6272 trailing_comments: Vec::new(),
6273 span: None,
6274 inferred_type: None,
6275 });
6276 let right_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
6277 this: right.clone(),
6278 index: k_ref.clone(),
6279 }));
6280 let left_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
6281 this: left.clone(),
6282 index: k_ref.clone(),
6283 }));
6284 let key_value = Expression::Coalesce(Box::new(VarArgFunc {
6285 expressions: vec![right_key, left_key],
6286 original_name: None,
6287 inferred_type: None,
6288 }));
6289 let struct_pack = Expression::Function(Box::new(Function::new(
6290 "STRUCT_PACK".to_string(),
6291 vec![
6292 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
6293 name: Identifier::new("key"),
6294 value: k_ref.clone(),
6295 separator: crate::expressions::NamedArgSeparator::ColonEq,
6296 })),
6297 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
6298 name: Identifier::new("value"),
6299 value: key_value,
6300 separator: crate::expressions::NamedArgSeparator::ColonEq,
6301 })),
6302 ],
6303 )));
6304 let lambda_k = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6305 parameters: vec![k_ident],
6306 body: struct_pack,
6307 colon: false,
6308 parameter_types: Vec::new(),
6309 }));
6310
6311 let list_transform = Expression::Function(Box::new(Function::new(
6312 "LIST_TRANSFORM".to_string(),
6313 vec![list_distinct, lambda_k],
6314 )));
6315
6316 let x_ident = Identifier::new("__x");
6317 let x_ref = Expression::boxed_column(Column {
6318 table: None,
6319 name: x_ident.clone(),
6320 join_mark: false,
6321 trailing_comments: Vec::new(),
6322 span: None,
6323 inferred_type: None,
6324 });
6325 let x_value = Expression::Dot(Box::new(crate::expressions::DotAccess {
6326 this: x_ref,
6327 field: Identifier::new("value"),
6328 }));
6329 let x_value_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6330 this: x_value,
6331 not: false,
6332 postfix_form: false,
6333 }));
6334 let lambda_x = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6335 parameters: vec![x_ident],
6336 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
6337 this: x_value_is_null,
6338 inferred_type: None,
6339 })),
6340 colon: false,
6341 parameter_types: Vec::new(),
6342 }));
6343
6344 let list_filter = Expression::Function(Box::new(Function::new(
6345 "LIST_FILTER".to_string(),
6346 vec![list_transform, lambda_x],
6347 )));
6348 let merged_map = Expression::Function(Box::new(Function::new(
6349 "MAP_FROM_ENTRIES".to_string(),
6350 vec![list_filter],
6351 )));
6352
6353 Ok(Expression::Case(Box::new(Case {
6354 operand: None,
6355 whens: vec![(null_cond, Expression::Null(crate::expressions::Null))],
6356 else_: Some(merged_map),
6357 comments: Vec::new(),
6358 inferred_type: None,
6359 })))
6360 }
6361
6362 "MINHASH" if f.args.len() == 2 => {
6364 let mut args = f.args;
6365 let num_perm = args.remove(0);
6366 let value = args.remove(0);
6367
6368 let num_perm_sql = Self::expr_to_sql(&num_perm);
6369 let value_sql = Self::expr_to_sql(&value);
6370
6371 let template = format!(
6372 "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))",
6373 value = value_sql,
6374 num_perm = num_perm_sql
6375 );
6376
6377 Self::parse_as_subquery(&template)
6378 }
6379
6380 "MINHASH_COMBINE" if f.args.len() == 1 => {
6382 let sig_sql = Self::expr_to_sql(&f.args[0]);
6383 let template = format!(
6384 "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)",
6385 sig = sig_sql
6386 );
6387 Self::parse_as_subquery(&template)
6388 }
6389
6390 "APPROXIMATE_SIMILARITY" if f.args.len() == 1 => {
6392 let sig_sql = Self::expr_to_sql(&f.args[0]);
6393 let template = format!(
6394 "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)",
6395 sig = sig_sql
6396 );
6397 Self::parse_as_subquery(&template)
6398 }
6399
6400 "ARRAYS_ZIP" if !f.args.is_empty() => {
6402 let args = f.args;
6403 let n = args.len();
6404 let is_null = |expr: Expression| {
6405 Expression::IsNull(Box::new(crate::expressions::IsNull {
6406 this: expr,
6407 not: false,
6408 postfix_form: false,
6409 }))
6410 };
6411 let length_of = |expr: Expression| {
6412 Expression::Function(Box::new(Function::new("LENGTH".to_string(), vec![expr])))
6413 };
6414 let eq_zero = |expr: Expression| {
6415 Expression::Eq(Box::new(BinaryOp {
6416 left: expr,
6417 right: Expression::number(0),
6418 left_comments: Vec::new(),
6419 operator_comments: Vec::new(),
6420 trailing_comments: Vec::new(),
6421 inferred_type: None,
6422 }))
6423 };
6424 let and_expr = |left: Expression, right: Expression| {
6425 Expression::And(Box::new(BinaryOp {
6426 left,
6427 right,
6428 left_comments: Vec::new(),
6429 operator_comments: Vec::new(),
6430 trailing_comments: Vec::new(),
6431 inferred_type: None,
6432 }))
6433 };
6434 let or_expr = |left: Expression, right: Expression| {
6435 Expression::Or(Box::new(BinaryOp {
6436 left,
6437 right,
6438 left_comments: Vec::new(),
6439 operator_comments: Vec::new(),
6440 trailing_comments: Vec::new(),
6441 inferred_type: None,
6442 }))
6443 };
6444
6445 let null_cond = args.iter().cloned().map(is_null).reduce(or_expr).unwrap();
6446 let empty_cond = args
6447 .iter()
6448 .cloned()
6449 .map(|a| eq_zero(length_of(a)))
6450 .reduce(and_expr)
6451 .unwrap();
6452
6453 let null_struct = Expression::Struct(Box::new(Struct {
6454 fields: (1..=n)
6455 .map(|i| {
6456 (
6457 Some(format!("${}", i)),
6458 Expression::Null(crate::expressions::Null),
6459 )
6460 })
6461 .collect(),
6462 }));
6463 let empty_result = Expression::Array(Box::new(crate::expressions::Array {
6464 expressions: vec![null_struct],
6465 }));
6466
6467 let range_upper = if n == 1 {
6468 length_of(args[0].clone())
6469 } else {
6470 let length_null_cond = args
6471 .iter()
6472 .cloned()
6473 .map(|a| is_null(length_of(a)))
6474 .reduce(or_expr)
6475 .unwrap();
6476 let greatest_len = Expression::Greatest(Box::new(VarArgFunc {
6477 expressions: args.iter().cloned().map(length_of).collect(),
6478 original_name: None,
6479 inferred_type: None,
6480 }));
6481 Expression::Case(Box::new(Case {
6482 operand: None,
6483 whens: vec![(length_null_cond, Expression::Null(crate::expressions::Null))],
6484 else_: Some(greatest_len),
6485 comments: Vec::new(),
6486 inferred_type: None,
6487 }))
6488 };
6489
6490 let range_expr = Expression::Function(Box::new(Function::new(
6491 "RANGE".to_string(),
6492 vec![Expression::number(0), range_upper],
6493 )));
6494
6495 let i_ident = Identifier::new("__i");
6496 let i_ref = Expression::boxed_column(Column {
6497 table: None,
6498 name: i_ident.clone(),
6499 join_mark: false,
6500 trailing_comments: Vec::new(),
6501 span: None,
6502 inferred_type: None,
6503 });
6504 let i_plus_one = Expression::Add(Box::new(BinaryOp {
6505 left: i_ref,
6506 right: Expression::number(1),
6507 left_comments: Vec::new(),
6508 operator_comments: Vec::new(),
6509 trailing_comments: Vec::new(),
6510 inferred_type: None,
6511 }));
6512 let empty_array = Expression::Array(Box::new(crate::expressions::Array {
6513 expressions: vec![],
6514 }));
6515 let zipped_struct = Expression::Struct(Box::new(Struct {
6516 fields: args
6517 .iter()
6518 .enumerate()
6519 .map(|(i, a)| {
6520 let coalesced = Expression::Coalesce(Box::new(VarArgFunc {
6521 expressions: vec![a.clone(), empty_array.clone()],
6522 original_name: None,
6523 inferred_type: None,
6524 }));
6525 let item =
6526 Expression::Subscript(Box::new(crate::expressions::Subscript {
6527 this: coalesced,
6528 index: i_plus_one.clone(),
6529 }));
6530 (Some(format!("${}", i + 1)), item)
6531 })
6532 .collect(),
6533 }));
6534 let lambda_i = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6535 parameters: vec![i_ident],
6536 body: zipped_struct,
6537 colon: false,
6538 parameter_types: Vec::new(),
6539 }));
6540 let zipped_result = Expression::Function(Box::new(Function::new(
6541 "LIST_TRANSFORM".to_string(),
6542 vec![range_expr, lambda_i],
6543 )));
6544
6545 Ok(Expression::Case(Box::new(Case {
6546 operand: None,
6547 whens: vec![
6548 (null_cond, Expression::Null(crate::expressions::Null)),
6549 (empty_cond, empty_result),
6550 ],
6551 else_: Some(zipped_result),
6552 comments: Vec::new(),
6553 inferred_type: None,
6554 })))
6555 }
6556
6557 "STRTOK" if f.args.len() == 3 => {
6561 let mut args = f.args.into_iter();
6562 let str_arg = args.next().unwrap();
6563 let delim_arg = args.next().unwrap();
6564 let pos_arg = args.next().unwrap();
6565
6566 let empty_str = || Expression::string("".to_string());
6568 let null_expr = || Expression::Null(crate::expressions::Null);
6570
6571 let when1_cond = Expression::And(Box::new(BinaryOp::new(
6573 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6574 Expression::Eq(Box::new(BinaryOp::new(str_arg.clone(), empty_str()))),
6575 )));
6576
6577 let when2_cond = Expression::And(Box::new(BinaryOp::new(
6579 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6580 Expression::Eq(Box::new(BinaryOp::new(
6581 pos_arg.clone(),
6582 Expression::number(1),
6583 ))),
6584 )));
6585
6586 let when3_cond =
6588 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str())));
6589
6590 let when4_cond = Expression::Lt(Box::new(BinaryOp::new(
6592 pos_arg.clone(),
6593 Expression::number(0),
6594 )));
6595
6596 let str_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6598 this: str_arg.clone(),
6599 not: false,
6600 postfix_form: false,
6601 }));
6602 let delim_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6603 this: delim_arg.clone(),
6604 not: false,
6605 postfix_form: false,
6606 }));
6607 let pos_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6608 this: pos_arg.clone(),
6609 not: false,
6610 postfix_form: false,
6611 }));
6612 let when5_cond = Expression::Or(Box::new(BinaryOp::new(
6613 Expression::Or(Box::new(BinaryOp::new(str_is_null, delim_is_null))),
6614 pos_is_null,
6615 )));
6616
6617 let regex_replace = Expression::Function(Box::new(Function::new(
6622 "REGEXP_REPLACE".to_string(),
6623 vec![
6624 delim_arg.clone(),
6625 Expression::string(r"([\[\]^.\-*+?(){}|$\\])".to_string()),
6626 Expression::string(r"\\\1".to_string()),
6627 Expression::string("g".to_string()),
6628 ],
6629 )));
6630
6631 let concat_regex = Expression::DPipe(Box::new(crate::expressions::DPipe {
6633 this: Box::new(Expression::DPipe(Box::new(crate::expressions::DPipe {
6634 this: Box::new(Expression::string("[".to_string())),
6635 expression: Box::new(regex_replace),
6636 safe: None,
6637 }))),
6638 expression: Box::new(Expression::string("]".to_string())),
6639 safe: None,
6640 }));
6641
6642 let inner_case = Expression::Case(Box::new(Case {
6643 operand: None,
6644 whens: vec![(
6645 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6646 empty_str(),
6647 )],
6648 else_: Some(concat_regex),
6649 comments: Vec::new(),
6650 inferred_type: None,
6651 }));
6652
6653 let regexp_split = Expression::Function(Box::new(Function::new(
6655 "REGEXP_SPLIT_TO_ARRAY".to_string(),
6656 vec![str_arg.clone(), inner_case],
6657 )));
6658
6659 let lambda = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6661 parameters: vec![Identifier::new("x".to_string())],
6662 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
6663 this: Expression::Eq(Box::new(BinaryOp::new(
6664 Expression::boxed_column(Column {
6665 table: None,
6666 name: Identifier::new("x".to_string()),
6667 join_mark: false,
6668 trailing_comments: Vec::new(),
6669 span: None,
6670 inferred_type: None,
6671 }),
6672 empty_str(),
6673 ))),
6674 inferred_type: None,
6675 })),
6676 colon: false,
6677 parameter_types: Vec::new(),
6678 }));
6679
6680 let list_filter = Expression::Function(Box::new(Function::new(
6682 "LIST_FILTER".to_string(),
6683 vec![regexp_split, lambda],
6684 )));
6685
6686 let subscripted = Expression::Subscript(Box::new(crate::expressions::Subscript {
6688 this: list_filter,
6689 index: pos_arg.clone(),
6690 }));
6691
6692 Ok(Expression::Case(Box::new(Case {
6693 operand: None,
6694 whens: vec![
6695 (when1_cond, null_expr()),
6696 (when2_cond, str_arg.clone()),
6697 (when3_cond, null_expr()),
6698 (when4_cond, null_expr()),
6699 (when5_cond, null_expr()),
6700 ],
6701 else_: Some(subscripted),
6702 comments: Vec::new(),
6703 inferred_type: None,
6704 })))
6705 }
6706
6707 _ => Ok(Expression::Function(Box::new(f))),
6709 }
6710 }
6711
6712 fn convert_snowflake_date_format(&self, fmt: Expression) -> Expression {
6714 match fmt {
6715 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6716 let Literal::String(s) = lit.as_ref() else {
6717 unreachable!()
6718 };
6719 let converted = Self::snowflake_to_strptime(&s);
6720 Expression::Literal(Box::new(Literal::String(converted)))
6721 }
6722 _ => fmt,
6723 }
6724 }
6725
6726 fn convert_snowflake_time_format(&self, fmt: Expression) -> Expression {
6728 match fmt {
6729 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6730 let Literal::String(s) = lit.as_ref() else {
6731 unreachable!()
6732 };
6733 let converted = Self::snowflake_to_strptime(&s);
6734 Expression::Literal(Box::new(Literal::String(converted)))
6735 }
6736 _ => fmt,
6737 }
6738 }
6739
6740 fn snowflake_to_strptime(s: &str) -> String {
6743 let mut result = String::new();
6744 let chars: Vec<char> = s.chars().collect();
6745 let len = chars.len();
6746 let mut i = 0;
6747 while i < len {
6748 let remaining = &s[i..];
6749 let remaining_upper: String =
6750 remaining.chars().take(8).collect::<String>().to_uppercase();
6751
6752 if remaining_upper.starts_with("HH24MISS") {
6754 result.push_str("%H%M%S");
6755 i += 8;
6756 } else if remaining_upper.starts_with("MMMM") {
6757 result.push_str("%B");
6758 i += 4;
6759 } else if remaining_upper.starts_with("YYYY") {
6760 result.push_str("%Y");
6761 i += 4;
6762 } else if remaining_upper.starts_with("YY") {
6763 result.push_str("%y");
6764 i += 2;
6765 } else if remaining_upper.starts_with("MON") {
6766 result.push_str("%b");
6767 i += 3;
6768 } else if remaining_upper.starts_with("HH24") {
6769 result.push_str("%H");
6770 i += 4;
6771 } else if remaining_upper.starts_with("HH12") {
6772 result.push_str("%I");
6773 i += 4;
6774 } else if remaining_upper.starts_with("HH") {
6775 result.push_str("%I");
6776 i += 2;
6777 } else if remaining_upper.starts_with("MISS") {
6778 result.push_str("%M%S");
6779 i += 4;
6780 } else if remaining_upper.starts_with("MI") {
6781 result.push_str("%M");
6782 i += 2;
6783 } else if remaining_upper.starts_with("MM") {
6784 result.push_str("%m");
6785 i += 2;
6786 } else if remaining_upper.starts_with("DD") {
6787 result.push_str("%d");
6788 i += 2;
6789 } else if remaining_upper.starts_with("DY") {
6790 result.push_str("%a");
6791 i += 2;
6792 } else if remaining_upper.starts_with("SS") {
6793 result.push_str("%S");
6794 i += 2;
6795 } else if remaining_upper.starts_with("FF") {
6796 let ff_pos = i + 2;
6799 if ff_pos < len && chars[ff_pos].is_ascii_digit() {
6800 let digit = chars[ff_pos].to_digit(10).unwrap_or(6);
6801 if digit >= 7 {
6802 result.push_str("%n");
6803 } else {
6804 result.push_str("%f");
6805 }
6806 i += 3; } else {
6808 result.push_str("%f");
6809 i += 2;
6810 }
6811 } else if remaining_upper.starts_with("PM") || remaining_upper.starts_with("AM") {
6812 result.push_str("%p");
6813 i += 2;
6814 } else if remaining_upper.starts_with("TZH") {
6815 result.push_str("%z");
6816 i += 3;
6817 } else if remaining_upper.starts_with("TZM") {
6818 i += 3;
6820 } else {
6821 result.push(chars[i]);
6822 i += 1;
6823 }
6824 }
6825 result
6826 }
6827
6828 fn convert_bq_to_strptime_format(&self, fmt: Expression) -> Expression {
6831 match fmt {
6832 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6833 let Literal::String(s) = lit.as_ref() else {
6834 unreachable!()
6835 };
6836 let converted = s.replace("%E6S", "%S.%f").replace("%E*S", "%S.%f");
6837 Expression::Literal(Box::new(Literal::String(converted)))
6838 }
6839 _ => fmt,
6840 }
6841 }
6842
6843 fn transform_date_part(&self, args: Vec<Expression>) -> Result<Expression> {
6845 let mut args = args;
6846 let unit_expr = args.remove(0);
6847 let date_expr = args.remove(0);
6848 let unit_name = match &unit_expr {
6849 Expression::Column(c) => c.name.name.to_uppercase(),
6850 Expression::Identifier(i) => i.name.to_uppercase(),
6851 Expression::Var(v) => v.this.to_uppercase(),
6852 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6853 let Literal::String(s) = lit.as_ref() else {
6854 unreachable!()
6855 };
6856 s.to_uppercase()
6857 }
6858 _ => {
6859 return Ok(Expression::Function(Box::new(Function::new(
6860 "DATE_PART".to_string(),
6861 vec![unit_expr, date_expr],
6862 ))))
6863 }
6864 };
6865 match unit_name.as_str() {
6866 "EPOCH_SECOND" | "EPOCH" => Ok(Expression::Cast(Box::new(Cast {
6867 this: Expression::Function(Box::new(Function::new(
6868 "EPOCH".to_string(),
6869 vec![date_expr],
6870 ))),
6871 to: DataType::BigInt { length: None },
6872 trailing_comments: Vec::new(),
6873 double_colon_syntax: false,
6874 format: None,
6875 default: None,
6876 inferred_type: None,
6877 }))),
6878 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Ok(Expression::Function(Box::new(
6879 Function::new("EPOCH_MS".to_string(), vec![date_expr]),
6880 ))),
6881 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Ok(Expression::Function(Box::new(
6882 Function::new("EPOCH_US".to_string(), vec![date_expr]),
6883 ))),
6884 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Ok(Expression::Function(Box::new(
6885 Function::new("EPOCH_NS".to_string(), vec![date_expr]),
6886 ))),
6887 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Extract(Box::new(
6888 crate::expressions::ExtractFunc {
6889 this: date_expr,
6890 field: crate::expressions::DateTimeField::Custom("ISODOW".to_string()),
6891 },
6892 ))),
6893 "YEAROFWEEK" | "YEAROFWEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6894 this: Expression::Function(Box::new(Function::new(
6895 "STRFTIME".to_string(),
6896 vec![
6897 date_expr,
6898 Expression::Literal(Box::new(Literal::String("%G".to_string()))),
6899 ],
6900 ))),
6901 to: DataType::Int {
6902 length: None,
6903 integer_spelling: false,
6904 },
6905 trailing_comments: Vec::new(),
6906 double_colon_syntax: false,
6907 format: None,
6908 default: None,
6909 inferred_type: None,
6910 }))),
6911 "WEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6912 this: Expression::Function(Box::new(Function::new(
6913 "STRFTIME".to_string(),
6914 vec![
6915 date_expr,
6916 Expression::Literal(Box::new(Literal::String("%V".to_string()))),
6917 ],
6918 ))),
6919 to: DataType::Int {
6920 length: None,
6921 integer_spelling: false,
6922 },
6923 trailing_comments: Vec::new(),
6924 double_colon_syntax: false,
6925 format: None,
6926 default: None,
6927 inferred_type: None,
6928 }))),
6929 "NANOSECOND" | "NANOSECONDS" | "NS" => Ok(Expression::Cast(Box::new(Cast {
6930 this: Expression::Function(Box::new(Function::new(
6931 "STRFTIME".to_string(),
6932 vec![
6933 Expression::Cast(Box::new(Cast {
6934 this: date_expr,
6935 to: DataType::Custom {
6936 name: "TIMESTAMP_NS".to_string(),
6937 },
6938 trailing_comments: Vec::new(),
6939 double_colon_syntax: false,
6940 format: None,
6941 default: None,
6942 inferred_type: None,
6943 })),
6944 Expression::Literal(Box::new(Literal::String("%n".to_string()))),
6945 ],
6946 ))),
6947 to: DataType::BigInt { length: None },
6948 trailing_comments: Vec::new(),
6949 double_colon_syntax: false,
6950 format: None,
6951 default: None,
6952 inferred_type: None,
6953 }))),
6954 "DAYOFMONTH" => Ok(Expression::Extract(Box::new(
6955 crate::expressions::ExtractFunc {
6956 this: date_expr,
6957 field: crate::expressions::DateTimeField::Day,
6958 },
6959 ))),
6960 _ => {
6961 let field = match unit_name.as_str() {
6962 "YEAR" | "YY" | "YYYY" => crate::expressions::DateTimeField::Year,
6963 "MONTH" | "MON" | "MM" => crate::expressions::DateTimeField::Month,
6964 "DAY" | "DD" | "D" => crate::expressions::DateTimeField::Day,
6965 "HOUR" | "HH" => crate::expressions::DateTimeField::Hour,
6966 "MINUTE" | "MI" | "MIN" => crate::expressions::DateTimeField::Minute,
6967 "SECOND" | "SEC" | "SS" => crate::expressions::DateTimeField::Second,
6968 "MILLISECOND" | "MS" => crate::expressions::DateTimeField::Millisecond,
6969 "MICROSECOND" | "US" => crate::expressions::DateTimeField::Microsecond,
6970 "QUARTER" | "QTR" => crate::expressions::DateTimeField::Quarter,
6971 "WEEK" | "WK" => crate::expressions::DateTimeField::Week,
6972 "DAYOFWEEK" | "DOW" => crate::expressions::DateTimeField::DayOfWeek,
6973 "DAYOFYEAR" | "DOY" => crate::expressions::DateTimeField::DayOfYear,
6974 "TIMEZONE_HOUR" => crate::expressions::DateTimeField::TimezoneHour,
6975 "TIMEZONE_MINUTE" => crate::expressions::DateTimeField::TimezoneMinute,
6976 _ => crate::expressions::DateTimeField::Custom(unit_name),
6977 };
6978 Ok(Expression::Extract(Box::new(
6979 crate::expressions::ExtractFunc {
6980 this: date_expr,
6981 field,
6982 },
6983 )))
6984 }
6985 }
6986 }
6987
6988 fn transform_dateadd(&self, args: Vec<Expression>) -> Result<Expression> {
6990 let mut args = args;
6991 let unit_expr = args.remove(0);
6992 let amount = args.remove(0);
6993 let date = args.remove(0);
6994 let unit_name = match &unit_expr {
6995 Expression::Column(c) => c.name.name.to_uppercase(),
6996 Expression::Identifier(i) => i.name.to_uppercase(),
6997 Expression::Var(v) => v.this.to_uppercase(),
6998 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6999 let Literal::String(s) = lit.as_ref() else {
7000 unreachable!()
7001 };
7002 s.to_uppercase()
7003 }
7004 _ => String::new(),
7005 };
7006 if unit_name == "NANOSECOND" || unit_name == "NS" {
7007 let epoch_ns = Expression::Function(Box::new(Function::new(
7008 "EPOCH_NS".to_string(),
7009 vec![Expression::Cast(Box::new(Cast {
7010 this: date,
7011 to: DataType::Custom {
7012 name: "TIMESTAMP_NS".to_string(),
7013 },
7014 trailing_comments: Vec::new(),
7015 double_colon_syntax: false,
7016 format: None,
7017 default: None,
7018 inferred_type: None,
7019 }))],
7020 )));
7021 return Ok(Expression::Function(Box::new(Function::new(
7022 "MAKE_TIMESTAMP_NS".to_string(),
7023 vec![Expression::Add(Box::new(BinaryOp {
7024 left: epoch_ns,
7025 right: amount,
7026 left_comments: Vec::new(),
7027 operator_comments: Vec::new(),
7028 trailing_comments: Vec::new(),
7029 inferred_type: None,
7030 }))],
7031 ))));
7032 }
7033 let (interval_unit, multiplied_amount) = match unit_name.as_str() {
7034 "YEAR" | "YY" | "YYYY" => (IntervalUnit::Year, amount),
7035 "MONTH" | "MON" | "MM" => (IntervalUnit::Month, amount),
7036 "DAY" | "DD" | "D" => (IntervalUnit::Day, amount),
7037 "HOUR" | "HH" => (IntervalUnit::Hour, amount),
7038 "MINUTE" | "MI" | "MIN" => (IntervalUnit::Minute, amount),
7039 "SECOND" | "SEC" | "SS" => (IntervalUnit::Second, amount),
7040 "MILLISECOND" | "MS" => (IntervalUnit::Millisecond, amount),
7041 "MICROSECOND" | "US" => (IntervalUnit::Microsecond, amount),
7042 "WEEK" | "WK" => (
7043 IntervalUnit::Day,
7044 Expression::Mul(Box::new(BinaryOp {
7045 left: amount,
7046 right: Expression::number(7),
7047 left_comments: Vec::new(),
7048 operator_comments: Vec::new(),
7049 trailing_comments: Vec::new(),
7050 inferred_type: None,
7051 })),
7052 ),
7053 "QUARTER" | "QTR" => (
7054 IntervalUnit::Month,
7055 Expression::Mul(Box::new(BinaryOp {
7056 left: amount,
7057 right: Expression::number(3),
7058 left_comments: Vec::new(),
7059 operator_comments: Vec::new(),
7060 trailing_comments: Vec::new(),
7061 inferred_type: None,
7062 })),
7063 ),
7064 _ => (IntervalUnit::Day, amount),
7065 };
7066 Ok(Expression::Add(Box::new(BinaryOp {
7067 left: date,
7068 right: Expression::Interval(Box::new(Interval {
7069 this: Some(multiplied_amount),
7070 unit: Some(IntervalUnitSpec::Simple {
7071 unit: interval_unit,
7072 use_plural: false,
7073 }),
7074 })),
7075 left_comments: Vec::new(),
7076 operator_comments: Vec::new(),
7077 trailing_comments: Vec::new(),
7078 inferred_type: None,
7079 })))
7080 }
7081
7082 fn transform_datediff(&self, args: Vec<Expression>) -> Result<Expression> {
7084 let mut args = args;
7085 let unit_expr = args.remove(0);
7086 let start = args.remove(0);
7087 let end = args.remove(0);
7088 let unit_name = match &unit_expr {
7089 Expression::Column(c) => c.name.name.to_uppercase(),
7090 Expression::Identifier(i) => i.name.to_uppercase(),
7091 Expression::Var(v) => v.this.to_uppercase(),
7092 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
7093 let Literal::String(s) = lit.as_ref() else {
7094 unreachable!()
7095 };
7096 s.to_uppercase()
7097 }
7098 _ => String::new(),
7099 };
7100 if unit_name == "NANOSECOND" || unit_name == "NS" {
7101 let epoch_end = Expression::Function(Box::new(Function::new(
7102 "EPOCH_NS".to_string(),
7103 vec![Expression::Cast(Box::new(Cast {
7104 this: end,
7105 to: DataType::Custom {
7106 name: "TIMESTAMP_NS".to_string(),
7107 },
7108 trailing_comments: Vec::new(),
7109 double_colon_syntax: false,
7110 format: None,
7111 default: None,
7112 inferred_type: None,
7113 }))],
7114 )));
7115 let epoch_start = Expression::Function(Box::new(Function::new(
7116 "EPOCH_NS".to_string(),
7117 vec![Expression::Cast(Box::new(Cast {
7118 this: start,
7119 to: DataType::Custom {
7120 name: "TIMESTAMP_NS".to_string(),
7121 },
7122 trailing_comments: Vec::new(),
7123 double_colon_syntax: false,
7124 format: None,
7125 default: None,
7126 inferred_type: None,
7127 }))],
7128 )));
7129 return Ok(Expression::Sub(Box::new(BinaryOp {
7130 left: epoch_end,
7131 right: epoch_start,
7132 left_comments: Vec::new(),
7133 operator_comments: Vec::new(),
7134 trailing_comments: Vec::new(),
7135 inferred_type: None,
7136 })));
7137 }
7138 if unit_name == "WEEK" || unit_name == "WK" {
7139 let trunc_start = Expression::Function(Box::new(Function::new(
7140 "DATE_TRUNC".to_string(),
7141 vec![
7142 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7143 Expression::Cast(Box::new(Cast {
7144 this: start,
7145 to: DataType::Date,
7146 trailing_comments: Vec::new(),
7147 double_colon_syntax: false,
7148 format: None,
7149 default: None,
7150 inferred_type: None,
7151 })),
7152 ],
7153 )));
7154 let trunc_end = Expression::Function(Box::new(Function::new(
7155 "DATE_TRUNC".to_string(),
7156 vec![
7157 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7158 Expression::Cast(Box::new(Cast {
7159 this: end,
7160 to: DataType::Date,
7161 trailing_comments: Vec::new(),
7162 double_colon_syntax: false,
7163 format: None,
7164 default: None,
7165 inferred_type: None,
7166 })),
7167 ],
7168 )));
7169 return Ok(Expression::Function(Box::new(Function::new(
7170 "DATE_DIFF".to_string(),
7171 vec![
7172 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7173 trunc_start,
7174 trunc_end,
7175 ],
7176 ))));
7177 }
7178 let cast_if_string = |e: Expression| -> Expression {
7179 match &e {
7180 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
7181 Expression::Cast(Box::new(Cast {
7182 this: e,
7183 to: DataType::Date,
7184 trailing_comments: Vec::new(),
7185 double_colon_syntax: false,
7186 format: None,
7187 default: None,
7188 inferred_type: None,
7189 }))
7190 }
7191 _ => e,
7192 }
7193 };
7194 let start = cast_if_string(start);
7195 let end = cast_if_string(end);
7196 Ok(Expression::Function(Box::new(Function::new(
7197 "DATE_DIFF".to_string(),
7198 vec![
7199 Expression::Literal(Box::new(Literal::String(unit_name))),
7200 start,
7201 end,
7202 ],
7203 ))))
7204 }
7205
7206 fn transform_aggregate_function(
7207 &self,
7208 f: Box<crate::expressions::AggregateFunction>,
7209 ) -> Result<Expression> {
7210 let name_upper = f.name.to_uppercase();
7211 match name_upper.as_str() {
7212 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
7214 Function::new("LISTAGG".to_string(), f.args),
7215 ))),
7216
7217 "LISTAGG" => Ok(Expression::AggregateFunction(f)),
7219
7220 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
7222 Function::new("LISTAGG".to_string(), f.args),
7223 ))),
7224
7225 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
7227 "list".to_string(),
7228 f.args,
7229 )))),
7230
7231 "LOGICAL_OR" if !f.args.is_empty() => {
7233 let arg = f.args.into_iter().next().unwrap();
7234 Ok(Expression::Function(Box::new(Function::new(
7235 "BOOL_OR".to_string(),
7236 vec![Expression::Cast(Box::new(crate::expressions::Cast {
7237 this: arg,
7238 to: crate::expressions::DataType::Boolean,
7239 trailing_comments: Vec::new(),
7240 double_colon_syntax: false,
7241 format: None,
7242 default: None,
7243 inferred_type: None,
7244 }))],
7245 ))))
7246 }
7247
7248 "LOGICAL_AND" if !f.args.is_empty() => {
7250 let arg = f.args.into_iter().next().unwrap();
7251 Ok(Expression::Function(Box::new(Function::new(
7252 "BOOL_AND".to_string(),
7253 vec![Expression::Cast(Box::new(crate::expressions::Cast {
7254 this: arg,
7255 to: crate::expressions::DataType::Boolean,
7256 trailing_comments: Vec::new(),
7257 double_colon_syntax: false,
7258 format: None,
7259 default: None,
7260 inferred_type: None,
7261 }))],
7262 ))))
7263 }
7264
7265 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
7267 "SKEWNESS".to_string(),
7268 f.args,
7269 )))),
7270
7271 "REGR_VALX" if f.args.len() == 2 => {
7273 let mut args = f.args;
7274 let y = args.remove(0);
7275 let x = args.remove(0);
7276 Ok(Expression::Case(Box::new(Case {
7277 operand: None,
7278 whens: vec![(
7279 Expression::IsNull(Box::new(crate::expressions::IsNull {
7280 this: y,
7281 not: false,
7282 postfix_form: false,
7283 })),
7284 Expression::Cast(Box::new(Cast {
7285 this: Expression::Null(crate::expressions::Null),
7286 to: DataType::Double {
7287 precision: None,
7288 scale: None,
7289 },
7290 trailing_comments: Vec::new(),
7291 double_colon_syntax: false,
7292 format: None,
7293 default: None,
7294 inferred_type: None,
7295 })),
7296 )],
7297 else_: Some(x),
7298 comments: Vec::new(),
7299 inferred_type: None,
7300 })))
7301 }
7302
7303 "REGR_VALY" if f.args.len() == 2 => {
7305 let mut args = f.args;
7306 let y = args.remove(0);
7307 let x = args.remove(0);
7308 Ok(Expression::Case(Box::new(Case {
7309 operand: None,
7310 whens: vec![(
7311 Expression::IsNull(Box::new(crate::expressions::IsNull {
7312 this: x,
7313 not: false,
7314 postfix_form: false,
7315 })),
7316 Expression::Cast(Box::new(Cast {
7317 this: Expression::Null(crate::expressions::Null),
7318 to: DataType::Double {
7319 precision: None,
7320 scale: None,
7321 },
7322 trailing_comments: Vec::new(),
7323 double_colon_syntax: false,
7324 format: None,
7325 default: None,
7326 inferred_type: None,
7327 })),
7328 )],
7329 else_: Some(y),
7330 comments: Vec::new(),
7331 inferred_type: None,
7332 })))
7333 }
7334
7335 "BOOLAND_AGG" if !f.args.is_empty() => {
7337 let arg = f.args.into_iter().next().unwrap();
7338 Ok(Expression::Function(Box::new(Function::new(
7339 "BOOL_AND".to_string(),
7340 vec![Expression::Cast(Box::new(Cast {
7341 this: arg,
7342 to: DataType::Boolean,
7343 trailing_comments: Vec::new(),
7344 double_colon_syntax: false,
7345 format: None,
7346 default: None,
7347 inferred_type: None,
7348 }))],
7349 ))))
7350 }
7351
7352 "BOOLOR_AGG" if !f.args.is_empty() => {
7354 let arg = f.args.into_iter().next().unwrap();
7355 Ok(Expression::Function(Box::new(Function::new(
7356 "BOOL_OR".to_string(),
7357 vec![Expression::Cast(Box::new(Cast {
7358 this: arg,
7359 to: DataType::Boolean,
7360 trailing_comments: Vec::new(),
7361 double_colon_syntax: false,
7362 format: None,
7363 default: None,
7364 inferred_type: None,
7365 }))],
7366 ))))
7367 }
7368
7369 "BOOLXOR_AGG" if !f.args.is_empty() => {
7371 let arg = f.args.into_iter().next().unwrap();
7372 Ok(Expression::Eq(Box::new(BinaryOp {
7373 left: Expression::Function(Box::new(Function::new(
7374 "COUNT_IF".to_string(),
7375 vec![Expression::Cast(Box::new(Cast {
7376 this: arg,
7377 to: DataType::Boolean,
7378 trailing_comments: Vec::new(),
7379 double_colon_syntax: false,
7380 format: None,
7381 default: None,
7382 inferred_type: None,
7383 }))],
7384 ))),
7385 right: Expression::number(1),
7386 left_comments: Vec::new(),
7387 operator_comments: Vec::new(),
7388 trailing_comments: Vec::new(),
7389 inferred_type: None,
7390 })))
7391 }
7392
7393 "MAX_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
7395 crate::expressions::AggregateFunction {
7396 name: "ARG_MAX".to_string(),
7397 ..(*f)
7398 },
7399 ))),
7400
7401 "MIN_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
7403 crate::expressions::AggregateFunction {
7404 name: "ARG_MIN".to_string(),
7405 ..(*f)
7406 },
7407 ))),
7408
7409 "CORR" if f.args.len() == 2 => Ok(Expression::AggregateFunction(f)),
7411
7412 "BITMAP_CONSTRUCT_AGG" if f.args.len() == 1 => {
7414 let v_sql = Self::expr_to_sql(&f.args[0]);
7415
7416 let template = format!(
7417 "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))",
7418 v = v_sql
7419 );
7420
7421 Self::parse_as_subquery(&template)
7422 }
7423
7424 _ => Ok(Expression::AggregateFunction(f)),
7426 }
7427 }
7428
7429 fn convert_format_to_duckdb(expr: &Expression) -> Expression {
7433 if let Expression::Literal(lit) = expr {
7434 if let Literal::String(s) = lit.as_ref() {
7435 let duckdb_fmt = Self::presto_to_duckdb_format(s);
7436 Expression::Literal(Box::new(Literal::String(duckdb_fmt)))
7437 } else {
7438 expr.clone()
7439 }
7440 } else {
7441 expr.clone()
7442 }
7443 }
7444
7445 fn presto_to_duckdb_format(fmt: &str) -> String {
7447 let mut result = String::new();
7448 let chars: Vec<char> = fmt.chars().collect();
7449 let mut i = 0;
7450 while i < chars.len() {
7451 if chars[i] == '%' && i + 1 < chars.len() {
7452 match chars[i + 1] {
7453 'i' => {
7454 result.push_str("%M");
7456 i += 2;
7457 }
7458 'T' => {
7459 result.push_str("%H:%M:%S");
7461 i += 2;
7462 }
7463 'F' => {
7464 result.push_str("%Y-%m-%d");
7466 i += 2;
7467 }
7468 _ => {
7469 result.push('%');
7470 result.push(chars[i + 1]);
7471 i += 2;
7472 }
7473 }
7474 } else {
7475 result.push(chars[i]);
7476 i += 1;
7477 }
7478 }
7479 result
7480 }
7481}
7482
7483#[cfg(test)]
7484mod tests {
7485 use super::*;
7486 use crate::dialects::Dialect;
7487
7488 fn transpile_to_duckdb(sql: &str) -> String {
7489 let dialect = Dialect::get(DialectType::Generic);
7490 let result = dialect
7491 .transpile(sql, DialectType::DuckDB)
7492 .expect("Transpile failed");
7493 result[0].clone()
7494 }
7495
7496 #[test]
7497 fn test_ifnull_to_coalesce() {
7498 let result = transpile_to_duckdb("SELECT IFNULL(a, b)");
7499 assert!(
7500 result.contains("COALESCE"),
7501 "Expected COALESCE, got: {}",
7502 result
7503 );
7504 }
7505
7506 #[test]
7507 fn test_nvl_to_coalesce() {
7508 let result = transpile_to_duckdb("SELECT NVL(a, b)");
7509 assert!(
7510 result.contains("COALESCE"),
7511 "Expected COALESCE, got: {}",
7512 result
7513 );
7514 }
7515
7516 #[test]
7517 fn test_basic_select() {
7518 let result = transpile_to_duckdb("SELECT a, b FROM users WHERE id = 1");
7519 assert!(result.contains("SELECT"));
7520 assert!(result.contains("FROM users"));
7521 }
7522
7523 #[test]
7524 fn test_group_concat_to_listagg() {
7525 let result = transpile_to_duckdb("SELECT GROUP_CONCAT(name)");
7526 assert!(
7527 result.contains("LISTAGG"),
7528 "Expected LISTAGG, got: {}",
7529 result
7530 );
7531 }
7532
7533 #[test]
7534 fn test_listagg_preserved() {
7535 let result = transpile_to_duckdb("SELECT LISTAGG(name)");
7536 assert!(
7537 result.contains("LISTAGG"),
7538 "Expected LISTAGG, got: {}",
7539 result
7540 );
7541 }
7542
7543 #[test]
7544 fn test_date_format_to_strftime() {
7545 let result = transpile_to_duckdb("SELECT DATE_FORMAT(d, '%Y-%m-%d')");
7546 assert!(
7548 result.to_uppercase().contains("STRFTIME"),
7549 "Expected STRFTIME, got: {}",
7550 result
7551 );
7552 }
7553
7554 #[test]
7555 fn test_regexp_like_to_regexp_matches() {
7556 let result = transpile_to_duckdb("SELECT REGEXP_LIKE(name, 'pattern')");
7557 assert!(
7559 result.to_uppercase().contains("REGEXP_MATCHES"),
7560 "Expected REGEXP_MATCHES, got: {}",
7561 result
7562 );
7563 }
7564
7565 #[test]
7566 fn test_double_quote_identifiers() {
7567 let dialect = Dialect::get(DialectType::DuckDB);
7569 let config = dialect.generator_config();
7570 assert_eq!(config.identifier_quote, '"');
7571 }
7572
7573 fn duckdb_identity(sql: &str) -> String {
7575 let dialect = Dialect::get(DialectType::DuckDB);
7576 let ast = dialect.parse(sql).expect("Parse failed");
7577 let transformed = dialect.transform(ast[0].clone()).expect("Transform failed");
7578 dialect.generate(&transformed).expect("Generate failed")
7579 }
7580
7581 #[test]
7582 fn test_interval_quoting() {
7583 let result = duckdb_identity("SELECT DATE_ADD(CAST('2020-01-01' AS DATE), INTERVAL 1 DAY)");
7585 assert_eq!(
7586 result, "SELECT CAST('2020-01-01' AS DATE) + INTERVAL '1' DAY",
7587 "Interval value should be quoted as string"
7588 );
7589 }
7590
7591 #[test]
7592 fn test_struct_pack_to_curly_brace() {
7593 let result = duckdb_identity("CAST([STRUCT_PACK(a := 1)] AS STRUCT(a BIGINT)[])");
7595 assert_eq!(
7596 result, "CAST([{'a': 1}] AS STRUCT(a BIGINT)[])",
7597 "STRUCT_PACK should be transformed to curly brace notation"
7598 );
7599 }
7600
7601 #[test]
7602 fn test_struct_pack_nested() {
7603 let result = duckdb_identity("CAST([[STRUCT_PACK(a := 1)]] AS STRUCT(a BIGINT)[][])");
7605 assert_eq!(
7606 result, "CAST([[{'a': 1}]] AS STRUCT(a BIGINT)[][])",
7607 "Nested STRUCT_PACK should be transformed"
7608 );
7609 }
7610
7611 #[test]
7612 fn test_struct_pack_cast() {
7613 let result = duckdb_identity("STRUCT_PACK(a := 'b')::json");
7615 assert_eq!(
7616 result, "CAST({'a': 'b'} AS JSON)",
7617 "STRUCT_PACK with cast should be transformed"
7618 );
7619 }
7620
7621 #[test]
7622 fn test_list_value_to_bracket() {
7623 let result = duckdb_identity("SELECT LIST_VALUE(1)[i]");
7625 assert_eq!(
7626 result, "SELECT [1][i]",
7627 "LIST_VALUE should be transformed to bracket notation"
7628 );
7629 }
7630
7631 #[test]
7632 fn test_list_value_in_struct_literal() {
7633 let result = duckdb_identity("{'x': LIST_VALUE(1)[i]}");
7635 assert_eq!(
7636 result, "{'x': [1][i]}",
7637 "LIST_VALUE inside struct literal should be transformed"
7638 );
7639 }
7640
7641 #[test]
7642 fn test_struct_pack_simple() {
7643 let result = duckdb_identity("SELECT STRUCT_PACK(a := 1)");
7645 eprintln!("STRUCT_PACK result: {}", result);
7646 assert!(
7647 result.contains("{"),
7648 "Expected curly brace, got: {}",
7649 result
7650 );
7651 }
7652
7653 #[test]
7654 fn test_not_in_position() {
7655 let result = duckdb_identity(
7658 "SELECT col FROM t WHERE JSON_EXTRACT_STRING(col, '$.id') NOT IN ('b')",
7659 );
7660 assert_eq!(
7661 result, "SELECT col FROM t WHERE NOT (col ->> '$.id') IN ('b')",
7662 "NOT IN should have NOT moved outside and JSON expression wrapped"
7663 );
7664 }
7665
7666 #[test]
7667 fn test_unnest_comma_join_to_join_on_true() {
7668 let result = duckdb_identity(
7670 "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",
7671 );
7672 assert_eq!(
7673 result,
7674 "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",
7675 "Comma-join with UNNEST should become JOIN ON TRUE"
7676 );
7677 }
7678}