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,
17 JSONPathKey, JSONPathRoot, JSONPathSubscript, JsonExtractFunc, Literal, Null, Paren, Struct,
18 Subquery, 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 "UUID_STRING" => Ok(Expression::Function(Box::new(Function::new(
3470 "UUID".to_string(),
3471 vec![],
3472 )))),
3473 "ENDSWITH" => Ok(Expression::Function(Box::new(Function::new(
3474 "ENDS_WITH".to_string(),
3475 f.args,
3476 )))),
3477 "REGEXP_REPLACE" if f.args.len() == 2 => {
3481 let mut args = f.args;
3483 args.push(Expression::Literal(Box::new(
3484 Literal::String(String::new()),
3485 )));
3486 Ok(Expression::Function(Box::new(Function::new(
3487 "REGEXP_REPLACE".to_string(),
3488 args,
3489 ))))
3490 }
3491 "DIV0" if f.args.len() == 2 => {
3492 let mut args = f.args;
3493 let a = args.remove(0);
3494 let b = args.remove(0);
3495 Ok(Expression::Case(Box::new(Case {
3496 operand: None,
3497 whens: vec![(
3498 Expression::And(Box::new(BinaryOp {
3499 left: Expression::Eq(Box::new(BinaryOp {
3500 left: b.clone(),
3501 right: Expression::number(0),
3502 left_comments: Vec::new(),
3503 operator_comments: Vec::new(),
3504 trailing_comments: Vec::new(),
3505 inferred_type: None,
3506 })),
3507 right: Expression::Not(Box::new(crate::expressions::UnaryOp {
3508 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3509 this: a.clone(),
3510 not: false,
3511 postfix_form: false,
3512 })),
3513 inferred_type: None,
3514 })),
3515 left_comments: Vec::new(),
3516 operator_comments: Vec::new(),
3517 trailing_comments: Vec::new(),
3518 inferred_type: None,
3519 })),
3520 Expression::number(0),
3521 )],
3522 else_: Some(Expression::Div(Box::new(BinaryOp {
3523 left: a,
3524 right: b,
3525 left_comments: Vec::new(),
3526 operator_comments: Vec::new(),
3527 trailing_comments: Vec::new(),
3528 inferred_type: None,
3529 }))),
3530 comments: Vec::new(),
3531 inferred_type: None,
3532 })))
3533 }
3534 "DIV0NULL" if f.args.len() == 2 => {
3535 let mut args = f.args;
3536 let a = args.remove(0);
3537 let b = args.remove(0);
3538 Ok(Expression::Case(Box::new(Case {
3539 operand: None,
3540 whens: vec![(
3541 Expression::Or(Box::new(BinaryOp {
3542 left: Expression::Eq(Box::new(BinaryOp {
3543 left: b.clone(),
3544 right: Expression::number(0),
3545 left_comments: Vec::new(),
3546 operator_comments: Vec::new(),
3547 trailing_comments: Vec::new(),
3548 inferred_type: None,
3549 })),
3550 right: Expression::IsNull(Box::new(crate::expressions::IsNull {
3551 this: b.clone(),
3552 not: false,
3553 postfix_form: false,
3554 })),
3555 left_comments: Vec::new(),
3556 operator_comments: Vec::new(),
3557 trailing_comments: Vec::new(),
3558 inferred_type: None,
3559 })),
3560 Expression::number(0),
3561 )],
3562 else_: Some(Expression::Div(Box::new(BinaryOp {
3563 left: a,
3564 right: b,
3565 left_comments: Vec::new(),
3566 operator_comments: Vec::new(),
3567 trailing_comments: Vec::new(),
3568 inferred_type: None,
3569 }))),
3570 comments: Vec::new(),
3571 inferred_type: None,
3572 })))
3573 }
3574 "ZEROIFNULL" if f.args.len() == 1 => {
3575 let x = f.args.into_iter().next().unwrap();
3576 Ok(Expression::Case(Box::new(Case {
3577 operand: None,
3578 whens: vec![(
3579 Expression::IsNull(Box::new(crate::expressions::IsNull {
3580 this: x.clone(),
3581 not: false,
3582 postfix_form: false,
3583 })),
3584 Expression::number(0),
3585 )],
3586 else_: Some(x),
3587 comments: Vec::new(),
3588 inferred_type: None,
3589 })))
3590 }
3591 "NULLIFZERO" 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::Eq(Box::new(BinaryOp {
3597 left: x.clone(),
3598 right: Expression::number(0),
3599 left_comments: Vec::new(),
3600 operator_comments: Vec::new(),
3601 trailing_comments: Vec::new(),
3602 inferred_type: None,
3603 })),
3604 Expression::Null(crate::expressions::Null),
3605 )],
3606 else_: Some(x),
3607 comments: Vec::new(),
3608 inferred_type: None,
3609 })))
3610 }
3611 "TO_DOUBLE" if f.args.len() == 1 => {
3612 let arg = f.args.into_iter().next().unwrap();
3613 Ok(Expression::Cast(Box::new(Cast {
3614 this: arg,
3615 to: DataType::Double {
3616 precision: None,
3617 scale: None,
3618 },
3619 trailing_comments: Vec::new(),
3620 double_colon_syntax: false,
3621 format: None,
3622 default: None,
3623 inferred_type: None,
3624 })))
3625 }
3626 "DATE" if f.args.len() == 1 => {
3627 let arg = f.args.into_iter().next().unwrap();
3628 Ok(Expression::Cast(Box::new(Cast {
3629 this: arg,
3630 to: DataType::Date,
3631 trailing_comments: Vec::new(),
3632 double_colon_syntax: false,
3633 format: None,
3634 default: None,
3635 inferred_type: None,
3636 })))
3637 }
3638 "DATE" if f.args.len() == 2 => {
3639 let mut args = f.args;
3640 let value = args.remove(0);
3641 let fmt = self.convert_snowflake_date_format(args.remove(0));
3642 Ok(Expression::Cast(Box::new(Cast {
3643 this: Expression::Function(Box::new(Function::new(
3644 "STRPTIME".to_string(),
3645 vec![value, fmt],
3646 ))),
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 "SYSDATE" => Ok(Expression::AtTimeZone(Box::new(
3656 crate::expressions::AtTimeZone {
3657 this: Expression::CurrentTimestamp(crate::expressions::CurrentTimestamp {
3658 precision: None,
3659 sysdate: false,
3660 }),
3661 zone: Expression::Literal(Box::new(Literal::String("UTC".to_string()))),
3662 },
3663 ))),
3664 "HEX_DECODE_BINARY" => Ok(Expression::Function(Box::new(Function::new(
3665 "UNHEX".to_string(),
3666 f.args,
3667 )))),
3668 "CONVERT_TIMEZONE" if f.args.len() == 3 => {
3669 let mut args = f.args;
3670 let src_tz = args.remove(0);
3671 let tgt_tz = args.remove(0);
3672 let ts = args.remove(0);
3673 let cast_ts = Expression::Cast(Box::new(Cast {
3674 this: ts,
3675 to: DataType::Timestamp {
3676 precision: None,
3677 timezone: false,
3678 },
3679 trailing_comments: Vec::new(),
3680 double_colon_syntax: false,
3681 format: None,
3682 default: None,
3683 inferred_type: None,
3684 }));
3685 Ok(Expression::AtTimeZone(Box::new(
3686 crate::expressions::AtTimeZone {
3687 this: Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone {
3688 this: cast_ts,
3689 zone: src_tz,
3690 })),
3691 zone: tgt_tz,
3692 },
3693 )))
3694 }
3695 "CONVERT_TIMEZONE" if f.args.len() == 2 => {
3696 let mut args = f.args;
3697 let tgt_tz = args.remove(0);
3698 let ts = args.remove(0);
3699 let cast_ts = Expression::Cast(Box::new(Cast {
3700 this: ts,
3701 to: DataType::Timestamp {
3702 precision: None,
3703 timezone: false,
3704 },
3705 trailing_comments: Vec::new(),
3706 double_colon_syntax: false,
3707 format: None,
3708 default: None,
3709 inferred_type: None,
3710 }));
3711 Ok(Expression::AtTimeZone(Box::new(
3712 crate::expressions::AtTimeZone {
3713 this: cast_ts,
3714 zone: tgt_tz,
3715 },
3716 )))
3717 }
3718 "DATE_PART" | "DATEPART" if f.args.len() == 2 => self.transform_date_part(f.args),
3719 "DATEADD" | "TIMEADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3720 "TIMESTAMPADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3721 "DATEDIFF" | "TIMEDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3722 "TIMESTAMPDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3723 "CORR" if f.args.len() == 2 => {
3724 Ok(Expression::Function(Box::new(f)))
3726 }
3727 "TO_TIMESTAMP" | "TO_TIMESTAMP_NTZ" if f.args.len() == 2 => {
3728 let mut args = f.args;
3729 let value = args.remove(0);
3730 let second_arg = args.remove(0);
3731 match &second_arg {
3732 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => Ok(
3733 Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone {
3734 this: Expression::Function(Box::new(Function::new(
3735 "TO_TIMESTAMP".to_string(),
3736 vec![Expression::Div(Box::new(BinaryOp {
3737 left: value,
3738 right: Expression::Function(Box::new(Function::new(
3739 "POWER".to_string(),
3740 vec![Expression::number(10), second_arg],
3741 ))),
3742 left_comments: Vec::new(),
3743 operator_comments: Vec::new(),
3744 trailing_comments: Vec::new(),
3745 inferred_type: None,
3746 }))],
3747 ))),
3748 zone: Expression::Literal(Box::new(Literal::String("UTC".to_string()))),
3749 })),
3750 ),
3751 _ => {
3752 let fmt = self.convert_snowflake_time_format(second_arg);
3753 Ok(Expression::Function(Box::new(Function::new(
3754 "STRPTIME".to_string(),
3755 vec![value, fmt],
3756 ))))
3757 }
3758 }
3759 }
3760 "TO_TIME" if f.args.len() == 1 => {
3761 let arg = f.args.into_iter().next().unwrap();
3762 Ok(Expression::Cast(Box::new(Cast {
3763 this: arg,
3764 to: DataType::Time {
3765 precision: None,
3766 timezone: false,
3767 },
3768 trailing_comments: Vec::new(),
3769 double_colon_syntax: false,
3770 format: None,
3771 default: None,
3772 inferred_type: None,
3773 })))
3774 }
3775 "TO_TIME" if f.args.len() == 2 => {
3776 let mut args = f.args;
3777 let value = args.remove(0);
3778 let fmt = self.convert_snowflake_time_format(args.remove(0));
3779 Ok(Expression::Cast(Box::new(Cast {
3780 this: Expression::Function(Box::new(Function::new(
3781 "STRPTIME".to_string(),
3782 vec![value, fmt],
3783 ))),
3784 to: DataType::Time {
3785 precision: None,
3786 timezone: false,
3787 },
3788 trailing_comments: Vec::new(),
3789 double_colon_syntax: false,
3790 format: None,
3791 default: None,
3792 inferred_type: None,
3793 })))
3794 }
3795 "TO_DATE" if f.args.len() == 2 => {
3796 let mut args = f.args;
3797 let value = args.remove(0);
3798 let fmt = self.convert_snowflake_date_format(args.remove(0));
3799 Ok(Expression::Cast(Box::new(Cast {
3800 this: Expression::Function(Box::new(Function::new(
3801 "STRPTIME".to_string(),
3802 vec![value, fmt],
3803 ))),
3804 to: DataType::Date,
3805 trailing_comments: Vec::new(),
3806 double_colon_syntax: false,
3807 format: None,
3808 default: None,
3809 inferred_type: None,
3810 })))
3811 }
3812 "SAFE_DIVIDE" if f.args.len() == 2 => {
3816 let mut args = f.args;
3817 let x = args.remove(0);
3818 let y = args.remove(0);
3819 Ok(Expression::Case(Box::new(Case {
3820 operand: None,
3821 whens: vec![(
3822 Expression::Neq(Box::new(BinaryOp {
3823 left: y.clone(),
3824 right: Expression::number(0),
3825 left_comments: Vec::new(),
3826 operator_comments: Vec::new(),
3827 trailing_comments: Vec::new(),
3828 inferred_type: None,
3829 })),
3830 Expression::Div(Box::new(BinaryOp {
3831 left: x,
3832 right: y,
3833 left_comments: Vec::new(),
3834 operator_comments: Vec::new(),
3835 trailing_comments: Vec::new(),
3836 inferred_type: None,
3837 })),
3838 )],
3839 else_: Some(Expression::Null(crate::expressions::Null)),
3840 comments: Vec::new(),
3841 inferred_type: None,
3842 })))
3843 }
3844
3845 "TO_HEX" if f.args.len() == 1 => {
3847 let arg = f.args.into_iter().next().unwrap();
3848 Ok(Expression::Lower(Box::new(UnaryFunc::new(
3849 Expression::Function(Box::new(Function::new("HEX".to_string(), vec![arg]))),
3850 ))))
3851 }
3852
3853 "EDIT_DISTANCE" if f.args.len() >= 2 => {
3855 let mut args = f.args;
3857 let a = args.remove(0);
3858 let b = args.remove(0);
3859 Ok(Expression::Function(Box::new(Function::new(
3860 "LEVENSHTEIN".to_string(),
3861 vec![a, b],
3862 ))))
3863 }
3864
3865 "UNIX_DATE" if f.args.len() == 1 => {
3867 let arg = f.args.into_iter().next().unwrap();
3868 Ok(Expression::Function(Box::new(Function::new(
3869 "DATE_DIFF".to_string(),
3870 vec![
3871 Expression::Literal(Box::new(Literal::String("DAY".to_string()))),
3872 Expression::Cast(Box::new(Cast {
3873 this: Expression::Literal(Box::new(Literal::String(
3874 "1970-01-01".to_string(),
3875 ))),
3876 to: DataType::Date,
3877 trailing_comments: Vec::new(),
3878 double_colon_syntax: false,
3879 format: None,
3880 default: None,
3881 inferred_type: None,
3882 })),
3883 arg,
3884 ],
3885 ))))
3886 }
3887
3888 "TIMESTAMP" if f.args.len() == 1 => {
3890 let arg = f.args.into_iter().next().unwrap();
3891 Ok(Expression::Cast(Box::new(Cast {
3892 this: arg,
3893 to: DataType::Custom {
3894 name: "TIMESTAMPTZ".to_string(),
3895 },
3896 trailing_comments: Vec::new(),
3897 double_colon_syntax: false,
3898 format: None,
3899 default: None,
3900 inferred_type: None,
3901 })))
3902 }
3903
3904 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3906 "MAKE_TIME".to_string(),
3907 f.args,
3908 )))),
3909
3910 "DATE" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3912 "MAKE_DATE".to_string(),
3913 f.args,
3914 )))),
3915
3916 "DATETIME" if f.args.len() == 6 => Ok(Expression::Function(Box::new(Function::new(
3918 "MAKE_TIMESTAMP".to_string(),
3919 f.args,
3920 )))),
3921
3922 "PARSE_TIMESTAMP" if f.args.len() >= 2 => {
3924 let mut args = f.args;
3925 let fmt = args.remove(0);
3926 let value = args.remove(0);
3927 let duckdb_fmt = self.convert_bq_to_strptime_format(fmt);
3929 Ok(Expression::Function(Box::new(Function::new(
3930 "STRPTIME".to_string(),
3931 vec![value, duckdb_fmt],
3932 ))))
3933 }
3934
3935 "BOOLAND" if f.args.len() == 2 => {
3937 let mut args = f.args;
3938 let a = args.remove(0);
3939 let b = args.remove(0);
3940 let ra = Expression::Function(Box::new(Function::new(
3941 "ROUND".to_string(),
3942 vec![a, Expression::number(0)],
3943 )));
3944 let rb = Expression::Function(Box::new(Function::new(
3945 "ROUND".to_string(),
3946 vec![b, Expression::number(0)],
3947 )));
3948 Ok(Expression::Paren(Box::new(Paren {
3949 this: Expression::And(Box::new(BinaryOp {
3950 left: Expression::Paren(Box::new(Paren {
3951 this: ra,
3952 trailing_comments: Vec::new(),
3953 })),
3954 right: Expression::Paren(Box::new(Paren {
3955 this: rb,
3956 trailing_comments: Vec::new(),
3957 })),
3958 left_comments: Vec::new(),
3959 operator_comments: Vec::new(),
3960 trailing_comments: Vec::new(),
3961 inferred_type: None,
3962 })),
3963 trailing_comments: Vec::new(),
3964 })))
3965 }
3966
3967 "BOOLOR" if f.args.len() == 2 => {
3969 let mut args = f.args;
3970 let a = args.remove(0);
3971 let b = args.remove(0);
3972 let ra = Expression::Function(Box::new(Function::new(
3973 "ROUND".to_string(),
3974 vec![a, Expression::number(0)],
3975 )));
3976 let rb = Expression::Function(Box::new(Function::new(
3977 "ROUND".to_string(),
3978 vec![b, Expression::number(0)],
3979 )));
3980 Ok(Expression::Paren(Box::new(Paren {
3981 this: Expression::Or(Box::new(BinaryOp {
3982 left: Expression::Paren(Box::new(Paren {
3983 this: ra,
3984 trailing_comments: Vec::new(),
3985 })),
3986 right: Expression::Paren(Box::new(Paren {
3987 this: rb,
3988 trailing_comments: Vec::new(),
3989 })),
3990 left_comments: Vec::new(),
3991 operator_comments: Vec::new(),
3992 trailing_comments: Vec::new(),
3993 inferred_type: None,
3994 })),
3995 trailing_comments: Vec::new(),
3996 })))
3997 }
3998
3999 "BOOLXOR" if f.args.len() == 2 => {
4001 let mut args = f.args;
4002 let a = args.remove(0);
4003 let b = args.remove(0);
4004 let ra = Expression::Function(Box::new(Function::new(
4005 "ROUND".to_string(),
4006 vec![a, Expression::number(0)],
4007 )));
4008 let rb = Expression::Function(Box::new(Function::new(
4009 "ROUND".to_string(),
4010 vec![b, Expression::number(0)],
4011 )));
4012 let not_rb = Expression::Not(Box::new(crate::expressions::UnaryOp {
4014 this: rb.clone(),
4015 inferred_type: None,
4016 }));
4017 let not_ra = Expression::Not(Box::new(crate::expressions::UnaryOp {
4018 this: ra.clone(),
4019 inferred_type: None,
4020 }));
4021 let left_and = Expression::And(Box::new(BinaryOp {
4022 left: ra,
4023 right: Expression::Paren(Box::new(Paren {
4024 this: not_rb,
4025 trailing_comments: Vec::new(),
4026 })),
4027 left_comments: Vec::new(),
4028 operator_comments: Vec::new(),
4029 trailing_comments: Vec::new(),
4030 inferred_type: None,
4031 }));
4032 let right_and = Expression::And(Box::new(BinaryOp {
4033 left: Expression::Paren(Box::new(Paren {
4034 this: not_ra,
4035 trailing_comments: Vec::new(),
4036 })),
4037 right: rb,
4038 left_comments: Vec::new(),
4039 operator_comments: Vec::new(),
4040 trailing_comments: Vec::new(),
4041 inferred_type: None,
4042 }));
4043 Ok(Expression::Or(Box::new(BinaryOp {
4044 left: Expression::Paren(Box::new(Paren {
4045 this: left_and,
4046 trailing_comments: Vec::new(),
4047 })),
4048 right: Expression::Paren(Box::new(Paren {
4049 this: right_and,
4050 trailing_comments: Vec::new(),
4051 })),
4052 left_comments: Vec::new(),
4053 operator_comments: Vec::new(),
4054 trailing_comments: Vec::new(),
4055 inferred_type: None,
4056 })))
4057 }
4058
4059 "DECODE" if f.args.len() >= 3 => {
4062 let mut args = f.args;
4063 let expr = args.remove(0);
4064 let mut whens = Vec::new();
4065 let mut else_expr = None;
4066 while args.len() >= 2 {
4067 let search = args.remove(0);
4068 let result = args.remove(0);
4069 let condition = if matches!(&search, Expression::Null(_)) {
4071 Expression::IsNull(Box::new(crate::expressions::IsNull {
4072 this: expr.clone(),
4073 not: false,
4074 postfix_form: false,
4075 }))
4076 } else {
4077 Expression::Eq(Box::new(BinaryOp {
4078 left: expr.clone(),
4079 right: search,
4080 left_comments: Vec::new(),
4081 operator_comments: Vec::new(),
4082 trailing_comments: Vec::new(),
4083 inferred_type: None,
4084 }))
4085 };
4086 whens.push((condition, result));
4087 }
4088 if !args.is_empty() {
4089 else_expr = Some(args.remove(0));
4090 }
4091 Ok(Expression::Case(Box::new(Case {
4092 operand: None,
4093 whens,
4094 else_: else_expr,
4095 comments: Vec::new(),
4096 inferred_type: None,
4097 })))
4098 }
4099
4100 "TRY_TO_BOOLEAN" if f.args.len() == 1 => {
4102 let arg = f.args.into_iter().next().unwrap();
4103 let cast_text = Expression::Cast(Box::new(Cast {
4104 this: arg.clone(),
4105 to: DataType::Text,
4106 trailing_comments: Vec::new(),
4107 double_colon_syntax: false,
4108 format: None,
4109 default: None,
4110 inferred_type: None,
4111 }));
4112 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
4113 Ok(Expression::Case(Box::new(Case {
4114 operand: None,
4115 whens: vec![
4116 (
4117 Expression::Eq(Box::new(BinaryOp {
4118 left: upper_text.clone(),
4119 right: Expression::Literal(Box::new(Literal::String(
4120 "ON".to_string(),
4121 ))),
4122 left_comments: Vec::new(),
4123 operator_comments: Vec::new(),
4124 trailing_comments: Vec::new(),
4125 inferred_type: None,
4126 })),
4127 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
4128 ),
4129 (
4130 Expression::Eq(Box::new(BinaryOp {
4131 left: upper_text,
4132 right: Expression::Literal(Box::new(Literal::String(
4133 "OFF".to_string(),
4134 ))),
4135 left_comments: Vec::new(),
4136 operator_comments: Vec::new(),
4137 trailing_comments: Vec::new(),
4138 inferred_type: None,
4139 })),
4140 Expression::Boolean(crate::expressions::BooleanLiteral {
4141 value: false,
4142 }),
4143 ),
4144 ],
4145 else_: Some(Expression::TryCast(Box::new(Cast {
4146 this: arg,
4147 to: DataType::Boolean,
4148 trailing_comments: Vec::new(),
4149 double_colon_syntax: false,
4150 format: None,
4151 default: None,
4152 inferred_type: None,
4153 }))),
4154 comments: Vec::new(),
4155 inferred_type: None,
4156 })))
4157 }
4158
4159 "TO_BOOLEAN" if f.args.len() == 1 => {
4161 let arg = f.args.into_iter().next().unwrap();
4162 let cast_text = Expression::Cast(Box::new(Cast {
4163 this: arg.clone(),
4164 to: DataType::Text,
4165 trailing_comments: Vec::new(),
4166 double_colon_syntax: false,
4167 format: None,
4168 default: None,
4169 inferred_type: None,
4170 }));
4171 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
4172 Ok(Expression::Case(Box::new(Case {
4173 operand: None,
4174 whens: vec![
4175 (
4176 Expression::Eq(Box::new(BinaryOp {
4177 left: upper_text.clone(),
4178 right: Expression::Literal(Box::new(Literal::String(
4179 "ON".to_string(),
4180 ))),
4181 left_comments: Vec::new(),
4182 operator_comments: Vec::new(),
4183 trailing_comments: Vec::new(),
4184 inferred_type: None,
4185 })),
4186 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
4187 ),
4188 (
4189 Expression::Eq(Box::new(BinaryOp {
4190 left: upper_text,
4191 right: Expression::Literal(Box::new(Literal::String(
4192 "OFF".to_string(),
4193 ))),
4194 left_comments: Vec::new(),
4195 operator_comments: Vec::new(),
4196 trailing_comments: Vec::new(),
4197 inferred_type: None,
4198 })),
4199 Expression::Boolean(crate::expressions::BooleanLiteral {
4200 value: false,
4201 }),
4202 ),
4203 (
4204 Expression::Or(Box::new(BinaryOp {
4205 left: Expression::Function(Box::new(Function::new(
4206 "ISNAN".to_string(),
4207 vec![Expression::TryCast(Box::new(Cast {
4208 this: arg.clone(),
4209 to: DataType::Custom {
4210 name: "REAL".to_string(),
4211 },
4212 trailing_comments: Vec::new(),
4213 double_colon_syntax: false,
4214 format: None,
4215 default: None,
4216 inferred_type: None,
4217 }))],
4218 ))),
4219 right: Expression::Function(Box::new(Function::new(
4220 "ISINF".to_string(),
4221 vec![Expression::TryCast(Box::new(Cast {
4222 this: arg.clone(),
4223 to: DataType::Custom {
4224 name: "REAL".to_string(),
4225 },
4226 trailing_comments: Vec::new(),
4227 double_colon_syntax: false,
4228 format: None,
4229 default: None,
4230 inferred_type: None,
4231 }))],
4232 ))),
4233 left_comments: Vec::new(),
4234 operator_comments: Vec::new(),
4235 trailing_comments: Vec::new(),
4236 inferred_type: None,
4237 })),
4238 Expression::Function(Box::new(Function::new(
4239 "ERROR".to_string(),
4240 vec![Expression::Literal(Box::new(Literal::String(
4241 "TO_BOOLEAN: Non-numeric values NaN and INF are not supported"
4242 .to_string(),
4243 )))],
4244 ))),
4245 ),
4246 ],
4247 else_: Some(Expression::Cast(Box::new(Cast {
4248 this: arg,
4249 to: DataType::Boolean,
4250 trailing_comments: Vec::new(),
4251 double_colon_syntax: false,
4252 format: None,
4253 default: None,
4254 inferred_type: None,
4255 }))),
4256 comments: Vec::new(),
4257 inferred_type: None,
4258 })))
4259 }
4260
4261 "OBJECT_INSERT" if f.args.len() == 3 => {
4264 let mut args = f.args;
4265 let obj = args.remove(0);
4266 let key = args.remove(0);
4267 let value = args.remove(0);
4268 let key_name = match &key {
4270 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4271 let Literal::String(s) = lit.as_ref() else {
4272 unreachable!()
4273 };
4274 s.clone()
4275 }
4276 _ => "key".to_string(),
4277 };
4278 let named_arg =
4279 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
4280 name: Identifier::new(&key_name),
4281 value,
4282 separator: crate::expressions::NamedArgSeparator::ColonEq,
4283 }));
4284 let is_empty_struct = match &obj {
4286 Expression::Struct(s) if s.fields.is_empty() => true,
4287 Expression::Function(f) => {
4288 let n = f.name.to_uppercase();
4289 (n == "STRUCT_PACK" || n == "OBJECT_CONSTRUCT") && f.args.is_empty()
4290 }
4291 _ => false,
4292 };
4293 if is_empty_struct {
4294 Ok(Expression::Function(Box::new(Function::new(
4296 "STRUCT_PACK".to_string(),
4297 vec![named_arg],
4298 ))))
4299 } else {
4300 Ok(Expression::Function(Box::new(Function::new(
4301 "STRUCT_INSERT".to_string(),
4302 vec![obj, named_arg],
4303 ))))
4304 }
4305 }
4306
4307 "GET" if f.args.len() == 2 => {
4309 let mut args = f.args;
4310 let this = args.remove(0);
4311 let key = args.remove(0);
4312 match &key {
4313 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4315 let Literal::String(s) = lit.as_ref() else {
4316 unreachable!()
4317 };
4318 let json_path = format!("$.{}", s);
4319 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4320 this,
4321 path: Expression::Literal(Box::new(Literal::String(json_path))),
4322 returning: None,
4323 arrow_syntax: true,
4324 hash_arrow_syntax: false,
4325 wrapper_option: None,
4326 quotes_option: None,
4327 on_scalar_string: false,
4328 on_error: None,
4329 })))
4330 }
4331 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4335 let Literal::Number(n) = lit.as_ref() else {
4336 unreachable!()
4337 };
4338 let idx: i64 = n.parse().unwrap_or(0);
4339 let is_map = matches!(&this, Expression::Cast(c) if matches!(c.to, DataType::Map { .. }));
4340 let index_val = if is_map { idx } else { idx + 1 };
4341 Ok(Expression::Subscript(Box::new(
4342 crate::expressions::Subscript {
4343 this,
4344 index: Expression::number(index_val),
4345 },
4346 )))
4347 }
4348 _ => {
4349 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4351 this,
4352 path: Expression::JSONPath(Box::new(JSONPath {
4353 expressions: vec![
4354 Expression::JSONPathRoot(JSONPathRoot),
4355 Expression::JSONPathKey(Box::new(JSONPathKey {
4356 this: Box::new(key),
4357 })),
4358 ],
4359 escape: None,
4360 })),
4361 returning: None,
4362 arrow_syntax: true,
4363 hash_arrow_syntax: false,
4364 wrapper_option: None,
4365 quotes_option: None,
4366 on_scalar_string: false,
4367 on_error: None,
4368 })))
4369 }
4370 }
4371 }
4372
4373 "GET_PATH" if f.args.len() == 2 => {
4375 let mut args = f.args;
4376 let this = args.remove(0);
4377 let path = args.remove(0);
4378 let json_path = match &path {
4380 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4381 let Literal::String(s) = lit.as_ref() else {
4382 unreachable!()
4383 };
4384 let s = Self::convert_bracket_to_quoted_path(s);
4386 let normalized = if s.starts_with('$') {
4388 s
4389 } else if s.starts_with('[') {
4390 format!("${}", s)
4391 } else {
4392 format!("$.{}", s)
4393 };
4394 Expression::Literal(Box::new(Literal::String(normalized)))
4395 }
4396 _ => path,
4397 };
4398 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4399 this,
4400 path: json_path,
4401 returning: None,
4402 arrow_syntax: true,
4403 hash_arrow_syntax: false,
4404 wrapper_option: None,
4405 quotes_option: None,
4406 on_scalar_string: false,
4407 on_error: None,
4408 })))
4409 }
4410
4411 "BASE64_ENCODE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
4413 Function::new("TO_BASE64".to_string(), f.args),
4414 ))),
4415
4416 "BASE64_ENCODE" if f.args.len() >= 2 => {
4418 let mut args = f.args;
4419 let x = args.remove(0);
4420 let line_len = args.remove(0);
4421 let line_len_str = match &line_len {
4422 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4423 let Literal::Number(n) = lit.as_ref() else {
4424 unreachable!()
4425 };
4426 n.clone()
4427 }
4428 _ => "76".to_string(),
4429 };
4430 let to_base64 =
4431 Expression::Function(Box::new(Function::new("TO_BASE64".to_string(), vec![x])));
4432 let pattern = format!("(.{{{}}})", line_len_str);
4433 let chr_10 = Expression::Function(Box::new(Function::new(
4434 "CHR".to_string(),
4435 vec![Expression::number(10)],
4436 )));
4437 let replacement = Expression::Concat(Box::new(BinaryOp {
4438 left: Expression::Literal(Box::new(Literal::String("\\1".to_string()))),
4439 right: chr_10.clone(),
4440 left_comments: Vec::new(),
4441 operator_comments: Vec::new(),
4442 trailing_comments: Vec::new(),
4443 inferred_type: None,
4444 }));
4445 let regexp_replace = Expression::Function(Box::new(Function::new(
4446 "REGEXP_REPLACE".to_string(),
4447 vec![
4448 to_base64,
4449 Expression::Literal(Box::new(Literal::String(pattern))),
4450 replacement,
4451 Expression::Literal(Box::new(Literal::String("g".to_string()))),
4452 ],
4453 )));
4454 Ok(Expression::Function(Box::new(Function::new(
4455 "RTRIM".to_string(),
4456 vec![regexp_replace, chr_10],
4457 ))))
4458 }
4459
4460 "TRY_TO_DATE" if f.args.len() == 2 => {
4462 let mut args = f.args;
4463 let value = args.remove(0);
4464 let fmt = self.convert_snowflake_date_format(args.remove(0));
4465 Ok(Expression::Cast(Box::new(Cast {
4466 this: Expression::Cast(Box::new(Cast {
4467 this: Expression::Function(Box::new(Function::new(
4468 "TRY_STRPTIME".to_string(),
4469 vec![value, fmt],
4470 ))),
4471 to: DataType::Timestamp {
4472 precision: None,
4473 timezone: false,
4474 },
4475 trailing_comments: Vec::new(),
4476 double_colon_syntax: false,
4477 format: None,
4478 default: None,
4479 inferred_type: None,
4480 })),
4481 to: DataType::Date,
4482 trailing_comments: Vec::new(),
4483 double_colon_syntax: false,
4484 format: None,
4485 default: None,
4486 inferred_type: None,
4487 })))
4488 }
4489
4490 "REGEXP_REPLACE" if f.args.len() == 4 => {
4493 let is_snowflake_position = matches!(&f.args[3], Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)));
4494 if is_snowflake_position {
4495 let mut args = f.args;
4497 let subject = args.remove(0);
4498 let pattern = args.remove(0);
4499 let replacement = args.remove(0);
4500 Ok(Expression::Function(Box::new(Function::new(
4501 "REGEXP_REPLACE".to_string(),
4502 vec![
4503 subject,
4504 pattern,
4505 replacement,
4506 Expression::Literal(Box::new(Literal::String("g".to_string()))),
4507 ],
4508 ))))
4509 } else {
4510 Ok(Expression::Function(Box::new(f)))
4512 }
4513 }
4514
4515 "REGEXP_REPLACE" if f.args.len() >= 5 => {
4517 let mut args = f.args;
4518 let subject = args.remove(0);
4519 let pattern = args.remove(0);
4520 let replacement = args.remove(0);
4521 let _position = args.remove(0);
4522 let occurrence = if !args.is_empty() {
4523 Some(args.remove(0))
4524 } else {
4525 None
4526 };
4527 let params = if !args.is_empty() {
4528 Some(args.remove(0))
4529 } else {
4530 None
4531 };
4532
4533 let mut flags = String::new();
4534 if let Some(Expression::Literal(lit)) = ¶ms {
4535 if let Literal::String(p) = lit.as_ref() {
4536 flags = p.clone();
4537 }
4538 }
4539 let is_global = match &occurrence {
4540 Some(Expression::Literal(lit))
4541 if matches!(lit.as_ref(), Literal::Number(_)) =>
4542 {
4543 let Literal::Number(n) = lit.as_ref() else {
4544 unreachable!()
4545 };
4546 n == "0"
4547 }
4548 None => true,
4549 _ => false,
4550 };
4551 if is_global && !flags.contains('g') {
4552 flags.push('g');
4553 }
4554
4555 Ok(Expression::Function(Box::new(Function::new(
4556 "REGEXP_REPLACE".to_string(),
4557 vec![
4558 subject,
4559 pattern,
4560 replacement,
4561 Expression::Literal(Box::new(Literal::String(flags))),
4562 ],
4563 ))))
4564 }
4565
4566 "ROUND"
4568 if f.args
4569 .iter()
4570 .any(|a| matches!(a, Expression::NamedArgument(_))) =>
4571 {
4572 let mut expr_val = None;
4573 let mut scale_val = None;
4574 let mut rounding_mode = None;
4575 for arg in &f.args {
4576 if let Expression::NamedArgument(na) = arg {
4577 match na.name.name.to_uppercase().as_str() {
4578 "EXPR" => expr_val = Some(na.value.clone()),
4579 "SCALE" => scale_val = Some(na.value.clone()),
4580 "ROUNDING_MODE" => rounding_mode = Some(na.value.clone()),
4581 _ => {}
4582 }
4583 }
4584 }
4585 if let Some(expr) = expr_val {
4586 let scale = scale_val.unwrap_or(Expression::number(0));
4587 let is_half_to_even = match &rounding_mode {
4588 Some(Expression::Literal(lit))
4589 if matches!(lit.as_ref(), Literal::String(_)) =>
4590 {
4591 let Literal::String(s) = lit.as_ref() else {
4592 unreachable!()
4593 };
4594 s == "HALF_TO_EVEN"
4595 }
4596 _ => false,
4597 };
4598 if is_half_to_even {
4599 Ok(Expression::Function(Box::new(Function::new(
4600 "ROUND_EVEN".to_string(),
4601 vec![expr, scale],
4602 ))))
4603 } else {
4604 Ok(Expression::Function(Box::new(Function::new(
4605 "ROUND".to_string(),
4606 vec![expr, scale],
4607 ))))
4608 }
4609 } else {
4610 Ok(Expression::Function(Box::new(f)))
4611 }
4612 }
4613
4614 "ROUND" if f.args.len() == 3 => {
4617 let mut args = f.args;
4618 let x = args.remove(0);
4619 let scale = args.remove(0);
4620 let mode = args.remove(0);
4621 let is_half_to_even = match &mode {
4622 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4623 let Literal::String(s) = lit.as_ref() else {
4624 unreachable!()
4625 };
4626 s == "HALF_TO_EVEN"
4627 }
4628 _ => false,
4629 };
4630 if is_half_to_even {
4631 Ok(Expression::Function(Box::new(Function::new(
4632 "ROUND_EVEN".to_string(),
4633 vec![x, scale],
4634 ))))
4635 } else {
4636 Ok(Expression::Function(Box::new(Function::new(
4638 "ROUND".to_string(),
4639 vec![x, scale],
4640 ))))
4641 }
4642 }
4643
4644 "ROUND" if f.args.len() == 2 => {
4646 let mut args = f.args;
4647 let x = args.remove(0);
4648 let scale = args.remove(0);
4649 let needs_cast = match &scale {
4650 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4651 let Literal::Number(n) = lit.as_ref() else {
4652 unreachable!()
4653 };
4654 n.contains('.')
4655 }
4656 Expression::Cast(_) => {
4657 true
4659 }
4660 _ => false,
4661 };
4662 if needs_cast {
4663 Ok(Expression::Function(Box::new(Function::new(
4664 "ROUND".to_string(),
4665 vec![
4666 x,
4667 Expression::Cast(Box::new(Cast {
4668 this: scale,
4669 to: DataType::Int {
4670 length: None,
4671 integer_spelling: false,
4672 },
4673 trailing_comments: Vec::new(),
4674 double_colon_syntax: false,
4675 format: None,
4676 default: None,
4677 inferred_type: None,
4678 })),
4679 ],
4680 ))))
4681 } else {
4682 Ok(Expression::Function(Box::new(Function::new(
4683 "ROUND".to_string(),
4684 vec![x, scale],
4685 ))))
4686 }
4687 }
4688
4689 "FLOOR" if f.args.len() == 2 => {
4691 let mut args = f.args;
4692 let x = args.remove(0);
4693 let scale = args.remove(0);
4694 let needs_cast = match &scale {
4696 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4697 let Literal::Number(n) = lit.as_ref() else {
4698 unreachable!()
4699 };
4700 n.contains('.')
4701 }
4702 _ => false,
4703 };
4704 let int_scale = if needs_cast {
4705 Expression::Cast(Box::new(Cast {
4706 this: scale.clone(),
4707 to: DataType::Int {
4708 length: None,
4709 integer_spelling: false,
4710 },
4711 trailing_comments: Vec::new(),
4712 double_colon_syntax: false,
4713 format: None,
4714 default: None,
4715 inferred_type: None,
4716 }))
4717 } else {
4718 scale.clone()
4719 };
4720 let power_10 = Expression::Function(Box::new(Function::new(
4721 "POWER".to_string(),
4722 vec![Expression::number(10), int_scale.clone()],
4723 )));
4724 let x_paren = match &x {
4725 Expression::Add(_)
4726 | Expression::Sub(_)
4727 | Expression::Mul(_)
4728 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4729 this: x,
4730 trailing_comments: Vec::new(),
4731 })),
4732 _ => x,
4733 };
4734 let multiplied = Expression::Mul(Box::new(BinaryOp {
4735 left: x_paren,
4736 right: power_10.clone(),
4737 left_comments: Vec::new(),
4738 operator_comments: Vec::new(),
4739 trailing_comments: Vec::new(),
4740 inferred_type: None,
4741 }));
4742 let floored = Expression::Function(Box::new(Function::new(
4743 "FLOOR".to_string(),
4744 vec![multiplied],
4745 )));
4746 let divided = Expression::Div(Box::new(BinaryOp {
4747 left: floored,
4748 right: power_10,
4749 left_comments: Vec::new(),
4750 operator_comments: Vec::new(),
4751 trailing_comments: Vec::new(),
4752 inferred_type: None,
4753 }));
4754 Ok(Expression::Function(Box::new(Function::new(
4755 "ROUND".to_string(),
4756 vec![divided, int_scale],
4757 ))))
4758 }
4759
4760 "CEIL" | "CEILING" if f.args.len() == 2 => {
4762 let mut args = f.args;
4763 let x = args.remove(0);
4764 let scale = args.remove(0);
4765 let needs_cast = match &scale {
4766 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4767 let Literal::Number(n) = lit.as_ref() else {
4768 unreachable!()
4769 };
4770 n.contains('.')
4771 }
4772 _ => false,
4773 };
4774 let int_scale = if needs_cast {
4775 Expression::Cast(Box::new(Cast {
4776 this: scale.clone(),
4777 to: DataType::Int {
4778 length: None,
4779 integer_spelling: false,
4780 },
4781 trailing_comments: Vec::new(),
4782 double_colon_syntax: false,
4783 format: None,
4784 default: None,
4785 inferred_type: None,
4786 }))
4787 } else {
4788 scale.clone()
4789 };
4790 let power_10 = Expression::Function(Box::new(Function::new(
4791 "POWER".to_string(),
4792 vec![Expression::number(10), int_scale.clone()],
4793 )));
4794 let x_paren = match &x {
4795 Expression::Add(_)
4796 | Expression::Sub(_)
4797 | Expression::Mul(_)
4798 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4799 this: x,
4800 trailing_comments: Vec::new(),
4801 })),
4802 _ => x,
4803 };
4804 let multiplied = Expression::Mul(Box::new(BinaryOp {
4805 left: x_paren,
4806 right: power_10.clone(),
4807 left_comments: Vec::new(),
4808 operator_comments: Vec::new(),
4809 trailing_comments: Vec::new(),
4810 inferred_type: None,
4811 }));
4812 let ceiled = Expression::Function(Box::new(Function::new(
4813 "CEIL".to_string(),
4814 vec![multiplied],
4815 )));
4816 let divided = Expression::Div(Box::new(BinaryOp {
4817 left: ceiled,
4818 right: power_10,
4819 left_comments: Vec::new(),
4820 operator_comments: Vec::new(),
4821 trailing_comments: Vec::new(),
4822 inferred_type: None,
4823 }));
4824 Ok(Expression::Function(Box::new(Function::new(
4825 "ROUND".to_string(),
4826 vec![divided, int_scale],
4827 ))))
4828 }
4829
4830 "ADD_MONTHS" if f.args.len() == 2 => {
4832 let mut args = f.args;
4833 let date_expr_raw = args.remove(0);
4834 let months_expr = args.remove(0);
4835
4836 let was_string_literal = matches!(&date_expr_raw, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)));
4838
4839 let date_expr = match &date_expr_raw {
4841 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
4842 Expression::Cast(Box::new(Cast {
4843 this: date_expr_raw,
4844 to: DataType::Timestamp {
4845 precision: None,
4846 timezone: false,
4847 },
4848 trailing_comments: Vec::new(),
4849 double_colon_syntax: false,
4850 format: None,
4851 default: None,
4852 inferred_type: None,
4853 }))
4854 }
4855 _ => date_expr_raw,
4856 };
4857
4858 let date_type = if was_string_literal {
4861 None
4862 } else {
4863 match &date_expr {
4864 Expression::Cast(c) => Some(c.to.clone()),
4865 _ => None,
4866 }
4867 };
4868
4869 let is_non_integer_months = match &months_expr {
4871 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4872 let Literal::Number(n) = lit.as_ref() else {
4873 unreachable!()
4874 };
4875 n.contains('.')
4876 }
4877 Expression::Neg(_) => {
4878 if let Expression::Neg(um) = &months_expr {
4879 matches!(&um.this, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(n) if n.contains('.')))
4880 } else {
4881 false
4882 }
4883 }
4884 Expression::Cast(c) => matches!(&c.to, DataType::Decimal { .. }),
4886 _ => false,
4887 };
4888
4889 let is_negative = match &months_expr {
4890 Expression::Neg(_) => true,
4891 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
4892 let Literal::Number(n) = lit.as_ref() else {
4893 unreachable!()
4894 };
4895 n.starts_with('-')
4896 }
4897 _ => false,
4898 };
4899 let is_null = matches!(&months_expr, Expression::Null(_));
4900
4901 let interval_expr = if is_non_integer_months {
4902 Expression::Function(Box::new(Function::new(
4904 "TO_MONTHS".to_string(),
4905 vec![Expression::Cast(Box::new(Cast {
4906 this: Expression::Function(Box::new(Function::new(
4907 "ROUND".to_string(),
4908 vec![months_expr.clone()],
4909 ))),
4910 to: DataType::Int {
4911 length: None,
4912 integer_spelling: false,
4913 },
4914 trailing_comments: Vec::new(),
4915 double_colon_syntax: false,
4916 format: None,
4917 default: None,
4918 inferred_type: None,
4919 }))],
4920 )))
4921 } else if is_negative || is_null {
4922 Expression::Interval(Box::new(Interval {
4924 this: Some(Expression::Paren(Box::new(Paren {
4925 this: months_expr.clone(),
4926 trailing_comments: Vec::new(),
4927 }))),
4928 unit: Some(IntervalUnitSpec::Simple {
4929 unit: IntervalUnit::Month,
4930 use_plural: false,
4931 }),
4932 }))
4933 } else {
4934 Expression::Interval(Box::new(Interval {
4936 this: Some(months_expr.clone()),
4937 unit: Some(IntervalUnitSpec::Simple {
4938 unit: IntervalUnit::Month,
4939 use_plural: false,
4940 }),
4941 }))
4942 };
4943
4944 let date_plus_interval = Expression::Add(Box::new(BinaryOp {
4945 left: date_expr.clone(),
4946 right: interval_expr.clone(),
4947 left_comments: Vec::new(),
4948 operator_comments: Vec::new(),
4949 trailing_comments: Vec::new(),
4950 inferred_type: None,
4951 }));
4952
4953 let case_expr = Expression::Case(Box::new(Case {
4954 operand: None,
4955 whens: vec![(
4956 Expression::Eq(Box::new(BinaryOp {
4957 left: Expression::Function(Box::new(Function::new(
4958 "LAST_DAY".to_string(),
4959 vec![date_expr.clone()],
4960 ))),
4961 right: date_expr.clone(),
4962 left_comments: Vec::new(),
4963 operator_comments: Vec::new(),
4964 trailing_comments: Vec::new(),
4965 inferred_type: None,
4966 })),
4967 Expression::Function(Box::new(Function::new(
4968 "LAST_DAY".to_string(),
4969 vec![date_plus_interval.clone()],
4970 ))),
4971 )],
4972 else_: Some(date_plus_interval),
4973 comments: Vec::new(),
4974 inferred_type: None,
4975 }));
4976
4977 if let Some(dt) = date_type {
4979 Ok(Expression::Cast(Box::new(Cast {
4980 this: case_expr,
4981 to: dt,
4982 trailing_comments: Vec::new(),
4983 double_colon_syntax: false,
4984 format: None,
4985 default: None,
4986 inferred_type: None,
4987 })))
4988 } else {
4989 Ok(case_expr)
4990 }
4991 }
4992
4993 "TIME_SLICE" if f.args.len() >= 3 => {
4996 let mut args = f.args;
4997 let date_expr = args.remove(0);
4998 let n = args.remove(0);
4999 let unit_str = args.remove(0);
5000 let alignment = if !args.is_empty() {
5001 Some(args.remove(0))
5002 } else {
5003 None
5004 };
5005
5006 let unit = match &unit_str {
5008 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5009 let Literal::String(s) = lit.as_ref() else {
5010 unreachable!()
5011 };
5012 s.to_uppercase()
5013 }
5014 Expression::Column(c) => c.name.name.to_uppercase(),
5015 Expression::Identifier(i) => i.name.to_uppercase(),
5016 _ => "DAY".to_string(),
5017 };
5018
5019 let interval_unit = match unit.as_str() {
5020 "YEAR" => IntervalUnit::Year,
5021 "QUARTER" => IntervalUnit::Quarter,
5022 "MONTH" => IntervalUnit::Month,
5023 "WEEK" => IntervalUnit::Week,
5024 "DAY" => IntervalUnit::Day,
5025 "HOUR" => IntervalUnit::Hour,
5026 "MINUTE" => IntervalUnit::Minute,
5027 "SECOND" => IntervalUnit::Second,
5028 _ => IntervalUnit::Day,
5029 };
5030
5031 let interval = Expression::Interval(Box::new(Interval {
5032 this: Some(n.clone()),
5033 unit: Some(IntervalUnitSpec::Simple {
5034 unit: interval_unit.clone(),
5035 use_plural: false,
5036 }),
5037 }));
5038
5039 let time_bucket = Expression::Function(Box::new(Function::new(
5040 "TIME_BUCKET".to_string(),
5041 vec![interval.clone(), date_expr.clone()],
5042 )));
5043
5044 let is_end = match &alignment {
5045 Some(Expression::Literal(lit))
5046 if matches!(lit.as_ref(), Literal::String(_)) =>
5047 {
5048 let Literal::String(s) = lit.as_ref() else {
5049 unreachable!()
5050 };
5051 s.to_uppercase() == "END"
5052 }
5053 _ => false,
5054 };
5055
5056 let is_date_type = match &date_expr {
5058 Expression::Cast(c) => matches!(&c.to, DataType::Date),
5059 _ => false,
5060 };
5061
5062 if is_end {
5063 let bucket_plus = Expression::Add(Box::new(BinaryOp {
5064 left: time_bucket,
5065 right: Expression::Interval(Box::new(Interval {
5066 this: Some(n),
5067 unit: Some(IntervalUnitSpec::Simple {
5068 unit: interval_unit,
5069 use_plural: false,
5070 }),
5071 })),
5072 left_comments: Vec::new(),
5073 operator_comments: Vec::new(),
5074 trailing_comments: Vec::new(),
5075 inferred_type: None,
5076 }));
5077 if is_date_type {
5078 Ok(Expression::Cast(Box::new(Cast {
5079 this: bucket_plus,
5080 to: DataType::Date,
5081 trailing_comments: Vec::new(),
5082 double_colon_syntax: false,
5083 format: None,
5084 default: None,
5085 inferred_type: None,
5086 })))
5087 } else {
5088 Ok(bucket_plus)
5089 }
5090 } else {
5091 Ok(time_bucket)
5092 }
5093 }
5094
5095 "DATE_FROM_PARTS" | "DATEFROMPARTS" if f.args.len() == 3 => {
5097 let mut args = f.args;
5098 let year = args.remove(0);
5099 let month = args.remove(0);
5100 let day = args.remove(0);
5101
5102 let make_date = Expression::Function(Box::new(Function::new(
5103 "MAKE_DATE".to_string(),
5104 vec![year, Expression::number(1), Expression::number(1)],
5105 )));
5106
5107 let month_wrapped = match &month {
5109 Expression::Add(_)
5110 | Expression::Sub(_)
5111 | Expression::Mul(_)
5112 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
5113 this: month,
5114 trailing_comments: Vec::new(),
5115 })),
5116 _ => month,
5117 };
5118 let day_wrapped = match &day {
5119 Expression::Add(_)
5120 | Expression::Sub(_)
5121 | Expression::Mul(_)
5122 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
5123 this: day,
5124 trailing_comments: Vec::new(),
5125 })),
5126 _ => day,
5127 };
5128 let month_minus_1 = Expression::Sub(Box::new(BinaryOp {
5129 left: month_wrapped,
5130 right: Expression::number(1),
5131 left_comments: Vec::new(),
5132 operator_comments: Vec::new(),
5133 trailing_comments: Vec::new(),
5134 inferred_type: None,
5135 }));
5136 let month_interval = Expression::Interval(Box::new(Interval {
5137 this: Some(Expression::Paren(Box::new(Paren {
5138 this: month_minus_1,
5139 trailing_comments: Vec::new(),
5140 }))),
5141 unit: Some(IntervalUnitSpec::Simple {
5142 unit: IntervalUnit::Month,
5143 use_plural: false,
5144 }),
5145 }));
5146
5147 let day_minus_1 = Expression::Sub(Box::new(BinaryOp {
5148 left: day_wrapped,
5149 right: Expression::number(1),
5150 left_comments: Vec::new(),
5151 operator_comments: Vec::new(),
5152 trailing_comments: Vec::new(),
5153 inferred_type: None,
5154 }));
5155 let day_interval = Expression::Interval(Box::new(Interval {
5156 this: Some(Expression::Paren(Box::new(Paren {
5157 this: day_minus_1,
5158 trailing_comments: Vec::new(),
5159 }))),
5160 unit: Some(IntervalUnitSpec::Simple {
5161 unit: IntervalUnit::Day,
5162 use_plural: false,
5163 }),
5164 }));
5165
5166 let result = Expression::Add(Box::new(BinaryOp {
5167 left: Expression::Add(Box::new(BinaryOp {
5168 left: make_date,
5169 right: month_interval,
5170 left_comments: Vec::new(),
5171 operator_comments: Vec::new(),
5172 trailing_comments: Vec::new(),
5173 inferred_type: None,
5174 })),
5175 right: day_interval,
5176 left_comments: Vec::new(),
5177 operator_comments: Vec::new(),
5178 trailing_comments: Vec::new(),
5179 inferred_type: None,
5180 }));
5181
5182 Ok(Expression::Cast(Box::new(Cast {
5183 this: result,
5184 to: DataType::Date,
5185 trailing_comments: Vec::new(),
5186 double_colon_syntax: false,
5187 format: None,
5188 default: None,
5189 inferred_type: None,
5190 })))
5191 }
5192
5193 "NEXT_DAY" if f.args.len() == 2 => {
5195 let mut args = f.args;
5196 let date = args.remove(0);
5197 let day_name = args.remove(0);
5198
5199 let day_num = match &day_name {
5201 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5202 let Literal::String(s) = lit.as_ref() else {
5203 unreachable!()
5204 };
5205 let upper = s.to_uppercase();
5206 if upper.starts_with("MO") {
5207 Some(1)
5208 } else if upper.starts_with("TU") {
5209 Some(2)
5210 } else if upper.starts_with("WE") {
5211 Some(3)
5212 } else if upper.starts_with("TH") {
5213 Some(4)
5214 } else if upper.starts_with("FR") {
5215 Some(5)
5216 } else if upper.starts_with("SA") {
5217 Some(6)
5218 } else if upper.starts_with("SU") {
5219 Some(7)
5220 } else {
5221 None
5222 }
5223 }
5224 _ => None,
5225 };
5226
5227 let target_day_expr = if let Some(n) = day_num {
5228 Expression::number(n)
5229 } else {
5230 Expression::Case(Box::new(Case {
5232 operand: None,
5233 whens: vec![
5234 (
5235 Expression::Function(Box::new(Function::new(
5236 "STARTS_WITH".to_string(),
5237 vec![
5238 Expression::Upper(Box::new(UnaryFunc::new(
5239 day_name.clone(),
5240 ))),
5241 Expression::Literal(Box::new(Literal::String(
5242 "MO".to_string(),
5243 ))),
5244 ],
5245 ))),
5246 Expression::number(1),
5247 ),
5248 (
5249 Expression::Function(Box::new(Function::new(
5250 "STARTS_WITH".to_string(),
5251 vec![
5252 Expression::Upper(Box::new(UnaryFunc::new(
5253 day_name.clone(),
5254 ))),
5255 Expression::Literal(Box::new(Literal::String(
5256 "TU".to_string(),
5257 ))),
5258 ],
5259 ))),
5260 Expression::number(2),
5261 ),
5262 (
5263 Expression::Function(Box::new(Function::new(
5264 "STARTS_WITH".to_string(),
5265 vec![
5266 Expression::Upper(Box::new(UnaryFunc::new(
5267 day_name.clone(),
5268 ))),
5269 Expression::Literal(Box::new(Literal::String(
5270 "WE".to_string(),
5271 ))),
5272 ],
5273 ))),
5274 Expression::number(3),
5275 ),
5276 (
5277 Expression::Function(Box::new(Function::new(
5278 "STARTS_WITH".to_string(),
5279 vec![
5280 Expression::Upper(Box::new(UnaryFunc::new(
5281 day_name.clone(),
5282 ))),
5283 Expression::Literal(Box::new(Literal::String(
5284 "TH".to_string(),
5285 ))),
5286 ],
5287 ))),
5288 Expression::number(4),
5289 ),
5290 (
5291 Expression::Function(Box::new(Function::new(
5292 "STARTS_WITH".to_string(),
5293 vec![
5294 Expression::Upper(Box::new(UnaryFunc::new(
5295 day_name.clone(),
5296 ))),
5297 Expression::Literal(Box::new(Literal::String(
5298 "FR".to_string(),
5299 ))),
5300 ],
5301 ))),
5302 Expression::number(5),
5303 ),
5304 (
5305 Expression::Function(Box::new(Function::new(
5306 "STARTS_WITH".to_string(),
5307 vec![
5308 Expression::Upper(Box::new(UnaryFunc::new(
5309 day_name.clone(),
5310 ))),
5311 Expression::Literal(Box::new(Literal::String(
5312 "SA".to_string(),
5313 ))),
5314 ],
5315 ))),
5316 Expression::number(6),
5317 ),
5318 (
5319 Expression::Function(Box::new(Function::new(
5320 "STARTS_WITH".to_string(),
5321 vec![
5322 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
5323 Expression::Literal(Box::new(Literal::String(
5324 "SU".to_string(),
5325 ))),
5326 ],
5327 ))),
5328 Expression::number(7),
5329 ),
5330 ],
5331 else_: None,
5332 comments: Vec::new(),
5333 inferred_type: None,
5334 }))
5335 };
5336
5337 let isodow = Expression::Function(Box::new(Function::new(
5338 "ISODOW".to_string(),
5339 vec![date.clone()],
5340 )));
5341 let diff = Expression::Add(Box::new(BinaryOp {
5343 left: Expression::Paren(Box::new(Paren {
5344 this: Expression::Mod(Box::new(BinaryOp {
5345 left: Expression::Paren(Box::new(Paren {
5346 this: Expression::Add(Box::new(BinaryOp {
5347 left: Expression::Paren(Box::new(Paren {
5348 this: Expression::Sub(Box::new(BinaryOp {
5349 left: target_day_expr,
5350 right: isodow,
5351 left_comments: Vec::new(),
5352 operator_comments: Vec::new(),
5353 trailing_comments: Vec::new(),
5354 inferred_type: None,
5355 })),
5356 trailing_comments: Vec::new(),
5357 })),
5358 right: Expression::number(6),
5359 left_comments: Vec::new(),
5360 operator_comments: Vec::new(),
5361 trailing_comments: Vec::new(),
5362 inferred_type: None,
5363 })),
5364 trailing_comments: Vec::new(),
5365 })),
5366 right: Expression::number(7),
5367 left_comments: Vec::new(),
5368 operator_comments: Vec::new(),
5369 trailing_comments: Vec::new(),
5370 inferred_type: None,
5371 })),
5372 trailing_comments: Vec::new(),
5373 })),
5374 right: Expression::number(1),
5375 left_comments: Vec::new(),
5376 operator_comments: Vec::new(),
5377 trailing_comments: Vec::new(),
5378 inferred_type: None,
5379 }));
5380
5381 let result = Expression::Add(Box::new(BinaryOp {
5382 left: date,
5383 right: Expression::Interval(Box::new(Interval {
5384 this: Some(Expression::Paren(Box::new(Paren {
5385 this: diff,
5386 trailing_comments: Vec::new(),
5387 }))),
5388 unit: Some(IntervalUnitSpec::Simple {
5389 unit: IntervalUnit::Day,
5390 use_plural: false,
5391 }),
5392 })),
5393 left_comments: Vec::new(),
5394 operator_comments: Vec::new(),
5395 trailing_comments: Vec::new(),
5396 inferred_type: None,
5397 }));
5398
5399 Ok(Expression::Cast(Box::new(Cast {
5400 this: result,
5401 to: DataType::Date,
5402 trailing_comments: Vec::new(),
5403 double_colon_syntax: false,
5404 format: None,
5405 default: None,
5406 inferred_type: None,
5407 })))
5408 }
5409
5410 "PREVIOUS_DAY" if f.args.len() == 2 => {
5412 let mut args = f.args;
5413 let date = args.remove(0);
5414 let day_name = args.remove(0);
5415
5416 let day_num = match &day_name {
5417 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
5418 let Literal::String(s) = lit.as_ref() else {
5419 unreachable!()
5420 };
5421 let upper = s.to_uppercase();
5422 if upper.starts_with("MO") {
5423 Some(1)
5424 } else if upper.starts_with("TU") {
5425 Some(2)
5426 } else if upper.starts_with("WE") {
5427 Some(3)
5428 } else if upper.starts_with("TH") {
5429 Some(4)
5430 } else if upper.starts_with("FR") {
5431 Some(5)
5432 } else if upper.starts_with("SA") {
5433 Some(6)
5434 } else if upper.starts_with("SU") {
5435 Some(7)
5436 } else {
5437 None
5438 }
5439 }
5440 _ => None,
5441 };
5442
5443 let target_day_expr = if let Some(n) = day_num {
5444 Expression::number(n)
5445 } else {
5446 Expression::Case(Box::new(Case {
5447 operand: None,
5448 whens: vec![
5449 (
5450 Expression::Function(Box::new(Function::new(
5451 "STARTS_WITH".to_string(),
5452 vec![
5453 Expression::Upper(Box::new(UnaryFunc::new(
5454 day_name.clone(),
5455 ))),
5456 Expression::Literal(Box::new(Literal::String(
5457 "MO".to_string(),
5458 ))),
5459 ],
5460 ))),
5461 Expression::number(1),
5462 ),
5463 (
5464 Expression::Function(Box::new(Function::new(
5465 "STARTS_WITH".to_string(),
5466 vec![
5467 Expression::Upper(Box::new(UnaryFunc::new(
5468 day_name.clone(),
5469 ))),
5470 Expression::Literal(Box::new(Literal::String(
5471 "TU".to_string(),
5472 ))),
5473 ],
5474 ))),
5475 Expression::number(2),
5476 ),
5477 (
5478 Expression::Function(Box::new(Function::new(
5479 "STARTS_WITH".to_string(),
5480 vec![
5481 Expression::Upper(Box::new(UnaryFunc::new(
5482 day_name.clone(),
5483 ))),
5484 Expression::Literal(Box::new(Literal::String(
5485 "WE".to_string(),
5486 ))),
5487 ],
5488 ))),
5489 Expression::number(3),
5490 ),
5491 (
5492 Expression::Function(Box::new(Function::new(
5493 "STARTS_WITH".to_string(),
5494 vec![
5495 Expression::Upper(Box::new(UnaryFunc::new(
5496 day_name.clone(),
5497 ))),
5498 Expression::Literal(Box::new(Literal::String(
5499 "TH".to_string(),
5500 ))),
5501 ],
5502 ))),
5503 Expression::number(4),
5504 ),
5505 (
5506 Expression::Function(Box::new(Function::new(
5507 "STARTS_WITH".to_string(),
5508 vec![
5509 Expression::Upper(Box::new(UnaryFunc::new(
5510 day_name.clone(),
5511 ))),
5512 Expression::Literal(Box::new(Literal::String(
5513 "FR".to_string(),
5514 ))),
5515 ],
5516 ))),
5517 Expression::number(5),
5518 ),
5519 (
5520 Expression::Function(Box::new(Function::new(
5521 "STARTS_WITH".to_string(),
5522 vec![
5523 Expression::Upper(Box::new(UnaryFunc::new(
5524 day_name.clone(),
5525 ))),
5526 Expression::Literal(Box::new(Literal::String(
5527 "SA".to_string(),
5528 ))),
5529 ],
5530 ))),
5531 Expression::number(6),
5532 ),
5533 (
5534 Expression::Function(Box::new(Function::new(
5535 "STARTS_WITH".to_string(),
5536 vec![
5537 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
5538 Expression::Literal(Box::new(Literal::String(
5539 "SU".to_string(),
5540 ))),
5541 ],
5542 ))),
5543 Expression::number(7),
5544 ),
5545 ],
5546 else_: None,
5547 comments: Vec::new(),
5548 inferred_type: None,
5549 }))
5550 };
5551
5552 let isodow = Expression::Function(Box::new(Function::new(
5553 "ISODOW".to_string(),
5554 vec![date.clone()],
5555 )));
5556 let diff = Expression::Add(Box::new(BinaryOp {
5558 left: Expression::Paren(Box::new(Paren {
5559 this: Expression::Mod(Box::new(BinaryOp {
5560 left: Expression::Paren(Box::new(Paren {
5561 this: Expression::Add(Box::new(BinaryOp {
5562 left: Expression::Paren(Box::new(Paren {
5563 this: Expression::Sub(Box::new(BinaryOp {
5564 left: isodow,
5565 right: target_day_expr,
5566 left_comments: Vec::new(),
5567 operator_comments: Vec::new(),
5568 trailing_comments: Vec::new(),
5569 inferred_type: None,
5570 })),
5571 trailing_comments: Vec::new(),
5572 })),
5573 right: Expression::number(6),
5574 left_comments: Vec::new(),
5575 operator_comments: Vec::new(),
5576 trailing_comments: Vec::new(),
5577 inferred_type: None,
5578 })),
5579 trailing_comments: Vec::new(),
5580 })),
5581 right: Expression::number(7),
5582 left_comments: Vec::new(),
5583 operator_comments: Vec::new(),
5584 trailing_comments: Vec::new(),
5585 inferred_type: None,
5586 })),
5587 trailing_comments: Vec::new(),
5588 })),
5589 right: Expression::number(1),
5590 left_comments: Vec::new(),
5591 operator_comments: Vec::new(),
5592 trailing_comments: Vec::new(),
5593 inferred_type: None,
5594 }));
5595
5596 let result = Expression::Sub(Box::new(BinaryOp {
5597 left: date,
5598 right: Expression::Interval(Box::new(Interval {
5599 this: Some(Expression::Paren(Box::new(Paren {
5600 this: diff,
5601 trailing_comments: Vec::new(),
5602 }))),
5603 unit: Some(IntervalUnitSpec::Simple {
5604 unit: IntervalUnit::Day,
5605 use_plural: false,
5606 }),
5607 })),
5608 left_comments: Vec::new(),
5609 operator_comments: Vec::new(),
5610 trailing_comments: Vec::new(),
5611 inferred_type: None,
5612 }));
5613
5614 Ok(Expression::Cast(Box::new(Cast {
5615 this: result,
5616 to: DataType::Date,
5617 trailing_comments: Vec::new(),
5618 double_colon_syntax: false,
5619 format: None,
5620 default: None,
5621 inferred_type: None,
5622 })))
5623 }
5624
5625 "LAST_DAY" if f.args.len() == 2 => {
5629 let mut args = f.args;
5630 let date = args.remove(0);
5631 let unit = args.remove(0);
5632 let unit_str = match &unit {
5633 Expression::Column(c) => c.name.name.to_uppercase(),
5634 Expression::Identifier(i) => i.name.to_uppercase(),
5635 _ => String::new(),
5636 };
5637
5638 match unit_str.as_str() {
5639 "MONTH" => Ok(Expression::Function(Box::new(Function::new(
5640 "LAST_DAY".to_string(),
5641 vec![date],
5642 )))),
5643 "YEAR" => Ok(Expression::Function(Box::new(Function::new(
5644 "MAKE_DATE".to_string(),
5645 vec![
5646 Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5647 this: date,
5648 field: crate::expressions::DateTimeField::Year,
5649 })),
5650 Expression::number(12),
5651 Expression::number(31),
5652 ],
5653 )))),
5654 "QUARTER" => {
5655 let year = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5656 this: date.clone(),
5657 field: crate::expressions::DateTimeField::Year,
5658 }));
5659 let quarter_month = Expression::Mul(Box::new(BinaryOp {
5660 left: Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5661 this: date,
5662 field: crate::expressions::DateTimeField::Custom(
5663 "QUARTER".to_string(),
5664 ),
5665 })),
5666 right: Expression::number(3),
5667 left_comments: Vec::new(),
5668 operator_comments: Vec::new(),
5669 trailing_comments: Vec::new(),
5670 inferred_type: None,
5671 }));
5672 let make_date = Expression::Function(Box::new(Function::new(
5673 "MAKE_DATE".to_string(),
5674 vec![year, quarter_month, Expression::number(1)],
5675 )));
5676 Ok(Expression::Function(Box::new(Function::new(
5677 "LAST_DAY".to_string(),
5678 vec![make_date],
5679 ))))
5680 }
5681 "WEEK" => {
5682 let dow = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5683 this: date.clone(),
5684 field: crate::expressions::DateTimeField::Custom(
5685 "DAYOFWEEK".to_string(),
5686 ),
5687 }));
5688 let diff = Expression::Mod(Box::new(BinaryOp {
5689 left: Expression::Paren(Box::new(Paren {
5690 this: Expression::Sub(Box::new(BinaryOp {
5691 left: Expression::number(7),
5692 right: dow,
5693 left_comments: Vec::new(),
5694 operator_comments: Vec::new(),
5695 trailing_comments: Vec::new(),
5696 inferred_type: None,
5697 })),
5698 trailing_comments: Vec::new(),
5699 })),
5700 right: Expression::number(7),
5701 left_comments: Vec::new(),
5702 operator_comments: Vec::new(),
5703 trailing_comments: Vec::new(),
5704 inferred_type: None,
5705 }));
5706 let result = Expression::Add(Box::new(BinaryOp {
5707 left: date,
5708 right: Expression::Interval(Box::new(Interval {
5709 this: Some(Expression::Paren(Box::new(Paren {
5710 this: diff,
5711 trailing_comments: Vec::new(),
5712 }))),
5713 unit: Some(IntervalUnitSpec::Simple {
5714 unit: IntervalUnit::Day,
5715 use_plural: false,
5716 }),
5717 })),
5718 left_comments: Vec::new(),
5719 operator_comments: Vec::new(),
5720 trailing_comments: Vec::new(),
5721 inferred_type: None,
5722 }));
5723 Ok(Expression::Cast(Box::new(Cast {
5724 this: result,
5725 to: DataType::Date,
5726 trailing_comments: Vec::new(),
5727 double_colon_syntax: false,
5728 format: None,
5729 default: None,
5730 inferred_type: None,
5731 })))
5732 }
5733 _ => Ok(Expression::Function(Box::new(Function::new(
5734 "LAST_DAY".to_string(),
5735 vec![date, unit],
5736 )))),
5737 }
5738 }
5739
5740 "SEQ1" | "SEQ2" | "SEQ4" | "SEQ8" => {
5743 let (range, half): (u128, u128) = match name_upper.as_str() {
5744 "SEQ1" => (256, 128),
5745 "SEQ2" => (65536, 32768),
5746 "SEQ4" => (4294967296, 2147483648),
5747 "SEQ8" => (18446744073709551616, 9223372036854775808),
5748 _ => unreachable!("sequence type already matched in caller"),
5749 };
5750
5751 let is_signed = match f.args.first() {
5752 Some(Expression::Literal(lit))
5753 if matches!(lit.as_ref(), Literal::Number(_)) =>
5754 {
5755 let Literal::Number(n) = lit.as_ref() else {
5756 unreachable!()
5757 };
5758 n == "1"
5759 }
5760 _ => false,
5761 };
5762
5763 let row_num = Expression::Sub(Box::new(BinaryOp {
5764 left: Expression::WindowFunction(Box::new(
5765 crate::expressions::WindowFunction {
5766 this: Expression::Function(Box::new(Function::new(
5767 "ROW_NUMBER".to_string(),
5768 vec![],
5769 ))),
5770 over: crate::expressions::Over {
5771 window_name: None,
5772 partition_by: vec![],
5773 order_by: vec![crate::expressions::Ordered {
5774 this: Expression::number(1),
5775 desc: false,
5776 nulls_first: Some(true),
5777 explicit_asc: false,
5778 with_fill: None,
5779 }],
5780 frame: None,
5781 alias: None,
5782 },
5783 keep: None,
5784 inferred_type: None,
5785 },
5786 )),
5787 right: Expression::number(1),
5788 left_comments: Vec::new(),
5789 operator_comments: Vec::new(),
5790 trailing_comments: Vec::new(),
5791 inferred_type: None,
5792 }));
5793
5794 let modded = Expression::Mod(Box::new(BinaryOp {
5795 left: Expression::Paren(Box::new(Paren {
5796 this: row_num,
5797 trailing_comments: Vec::new(),
5798 })),
5799 right: Expression::Literal(Box::new(Literal::Number(range.to_string()))),
5800 left_comments: Vec::new(),
5801 operator_comments: Vec::new(),
5802 trailing_comments: Vec::new(),
5803 inferred_type: None,
5804 }));
5805
5806 if is_signed {
5807 let cond = Expression::Gte(Box::new(BinaryOp {
5809 left: modded.clone(),
5810 right: Expression::Literal(Box::new(Literal::Number(half.to_string()))),
5811 left_comments: Vec::new(),
5812 operator_comments: Vec::new(),
5813 trailing_comments: Vec::new(),
5814 inferred_type: None,
5815 }));
5816 let signed_val = Expression::Sub(Box::new(BinaryOp {
5817 left: modded.clone(),
5818 right: Expression::Literal(Box::new(Literal::Number(range.to_string()))),
5819 left_comments: Vec::new(),
5820 operator_comments: Vec::new(),
5821 trailing_comments: Vec::new(),
5822 inferred_type: None,
5823 }));
5824 Ok(Expression::Paren(Box::new(Paren {
5825 this: Expression::Case(Box::new(Case {
5826 operand: None,
5827 whens: vec![(cond, signed_val)],
5828 else_: Some(modded),
5829 comments: Vec::new(),
5830 inferred_type: None,
5831 })),
5832 trailing_comments: Vec::new(),
5833 })))
5834 } else {
5835 Ok(modded)
5836 }
5837 }
5838
5839 "TABLE" if f.args.len() == 1 => {
5842 let inner = f.args.into_iter().next().unwrap();
5843 if let Expression::Function(ref gen_f) = inner {
5845 if gen_f.name.to_uppercase() == "GENERATOR" {
5846 let mut rowcount = None;
5847 for arg in &gen_f.args {
5848 if let Expression::NamedArgument(na) = arg {
5849 if na.name.name.to_uppercase() == "ROWCOUNT" {
5850 rowcount = Some(na.value.clone());
5851 }
5852 }
5853 }
5854 if let Some(n) = rowcount {
5855 return Ok(Expression::Function(Box::new(Function::new(
5856 "RANGE".to_string(),
5857 vec![n],
5858 ))));
5859 }
5860 }
5861 }
5862 Ok(inner)
5863 }
5864
5865 "GENERATOR" => {
5867 let mut rowcount = None;
5868 for arg in &f.args {
5869 if let Expression::NamedArgument(na) = arg {
5870 if na.name.name.to_uppercase() == "ROWCOUNT" {
5871 rowcount = Some(na.value.clone());
5872 }
5873 }
5874 }
5875 if let Some(n) = rowcount {
5876 Ok(Expression::Function(Box::new(Function::new(
5877 "RANGE".to_string(),
5878 vec![n],
5879 ))))
5880 } else {
5881 Ok(Expression::Function(Box::new(f)))
5882 }
5883 }
5884
5885 "UNIFORM" if f.args.len() == 3 => {
5888 let mut args = f.args;
5889 let low = args.remove(0);
5890 let high = args.remove(0);
5891 let gen = args.remove(0);
5892
5893 let range = Expression::Add(Box::new(BinaryOp {
5894 left: Expression::Sub(Box::new(BinaryOp {
5895 left: high,
5896 right: low.clone(),
5897 left_comments: Vec::new(),
5898 operator_comments: Vec::new(),
5899 trailing_comments: Vec::new(),
5900 inferred_type: None,
5901 })),
5902 right: Expression::number(1),
5903 left_comments: Vec::new(),
5904 operator_comments: Vec::new(),
5905 trailing_comments: Vec::new(),
5906 inferred_type: None,
5907 }));
5908
5909 let random_val = match &gen {
5911 Expression::Rand(_) | Expression::Random(_) => {
5912 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5914 }
5915 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
5916 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5918 }
5919 _ => {
5920 let hash = Expression::Function(Box::new(Function::new(
5922 "HASH".to_string(),
5923 vec![gen],
5924 )));
5925 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
5926 let modded = Expression::Mod(Box::new(BinaryOp {
5927 left: abs_hash,
5928 right: Expression::number(1000000),
5929 left_comments: Vec::new(),
5930 operator_comments: Vec::new(),
5931 trailing_comments: Vec::new(),
5932 inferred_type: None,
5933 }));
5934 let paren_modded = Expression::Paren(Box::new(Paren {
5935 this: modded,
5936 trailing_comments: Vec::new(),
5937 }));
5938 Expression::Div(Box::new(BinaryOp {
5939 left: paren_modded,
5940 right: Expression::Literal(Box::new(Literal::Number(
5941 "1000000.0".to_string(),
5942 ))),
5943 left_comments: Vec::new(),
5944 operator_comments: Vec::new(),
5945 trailing_comments: Vec::new(),
5946 inferred_type: None,
5947 }))
5948 }
5949 };
5950
5951 let inner = Expression::Function(Box::new(Function::new(
5952 "FLOOR".to_string(),
5953 vec![Expression::Add(Box::new(BinaryOp {
5954 left: low,
5955 right: Expression::Mul(Box::new(BinaryOp {
5956 left: random_val,
5957 right: Expression::Paren(Box::new(Paren {
5958 this: range,
5959 trailing_comments: Vec::new(),
5960 })),
5961 left_comments: Vec::new(),
5962 operator_comments: Vec::new(),
5963 trailing_comments: Vec::new(),
5964 inferred_type: None,
5965 })),
5966 left_comments: Vec::new(),
5967 operator_comments: Vec::new(),
5968 trailing_comments: Vec::new(),
5969 inferred_type: None,
5970 }))],
5971 )));
5972
5973 Ok(Expression::Cast(Box::new(Cast {
5974 this: inner,
5975 to: DataType::BigInt { length: None },
5976 trailing_comments: Vec::new(),
5977 double_colon_syntax: false,
5978 format: None,
5979 default: None,
5980 inferred_type: None,
5981 })))
5982 }
5983
5984 "NORMAL" if f.args.len() == 3 => {
5988 let mut args = f.args;
5989 let mean = args.remove(0);
5990 let stddev = args.remove(0);
5991 let gen = args.remove(0);
5992
5993 let make_seed_random = |seed: Expression| -> Expression {
5995 let hash = Expression::Function(Box::new(Function::new(
5996 "HASH".to_string(),
5997 vec![seed],
5998 )));
5999 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
6000 let modded = Expression::Mod(Box::new(BinaryOp {
6001 left: abs_hash,
6002 right: Expression::number(1000000),
6003 left_comments: Vec::new(),
6004 operator_comments: Vec::new(),
6005 trailing_comments: Vec::new(),
6006 inferred_type: None,
6007 }));
6008 let paren_modded = Expression::Paren(Box::new(Paren {
6009 this: modded,
6010 trailing_comments: Vec::new(),
6011 }));
6012 Expression::Div(Box::new(BinaryOp {
6013 left: paren_modded,
6014 right: Expression::Literal(Box::new(Literal::Number(
6015 "1000000.0".to_string(),
6016 ))),
6017 left_comments: Vec::new(),
6018 operator_comments: Vec::new(),
6019 trailing_comments: Vec::new(),
6020 inferred_type: None,
6021 }))
6022 };
6023
6024 let is_random_no_seed = match &gen {
6026 Expression::Random(_) => true,
6027 Expression::Rand(r) => r.seed.is_none(),
6028 _ => false,
6029 };
6030 let (u1, u2) = if is_random_no_seed {
6031 let u1 =
6033 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
6034 let u2 =
6035 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
6036 (u1, u2)
6037 } else {
6038 let seed = match gen {
6040 Expression::Rand(r) => r.seed.map(|s| *s).unwrap_or(Expression::number(0)),
6041 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
6042 if func.args.len() == 1 {
6043 func.args.into_iter().next().unwrap()
6044 } else {
6045 Expression::number(0)
6046 }
6047 }
6048 other => other,
6049 };
6050 let u1 = make_seed_random(seed.clone());
6051 let seed_plus_1 = Expression::Add(Box::new(BinaryOp {
6052 left: seed,
6053 right: Expression::number(1),
6054 left_comments: Vec::new(),
6055 operator_comments: Vec::new(),
6056 trailing_comments: Vec::new(),
6057 inferred_type: None,
6058 }));
6059 let u2 = make_seed_random(seed_plus_1);
6060 (u1, u2)
6061 };
6062
6063 let greatest = Expression::Greatest(Box::new(VarArgFunc {
6065 expressions: vec![
6066 u1,
6067 Expression::Literal(Box::new(Literal::Number("1e-10".to_string()))),
6068 ],
6069 original_name: None,
6070 inferred_type: None,
6071 }));
6072
6073 let neg2 = Expression::Neg(Box::new(crate::expressions::UnaryOp {
6075 this: Expression::number(2),
6076 inferred_type: None,
6077 }));
6078 let ln_greatest =
6079 Expression::Function(Box::new(Function::new("LN".to_string(), vec![greatest])));
6080 let neg2_times_ln = Expression::Mul(Box::new(BinaryOp {
6081 left: neg2,
6082 right: ln_greatest,
6083 left_comments: Vec::new(),
6084 operator_comments: Vec::new(),
6085 trailing_comments: Vec::new(),
6086 inferred_type: None,
6087 }));
6088 let sqrt_part = Expression::Function(Box::new(Function::new(
6089 "SQRT".to_string(),
6090 vec![neg2_times_ln],
6091 )));
6092
6093 let pi = Expression::Function(Box::new(Function::new("PI".to_string(), vec![])));
6095 let two_pi = Expression::Mul(Box::new(BinaryOp {
6096 left: Expression::number(2),
6097 right: pi,
6098 left_comments: Vec::new(),
6099 operator_comments: Vec::new(),
6100 trailing_comments: Vec::new(),
6101 inferred_type: None,
6102 }));
6103 let two_pi_u2 = Expression::Mul(Box::new(BinaryOp {
6104 left: two_pi,
6105 right: u2,
6106 left_comments: Vec::new(),
6107 operator_comments: Vec::new(),
6108 trailing_comments: Vec::new(),
6109 inferred_type: None,
6110 }));
6111 let cos_part = Expression::Function(Box::new(Function::new(
6112 "COS".to_string(),
6113 vec![two_pi_u2],
6114 )));
6115
6116 let stddev_times_sqrt = Expression::Mul(Box::new(BinaryOp {
6118 left: stddev,
6119 right: sqrt_part,
6120 left_comments: Vec::new(),
6121 operator_comments: Vec::new(),
6122 trailing_comments: Vec::new(),
6123 inferred_type: None,
6124 }));
6125 let inner = Expression::Mul(Box::new(BinaryOp {
6126 left: stddev_times_sqrt,
6127 right: cos_part,
6128 left_comments: Vec::new(),
6129 operator_comments: Vec::new(),
6130 trailing_comments: Vec::new(),
6131 inferred_type: None,
6132 }));
6133 let paren_inner = Expression::Paren(Box::new(Paren {
6134 this: inner,
6135 trailing_comments: Vec::new(),
6136 }));
6137
6138 Ok(Expression::Add(Box::new(BinaryOp {
6140 left: mean,
6141 right: paren_inner,
6142 left_comments: Vec::new(),
6143 operator_comments: Vec::new(),
6144 trailing_comments: Vec::new(),
6145 inferred_type: None,
6146 })))
6147 }
6148
6149 "ZIPF" if f.args.len() == 3 => {
6159 let mut args = f.args;
6160 let s_expr = args.remove(0);
6161 let n_expr = args.remove(0);
6162 let gen_expr = args.remove(0);
6163
6164 let s_sql = Self::expr_to_sql(&s_expr);
6165 let n_sql = Self::expr_to_sql(&n_expr);
6166 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
6167
6168 let rand_sql = if is_random {
6169 format!("SELECT {} AS r", seed_sql)
6170 } else {
6171 format!(
6172 "SELECT (ABS(HASH({})) % 1000000) / 1000000.0 AS r",
6173 seed_sql
6174 )
6175 };
6176
6177 let template = format!(
6178 "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)",
6179 rand_sql, s_sql, n_sql
6180 );
6181
6182 Self::parse_as_subquery(&template)
6183 }
6184
6185 "RANDSTR" if f.args.len() == 2 => {
6187 let mut args = f.args;
6188 let len_expr = args.remove(0);
6189 let gen_expr = args.remove(0);
6190
6191 let len_sql = Self::expr_to_sql(&len_expr);
6192 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
6193
6194 let random_value_sql = if is_random {
6195 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
6196 } else {
6197 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
6198 };
6199
6200 let template = format!(
6201 "SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT {} AS random_value FROM RANGE({}) AS t(i))",
6202 random_value_sql, len_sql
6203 );
6204
6205 Self::parse_as_subquery(&template)
6206 }
6207
6208 "MAP_CAT" if f.args.len() == 2 => {
6210 let mut args = f.args;
6211 let left = Self::normalize_empty_map_expr(args.remove(0));
6212 let right = Self::normalize_empty_map_expr(args.remove(0));
6213 let left_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6214 this: left.clone(),
6215 not: false,
6216 postfix_form: false,
6217 }));
6218 let right_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6219 this: right.clone(),
6220 not: false,
6221 postfix_form: false,
6222 }));
6223 let null_cond = Expression::Or(Box::new(BinaryOp {
6224 left: left_is_null,
6225 right: right_is_null,
6226 left_comments: Vec::new(),
6227 operator_comments: Vec::new(),
6228 trailing_comments: Vec::new(),
6229 inferred_type: None,
6230 }));
6231
6232 let list_concat = Expression::Function(Box::new(Function::new(
6233 "LIST_CONCAT".to_string(),
6234 vec![
6235 Expression::Function(Box::new(Function::new(
6236 "MAP_KEYS".to_string(),
6237 vec![left.clone()],
6238 ))),
6239 Expression::Function(Box::new(Function::new(
6240 "MAP_KEYS".to_string(),
6241 vec![right.clone()],
6242 ))),
6243 ],
6244 )));
6245 let list_distinct = Expression::Function(Box::new(Function::new(
6246 "LIST_DISTINCT".to_string(),
6247 vec![list_concat],
6248 )));
6249
6250 let k_ident = Identifier::new("__k");
6251 let k_ref = Expression::boxed_column(Column {
6252 table: None,
6253 name: k_ident.clone(),
6254 join_mark: false,
6255 trailing_comments: Vec::new(),
6256 span: None,
6257 inferred_type: None,
6258 });
6259 let right_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
6260 this: right.clone(),
6261 index: k_ref.clone(),
6262 }));
6263 let left_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
6264 this: left.clone(),
6265 index: k_ref.clone(),
6266 }));
6267 let key_value = Expression::Coalesce(Box::new(VarArgFunc {
6268 expressions: vec![right_key, left_key],
6269 original_name: None,
6270 inferred_type: None,
6271 }));
6272 let struct_pack = Expression::Function(Box::new(Function::new(
6273 "STRUCT_PACK".to_string(),
6274 vec![
6275 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
6276 name: Identifier::new("key"),
6277 value: k_ref.clone(),
6278 separator: crate::expressions::NamedArgSeparator::ColonEq,
6279 })),
6280 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
6281 name: Identifier::new("value"),
6282 value: key_value,
6283 separator: crate::expressions::NamedArgSeparator::ColonEq,
6284 })),
6285 ],
6286 )));
6287 let lambda_k = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6288 parameters: vec![k_ident],
6289 body: struct_pack,
6290 colon: false,
6291 parameter_types: Vec::new(),
6292 }));
6293
6294 let list_transform = Expression::Function(Box::new(Function::new(
6295 "LIST_TRANSFORM".to_string(),
6296 vec![list_distinct, lambda_k],
6297 )));
6298
6299 let x_ident = Identifier::new("__x");
6300 let x_ref = Expression::boxed_column(Column {
6301 table: None,
6302 name: x_ident.clone(),
6303 join_mark: false,
6304 trailing_comments: Vec::new(),
6305 span: None,
6306 inferred_type: None,
6307 });
6308 let x_value = Expression::Dot(Box::new(crate::expressions::DotAccess {
6309 this: x_ref,
6310 field: Identifier::new("value"),
6311 }));
6312 let x_value_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6313 this: x_value,
6314 not: false,
6315 postfix_form: false,
6316 }));
6317 let lambda_x = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6318 parameters: vec![x_ident],
6319 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
6320 this: x_value_is_null,
6321 inferred_type: None,
6322 })),
6323 colon: false,
6324 parameter_types: Vec::new(),
6325 }));
6326
6327 let list_filter = Expression::Function(Box::new(Function::new(
6328 "LIST_FILTER".to_string(),
6329 vec![list_transform, lambda_x],
6330 )));
6331 let merged_map = Expression::Function(Box::new(Function::new(
6332 "MAP_FROM_ENTRIES".to_string(),
6333 vec![list_filter],
6334 )));
6335
6336 Ok(Expression::Case(Box::new(Case {
6337 operand: None,
6338 whens: vec![(null_cond, Expression::Null(crate::expressions::Null))],
6339 else_: Some(merged_map),
6340 comments: Vec::new(),
6341 inferred_type: None,
6342 })))
6343 }
6344
6345 "MINHASH" if f.args.len() == 2 => {
6347 let mut args = f.args;
6348 let num_perm = args.remove(0);
6349 let value = args.remove(0);
6350
6351 let num_perm_sql = Self::expr_to_sql(&num_perm);
6352 let value_sql = Self::expr_to_sql(&value);
6353
6354 let template = format!(
6355 "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))",
6356 value = value_sql,
6357 num_perm = num_perm_sql
6358 );
6359
6360 Self::parse_as_subquery(&template)
6361 }
6362
6363 "MINHASH_COMBINE" if f.args.len() == 1 => {
6365 let sig_sql = Self::expr_to_sql(&f.args[0]);
6366 let template = format!(
6367 "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)",
6368 sig = sig_sql
6369 );
6370 Self::parse_as_subquery(&template)
6371 }
6372
6373 "APPROXIMATE_SIMILARITY" if f.args.len() == 1 => {
6375 let sig_sql = Self::expr_to_sql(&f.args[0]);
6376 let template = format!(
6377 "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)",
6378 sig = sig_sql
6379 );
6380 Self::parse_as_subquery(&template)
6381 }
6382
6383 "ARRAYS_ZIP" if !f.args.is_empty() => {
6385 let args = f.args;
6386 let n = args.len();
6387 let is_null = |expr: Expression| {
6388 Expression::IsNull(Box::new(crate::expressions::IsNull {
6389 this: expr,
6390 not: false,
6391 postfix_form: false,
6392 }))
6393 };
6394 let length_of = |expr: Expression| {
6395 Expression::Function(Box::new(Function::new("LENGTH".to_string(), vec![expr])))
6396 };
6397 let eq_zero = |expr: Expression| {
6398 Expression::Eq(Box::new(BinaryOp {
6399 left: expr,
6400 right: Expression::number(0),
6401 left_comments: Vec::new(),
6402 operator_comments: Vec::new(),
6403 trailing_comments: Vec::new(),
6404 inferred_type: None,
6405 }))
6406 };
6407 let and_expr = |left: Expression, right: Expression| {
6408 Expression::And(Box::new(BinaryOp {
6409 left,
6410 right,
6411 left_comments: Vec::new(),
6412 operator_comments: Vec::new(),
6413 trailing_comments: Vec::new(),
6414 inferred_type: None,
6415 }))
6416 };
6417 let or_expr = |left: Expression, right: Expression| {
6418 Expression::Or(Box::new(BinaryOp {
6419 left,
6420 right,
6421 left_comments: Vec::new(),
6422 operator_comments: Vec::new(),
6423 trailing_comments: Vec::new(),
6424 inferred_type: None,
6425 }))
6426 };
6427
6428 let null_cond = args.iter().cloned().map(is_null).reduce(or_expr).unwrap();
6429 let empty_cond = args
6430 .iter()
6431 .cloned()
6432 .map(|a| eq_zero(length_of(a)))
6433 .reduce(and_expr)
6434 .unwrap();
6435
6436 let null_struct = Expression::Struct(Box::new(Struct {
6437 fields: (1..=n)
6438 .map(|i| {
6439 (
6440 Some(format!("${}", i)),
6441 Expression::Null(crate::expressions::Null),
6442 )
6443 })
6444 .collect(),
6445 }));
6446 let empty_result = Expression::Array(Box::new(crate::expressions::Array {
6447 expressions: vec![null_struct],
6448 }));
6449
6450 let range_upper = if n == 1 {
6451 length_of(args[0].clone())
6452 } else {
6453 let length_null_cond = args
6454 .iter()
6455 .cloned()
6456 .map(|a| is_null(length_of(a)))
6457 .reduce(or_expr)
6458 .unwrap();
6459 let greatest_len = Expression::Greatest(Box::new(VarArgFunc {
6460 expressions: args.iter().cloned().map(length_of).collect(),
6461 original_name: None,
6462 inferred_type: None,
6463 }));
6464 Expression::Case(Box::new(Case {
6465 operand: None,
6466 whens: vec![(length_null_cond, Expression::Null(crate::expressions::Null))],
6467 else_: Some(greatest_len),
6468 comments: Vec::new(),
6469 inferred_type: None,
6470 }))
6471 };
6472
6473 let range_expr = Expression::Function(Box::new(Function::new(
6474 "RANGE".to_string(),
6475 vec![Expression::number(0), range_upper],
6476 )));
6477
6478 let i_ident = Identifier::new("__i");
6479 let i_ref = Expression::boxed_column(Column {
6480 table: None,
6481 name: i_ident.clone(),
6482 join_mark: false,
6483 trailing_comments: Vec::new(),
6484 span: None,
6485 inferred_type: None,
6486 });
6487 let i_plus_one = Expression::Add(Box::new(BinaryOp {
6488 left: i_ref,
6489 right: Expression::number(1),
6490 left_comments: Vec::new(),
6491 operator_comments: Vec::new(),
6492 trailing_comments: Vec::new(),
6493 inferred_type: None,
6494 }));
6495 let empty_array = Expression::Array(Box::new(crate::expressions::Array {
6496 expressions: vec![],
6497 }));
6498 let zipped_struct = Expression::Struct(Box::new(Struct {
6499 fields: args
6500 .iter()
6501 .enumerate()
6502 .map(|(i, a)| {
6503 let coalesced = Expression::Coalesce(Box::new(VarArgFunc {
6504 expressions: vec![a.clone(), empty_array.clone()],
6505 original_name: None,
6506 inferred_type: None,
6507 }));
6508 let item =
6509 Expression::Subscript(Box::new(crate::expressions::Subscript {
6510 this: coalesced,
6511 index: i_plus_one.clone(),
6512 }));
6513 (Some(format!("${}", i + 1)), item)
6514 })
6515 .collect(),
6516 }));
6517 let lambda_i = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6518 parameters: vec![i_ident],
6519 body: zipped_struct,
6520 colon: false,
6521 parameter_types: Vec::new(),
6522 }));
6523 let zipped_result = Expression::Function(Box::new(Function::new(
6524 "LIST_TRANSFORM".to_string(),
6525 vec![range_expr, lambda_i],
6526 )));
6527
6528 Ok(Expression::Case(Box::new(Case {
6529 operand: None,
6530 whens: vec![
6531 (null_cond, Expression::Null(crate::expressions::Null)),
6532 (empty_cond, empty_result),
6533 ],
6534 else_: Some(zipped_result),
6535 comments: Vec::new(),
6536 inferred_type: None,
6537 })))
6538 }
6539
6540 "STRTOK" if f.args.len() == 3 => {
6544 let mut args = f.args.into_iter();
6545 let str_arg = args.next().unwrap();
6546 let delim_arg = args.next().unwrap();
6547 let pos_arg = args.next().unwrap();
6548
6549 let empty_str = || Expression::string("".to_string());
6551 let null_expr = || Expression::Null(crate::expressions::Null);
6553
6554 let when1_cond = Expression::And(Box::new(BinaryOp::new(
6556 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6557 Expression::Eq(Box::new(BinaryOp::new(str_arg.clone(), empty_str()))),
6558 )));
6559
6560 let when2_cond = Expression::And(Box::new(BinaryOp::new(
6562 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6563 Expression::Eq(Box::new(BinaryOp::new(
6564 pos_arg.clone(),
6565 Expression::number(1),
6566 ))),
6567 )));
6568
6569 let when3_cond =
6571 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str())));
6572
6573 let when4_cond = Expression::Lt(Box::new(BinaryOp::new(
6575 pos_arg.clone(),
6576 Expression::number(0),
6577 )));
6578
6579 let str_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6581 this: str_arg.clone(),
6582 not: false,
6583 postfix_form: false,
6584 }));
6585 let delim_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6586 this: delim_arg.clone(),
6587 not: false,
6588 postfix_form: false,
6589 }));
6590 let pos_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
6591 this: pos_arg.clone(),
6592 not: false,
6593 postfix_form: false,
6594 }));
6595 let when5_cond = Expression::Or(Box::new(BinaryOp::new(
6596 Expression::Or(Box::new(BinaryOp::new(str_is_null, delim_is_null))),
6597 pos_is_null,
6598 )));
6599
6600 let regex_replace = Expression::Function(Box::new(Function::new(
6605 "REGEXP_REPLACE".to_string(),
6606 vec![
6607 delim_arg.clone(),
6608 Expression::string(r"([\[\]^.\-*+?(){}|$\\])".to_string()),
6609 Expression::string(r"\\\1".to_string()),
6610 Expression::string("g".to_string()),
6611 ],
6612 )));
6613
6614 let concat_regex = Expression::DPipe(Box::new(crate::expressions::DPipe {
6616 this: Box::new(Expression::DPipe(Box::new(crate::expressions::DPipe {
6617 this: Box::new(Expression::string("[".to_string())),
6618 expression: Box::new(regex_replace),
6619 safe: None,
6620 }))),
6621 expression: Box::new(Expression::string("]".to_string())),
6622 safe: None,
6623 }));
6624
6625 let inner_case = Expression::Case(Box::new(Case {
6626 operand: None,
6627 whens: vec![(
6628 Expression::Eq(Box::new(BinaryOp::new(delim_arg.clone(), empty_str()))),
6629 empty_str(),
6630 )],
6631 else_: Some(concat_regex),
6632 comments: Vec::new(),
6633 inferred_type: None,
6634 }));
6635
6636 let regexp_split = Expression::Function(Box::new(Function::new(
6638 "REGEXP_SPLIT_TO_ARRAY".to_string(),
6639 vec![str_arg.clone(), inner_case],
6640 )));
6641
6642 let lambda = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6644 parameters: vec![Identifier::new("x".to_string())],
6645 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
6646 this: Expression::Eq(Box::new(BinaryOp::new(
6647 Expression::boxed_column(Column {
6648 table: None,
6649 name: Identifier::new("x".to_string()),
6650 join_mark: false,
6651 trailing_comments: Vec::new(),
6652 span: None,
6653 inferred_type: None,
6654 }),
6655 empty_str(),
6656 ))),
6657 inferred_type: None,
6658 })),
6659 colon: false,
6660 parameter_types: Vec::new(),
6661 }));
6662
6663 let list_filter = Expression::Function(Box::new(Function::new(
6665 "LIST_FILTER".to_string(),
6666 vec![regexp_split, lambda],
6667 )));
6668
6669 let subscripted = Expression::Subscript(Box::new(crate::expressions::Subscript {
6671 this: list_filter,
6672 index: pos_arg.clone(),
6673 }));
6674
6675 Ok(Expression::Case(Box::new(Case {
6676 operand: None,
6677 whens: vec![
6678 (when1_cond, null_expr()),
6679 (when2_cond, str_arg.clone()),
6680 (when3_cond, null_expr()),
6681 (when4_cond, null_expr()),
6682 (when5_cond, null_expr()),
6683 ],
6684 else_: Some(subscripted),
6685 comments: Vec::new(),
6686 inferred_type: None,
6687 })))
6688 }
6689
6690 _ => Ok(Expression::Function(Box::new(f))),
6692 }
6693 }
6694
6695 fn convert_snowflake_date_format(&self, fmt: Expression) -> Expression {
6697 match fmt {
6698 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6699 let Literal::String(s) = lit.as_ref() else {
6700 unreachable!()
6701 };
6702 let converted = Self::snowflake_to_strptime(&s);
6703 Expression::Literal(Box::new(Literal::String(converted)))
6704 }
6705 _ => fmt,
6706 }
6707 }
6708
6709 fn convert_snowflake_time_format(&self, fmt: Expression) -> Expression {
6711 match fmt {
6712 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6713 let Literal::String(s) = lit.as_ref() else {
6714 unreachable!()
6715 };
6716 let converted = Self::snowflake_to_strptime(&s);
6717 Expression::Literal(Box::new(Literal::String(converted)))
6718 }
6719 _ => fmt,
6720 }
6721 }
6722
6723 fn snowflake_to_strptime(s: &str) -> String {
6726 let mut result = String::new();
6727 let chars: Vec<char> = s.chars().collect();
6728 let len = chars.len();
6729 let mut i = 0;
6730 while i < len {
6731 let remaining = &s[i..];
6732 let remaining_upper: String =
6733 remaining.chars().take(8).collect::<String>().to_uppercase();
6734
6735 if remaining_upper.starts_with("HH24MISS") {
6737 result.push_str("%H%M%S");
6738 i += 8;
6739 } else if remaining_upper.starts_with("MMMM") {
6740 result.push_str("%B");
6741 i += 4;
6742 } else if remaining_upper.starts_with("YYYY") {
6743 result.push_str("%Y");
6744 i += 4;
6745 } else if remaining_upper.starts_with("YY") {
6746 result.push_str("%y");
6747 i += 2;
6748 } else if remaining_upper.starts_with("MON") {
6749 result.push_str("%b");
6750 i += 3;
6751 } else if remaining_upper.starts_with("HH24") {
6752 result.push_str("%H");
6753 i += 4;
6754 } else if remaining_upper.starts_with("HH12") {
6755 result.push_str("%I");
6756 i += 4;
6757 } else if remaining_upper.starts_with("HH") {
6758 result.push_str("%I");
6759 i += 2;
6760 } else if remaining_upper.starts_with("MISS") {
6761 result.push_str("%M%S");
6762 i += 4;
6763 } else if remaining_upper.starts_with("MI") {
6764 result.push_str("%M");
6765 i += 2;
6766 } else if remaining_upper.starts_with("MM") {
6767 result.push_str("%m");
6768 i += 2;
6769 } else if remaining_upper.starts_with("DD") {
6770 result.push_str("%d");
6771 i += 2;
6772 } else if remaining_upper.starts_with("DY") {
6773 result.push_str("%a");
6774 i += 2;
6775 } else if remaining_upper.starts_with("SS") {
6776 result.push_str("%S");
6777 i += 2;
6778 } else if remaining_upper.starts_with("FF") {
6779 let ff_pos = i + 2;
6782 if ff_pos < len && chars[ff_pos].is_ascii_digit() {
6783 let digit = chars[ff_pos].to_digit(10).unwrap_or(6);
6784 if digit >= 7 {
6785 result.push_str("%n");
6786 } else {
6787 result.push_str("%f");
6788 }
6789 i += 3; } else {
6791 result.push_str("%f");
6792 i += 2;
6793 }
6794 } else if remaining_upper.starts_with("PM") || remaining_upper.starts_with("AM") {
6795 result.push_str("%p");
6796 i += 2;
6797 } else if remaining_upper.starts_with("TZH") {
6798 result.push_str("%z");
6799 i += 3;
6800 } else if remaining_upper.starts_with("TZM") {
6801 i += 3;
6803 } else {
6804 result.push(chars[i]);
6805 i += 1;
6806 }
6807 }
6808 result
6809 }
6810
6811 fn convert_bq_to_strptime_format(&self, fmt: Expression) -> Expression {
6814 match fmt {
6815 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6816 let Literal::String(s) = lit.as_ref() else {
6817 unreachable!()
6818 };
6819 let converted = s.replace("%E6S", "%S.%f").replace("%E*S", "%S.%f");
6820 Expression::Literal(Box::new(Literal::String(converted)))
6821 }
6822 _ => fmt,
6823 }
6824 }
6825
6826 fn transform_date_part(&self, args: Vec<Expression>) -> Result<Expression> {
6828 let mut args = args;
6829 let unit_expr = args.remove(0);
6830 let date_expr = args.remove(0);
6831 let unit_name = match &unit_expr {
6832 Expression::Column(c) => c.name.name.to_uppercase(),
6833 Expression::Identifier(i) => i.name.to_uppercase(),
6834 Expression::Var(v) => v.this.to_uppercase(),
6835 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6836 let Literal::String(s) = lit.as_ref() else {
6837 unreachable!()
6838 };
6839 s.to_uppercase()
6840 }
6841 _ => {
6842 return Ok(Expression::Function(Box::new(Function::new(
6843 "DATE_PART".to_string(),
6844 vec![unit_expr, date_expr],
6845 ))))
6846 }
6847 };
6848 match unit_name.as_str() {
6849 "EPOCH_SECOND" | "EPOCH" => Ok(Expression::Cast(Box::new(Cast {
6850 this: Expression::Function(Box::new(Function::new(
6851 "EPOCH".to_string(),
6852 vec![date_expr],
6853 ))),
6854 to: DataType::BigInt { length: None },
6855 trailing_comments: Vec::new(),
6856 double_colon_syntax: false,
6857 format: None,
6858 default: None,
6859 inferred_type: None,
6860 }))),
6861 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Ok(Expression::Function(Box::new(
6862 Function::new("EPOCH_MS".to_string(), vec![date_expr]),
6863 ))),
6864 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Ok(Expression::Function(Box::new(
6865 Function::new("EPOCH_US".to_string(), vec![date_expr]),
6866 ))),
6867 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Ok(Expression::Function(Box::new(
6868 Function::new("EPOCH_NS".to_string(), vec![date_expr]),
6869 ))),
6870 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Extract(Box::new(
6871 crate::expressions::ExtractFunc {
6872 this: date_expr,
6873 field: crate::expressions::DateTimeField::Custom("ISODOW".to_string()),
6874 },
6875 ))),
6876 "YEAROFWEEK" | "YEAROFWEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6877 this: Expression::Function(Box::new(Function::new(
6878 "STRFTIME".to_string(),
6879 vec![
6880 date_expr,
6881 Expression::Literal(Box::new(Literal::String("%G".to_string()))),
6882 ],
6883 ))),
6884 to: DataType::Int {
6885 length: None,
6886 integer_spelling: false,
6887 },
6888 trailing_comments: Vec::new(),
6889 double_colon_syntax: false,
6890 format: None,
6891 default: None,
6892 inferred_type: None,
6893 }))),
6894 "WEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6895 this: Expression::Function(Box::new(Function::new(
6896 "STRFTIME".to_string(),
6897 vec![
6898 date_expr,
6899 Expression::Literal(Box::new(Literal::String("%V".to_string()))),
6900 ],
6901 ))),
6902 to: DataType::Int {
6903 length: None,
6904 integer_spelling: false,
6905 },
6906 trailing_comments: Vec::new(),
6907 double_colon_syntax: false,
6908 format: None,
6909 default: None,
6910 inferred_type: None,
6911 }))),
6912 "NANOSECOND" | "NANOSECONDS" | "NS" => Ok(Expression::Cast(Box::new(Cast {
6913 this: Expression::Function(Box::new(Function::new(
6914 "STRFTIME".to_string(),
6915 vec![
6916 Expression::Cast(Box::new(Cast {
6917 this: date_expr,
6918 to: DataType::Custom {
6919 name: "TIMESTAMP_NS".to_string(),
6920 },
6921 trailing_comments: Vec::new(),
6922 double_colon_syntax: false,
6923 format: None,
6924 default: None,
6925 inferred_type: None,
6926 })),
6927 Expression::Literal(Box::new(Literal::String("%n".to_string()))),
6928 ],
6929 ))),
6930 to: DataType::BigInt { length: None },
6931 trailing_comments: Vec::new(),
6932 double_colon_syntax: false,
6933 format: None,
6934 default: None,
6935 inferred_type: None,
6936 }))),
6937 "DAYOFMONTH" => Ok(Expression::Extract(Box::new(
6938 crate::expressions::ExtractFunc {
6939 this: date_expr,
6940 field: crate::expressions::DateTimeField::Day,
6941 },
6942 ))),
6943 _ => {
6944 let field = match unit_name.as_str() {
6945 "YEAR" | "YY" | "YYYY" => crate::expressions::DateTimeField::Year,
6946 "MONTH" | "MON" | "MM" => crate::expressions::DateTimeField::Month,
6947 "DAY" | "DD" | "D" => crate::expressions::DateTimeField::Day,
6948 "HOUR" | "HH" => crate::expressions::DateTimeField::Hour,
6949 "MINUTE" | "MI" | "MIN" => crate::expressions::DateTimeField::Minute,
6950 "SECOND" | "SEC" | "SS" => crate::expressions::DateTimeField::Second,
6951 "MILLISECOND" | "MS" => crate::expressions::DateTimeField::Millisecond,
6952 "MICROSECOND" | "US" => crate::expressions::DateTimeField::Microsecond,
6953 "QUARTER" | "QTR" => crate::expressions::DateTimeField::Quarter,
6954 "WEEK" | "WK" => crate::expressions::DateTimeField::Week,
6955 "DAYOFWEEK" | "DOW" => crate::expressions::DateTimeField::DayOfWeek,
6956 "DAYOFYEAR" | "DOY" => crate::expressions::DateTimeField::DayOfYear,
6957 "TIMEZONE_HOUR" => crate::expressions::DateTimeField::TimezoneHour,
6958 "TIMEZONE_MINUTE" => crate::expressions::DateTimeField::TimezoneMinute,
6959 _ => crate::expressions::DateTimeField::Custom(unit_name),
6960 };
6961 Ok(Expression::Extract(Box::new(
6962 crate::expressions::ExtractFunc {
6963 this: date_expr,
6964 field,
6965 },
6966 )))
6967 }
6968 }
6969 }
6970
6971 fn transform_dateadd(&self, args: Vec<Expression>) -> Result<Expression> {
6973 let mut args = args;
6974 let unit_expr = args.remove(0);
6975 let amount = args.remove(0);
6976 let date = args.remove(0);
6977 let unit_name = match &unit_expr {
6978 Expression::Column(c) => c.name.name.to_uppercase(),
6979 Expression::Identifier(i) => i.name.to_uppercase(),
6980 Expression::Var(v) => v.this.to_uppercase(),
6981 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
6982 let Literal::String(s) = lit.as_ref() else {
6983 unreachable!()
6984 };
6985 s.to_uppercase()
6986 }
6987 _ => String::new(),
6988 };
6989 if unit_name == "NANOSECOND" || unit_name == "NS" {
6990 let epoch_ns = Expression::Function(Box::new(Function::new(
6991 "EPOCH_NS".to_string(),
6992 vec![Expression::Cast(Box::new(Cast {
6993 this: date,
6994 to: DataType::Custom {
6995 name: "TIMESTAMP_NS".to_string(),
6996 },
6997 trailing_comments: Vec::new(),
6998 double_colon_syntax: false,
6999 format: None,
7000 default: None,
7001 inferred_type: None,
7002 }))],
7003 )));
7004 return Ok(Expression::Function(Box::new(Function::new(
7005 "MAKE_TIMESTAMP_NS".to_string(),
7006 vec![Expression::Add(Box::new(BinaryOp {
7007 left: epoch_ns,
7008 right: amount,
7009 left_comments: Vec::new(),
7010 operator_comments: Vec::new(),
7011 trailing_comments: Vec::new(),
7012 inferred_type: None,
7013 }))],
7014 ))));
7015 }
7016 let (interval_unit, multiplied_amount) = match unit_name.as_str() {
7017 "YEAR" | "YY" | "YYYY" => (IntervalUnit::Year, amount),
7018 "MONTH" | "MON" | "MM" => (IntervalUnit::Month, amount),
7019 "DAY" | "DD" | "D" => (IntervalUnit::Day, amount),
7020 "HOUR" | "HH" => (IntervalUnit::Hour, amount),
7021 "MINUTE" | "MI" | "MIN" => (IntervalUnit::Minute, amount),
7022 "SECOND" | "SEC" | "SS" => (IntervalUnit::Second, amount),
7023 "MILLISECOND" | "MS" => (IntervalUnit::Millisecond, amount),
7024 "MICROSECOND" | "US" => (IntervalUnit::Microsecond, amount),
7025 "WEEK" | "WK" => (
7026 IntervalUnit::Day,
7027 Expression::Mul(Box::new(BinaryOp {
7028 left: amount,
7029 right: Expression::number(7),
7030 left_comments: Vec::new(),
7031 operator_comments: Vec::new(),
7032 trailing_comments: Vec::new(),
7033 inferred_type: None,
7034 })),
7035 ),
7036 "QUARTER" | "QTR" => (
7037 IntervalUnit::Month,
7038 Expression::Mul(Box::new(BinaryOp {
7039 left: amount,
7040 right: Expression::number(3),
7041 left_comments: Vec::new(),
7042 operator_comments: Vec::new(),
7043 trailing_comments: Vec::new(),
7044 inferred_type: None,
7045 })),
7046 ),
7047 _ => (IntervalUnit::Day, amount),
7048 };
7049 Ok(Expression::Add(Box::new(BinaryOp {
7050 left: date,
7051 right: Expression::Interval(Box::new(Interval {
7052 this: Some(multiplied_amount),
7053 unit: Some(IntervalUnitSpec::Simple {
7054 unit: interval_unit,
7055 use_plural: false,
7056 }),
7057 })),
7058 left_comments: Vec::new(),
7059 operator_comments: Vec::new(),
7060 trailing_comments: Vec::new(),
7061 inferred_type: None,
7062 })))
7063 }
7064
7065 fn transform_datediff(&self, args: Vec<Expression>) -> Result<Expression> {
7067 let mut args = args;
7068 let unit_expr = args.remove(0);
7069 let start = args.remove(0);
7070 let end = args.remove(0);
7071 let unit_name = match &unit_expr {
7072 Expression::Column(c) => c.name.name.to_uppercase(),
7073 Expression::Identifier(i) => i.name.to_uppercase(),
7074 Expression::Var(v) => v.this.to_uppercase(),
7075 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
7076 let Literal::String(s) = lit.as_ref() else {
7077 unreachable!()
7078 };
7079 s.to_uppercase()
7080 }
7081 _ => String::new(),
7082 };
7083 if unit_name == "NANOSECOND" || unit_name == "NS" {
7084 let epoch_end = Expression::Function(Box::new(Function::new(
7085 "EPOCH_NS".to_string(),
7086 vec![Expression::Cast(Box::new(Cast {
7087 this: end,
7088 to: DataType::Custom {
7089 name: "TIMESTAMP_NS".to_string(),
7090 },
7091 trailing_comments: Vec::new(),
7092 double_colon_syntax: false,
7093 format: None,
7094 default: None,
7095 inferred_type: None,
7096 }))],
7097 )));
7098 let epoch_start = Expression::Function(Box::new(Function::new(
7099 "EPOCH_NS".to_string(),
7100 vec![Expression::Cast(Box::new(Cast {
7101 this: start,
7102 to: DataType::Custom {
7103 name: "TIMESTAMP_NS".to_string(),
7104 },
7105 trailing_comments: Vec::new(),
7106 double_colon_syntax: false,
7107 format: None,
7108 default: None,
7109 inferred_type: None,
7110 }))],
7111 )));
7112 return Ok(Expression::Sub(Box::new(BinaryOp {
7113 left: epoch_end,
7114 right: epoch_start,
7115 left_comments: Vec::new(),
7116 operator_comments: Vec::new(),
7117 trailing_comments: Vec::new(),
7118 inferred_type: None,
7119 })));
7120 }
7121 if unit_name == "WEEK" || unit_name == "WK" {
7122 let trunc_start = Expression::Function(Box::new(Function::new(
7123 "DATE_TRUNC".to_string(),
7124 vec![
7125 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7126 Expression::Cast(Box::new(Cast {
7127 this: start,
7128 to: DataType::Date,
7129 trailing_comments: Vec::new(),
7130 double_colon_syntax: false,
7131 format: None,
7132 default: None,
7133 inferred_type: None,
7134 })),
7135 ],
7136 )));
7137 let trunc_end = Expression::Function(Box::new(Function::new(
7138 "DATE_TRUNC".to_string(),
7139 vec![
7140 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7141 Expression::Cast(Box::new(Cast {
7142 this: end,
7143 to: DataType::Date,
7144 trailing_comments: Vec::new(),
7145 double_colon_syntax: false,
7146 format: None,
7147 default: None,
7148 inferred_type: None,
7149 })),
7150 ],
7151 )));
7152 return Ok(Expression::Function(Box::new(Function::new(
7153 "DATE_DIFF".to_string(),
7154 vec![
7155 Expression::Literal(Box::new(Literal::String("WEEK".to_string()))),
7156 trunc_start,
7157 trunc_end,
7158 ],
7159 ))));
7160 }
7161 let cast_if_string = |e: Expression| -> Expression {
7162 match &e {
7163 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
7164 Expression::Cast(Box::new(Cast {
7165 this: e,
7166 to: DataType::Date,
7167 trailing_comments: Vec::new(),
7168 double_colon_syntax: false,
7169 format: None,
7170 default: None,
7171 inferred_type: None,
7172 }))
7173 }
7174 _ => e,
7175 }
7176 };
7177 let start = cast_if_string(start);
7178 let end = cast_if_string(end);
7179 Ok(Expression::Function(Box::new(Function::new(
7180 "DATE_DIFF".to_string(),
7181 vec![
7182 Expression::Literal(Box::new(Literal::String(unit_name))),
7183 start,
7184 end,
7185 ],
7186 ))))
7187 }
7188
7189 fn transform_aggregate_function(
7190 &self,
7191 f: Box<crate::expressions::AggregateFunction>,
7192 ) -> Result<Expression> {
7193 let name_upper = f.name.to_uppercase();
7194 match name_upper.as_str() {
7195 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
7197 Function::new("LISTAGG".to_string(), f.args),
7198 ))),
7199
7200 "LISTAGG" => Ok(Expression::AggregateFunction(f)),
7202
7203 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
7205 Function::new("LISTAGG".to_string(), f.args),
7206 ))),
7207
7208 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
7210 "list".to_string(),
7211 f.args,
7212 )))),
7213
7214 "LOGICAL_OR" if !f.args.is_empty() => {
7216 let arg = f.args.into_iter().next().unwrap();
7217 Ok(Expression::Function(Box::new(Function::new(
7218 "BOOL_OR".to_string(),
7219 vec![Expression::Cast(Box::new(crate::expressions::Cast {
7220 this: arg,
7221 to: crate::expressions::DataType::Boolean,
7222 trailing_comments: Vec::new(),
7223 double_colon_syntax: false,
7224 format: None,
7225 default: None,
7226 inferred_type: None,
7227 }))],
7228 ))))
7229 }
7230
7231 "LOGICAL_AND" if !f.args.is_empty() => {
7233 let arg = f.args.into_iter().next().unwrap();
7234 Ok(Expression::Function(Box::new(Function::new(
7235 "BOOL_AND".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 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
7250 "SKEWNESS".to_string(),
7251 f.args,
7252 )))),
7253
7254 "REGR_VALX" if f.args.len() == 2 => {
7256 let mut args = f.args;
7257 let y = args.remove(0);
7258 let x = args.remove(0);
7259 Ok(Expression::Case(Box::new(Case {
7260 operand: None,
7261 whens: vec![(
7262 Expression::IsNull(Box::new(crate::expressions::IsNull {
7263 this: y,
7264 not: false,
7265 postfix_form: false,
7266 })),
7267 Expression::Cast(Box::new(Cast {
7268 this: Expression::Null(crate::expressions::Null),
7269 to: DataType::Double {
7270 precision: None,
7271 scale: None,
7272 },
7273 trailing_comments: Vec::new(),
7274 double_colon_syntax: false,
7275 format: None,
7276 default: None,
7277 inferred_type: None,
7278 })),
7279 )],
7280 else_: Some(x),
7281 comments: Vec::new(),
7282 inferred_type: None,
7283 })))
7284 }
7285
7286 "REGR_VALY" if f.args.len() == 2 => {
7288 let mut args = f.args;
7289 let y = args.remove(0);
7290 let x = args.remove(0);
7291 Ok(Expression::Case(Box::new(Case {
7292 operand: None,
7293 whens: vec![(
7294 Expression::IsNull(Box::new(crate::expressions::IsNull {
7295 this: x,
7296 not: false,
7297 postfix_form: false,
7298 })),
7299 Expression::Cast(Box::new(Cast {
7300 this: Expression::Null(crate::expressions::Null),
7301 to: DataType::Double {
7302 precision: None,
7303 scale: None,
7304 },
7305 trailing_comments: Vec::new(),
7306 double_colon_syntax: false,
7307 format: None,
7308 default: None,
7309 inferred_type: None,
7310 })),
7311 )],
7312 else_: Some(y),
7313 comments: Vec::new(),
7314 inferred_type: None,
7315 })))
7316 }
7317
7318 "BOOLAND_AGG" if !f.args.is_empty() => {
7320 let arg = f.args.into_iter().next().unwrap();
7321 Ok(Expression::Function(Box::new(Function::new(
7322 "BOOL_AND".to_string(),
7323 vec![Expression::Cast(Box::new(Cast {
7324 this: arg,
7325 to: DataType::Boolean,
7326 trailing_comments: Vec::new(),
7327 double_colon_syntax: false,
7328 format: None,
7329 default: None,
7330 inferred_type: None,
7331 }))],
7332 ))))
7333 }
7334
7335 "BOOLOR_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_OR".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 "BOOLXOR_AGG" if !f.args.is_empty() => {
7354 let arg = f.args.into_iter().next().unwrap();
7355 Ok(Expression::Eq(Box::new(BinaryOp {
7356 left: Expression::Function(Box::new(Function::new(
7357 "COUNT_IF".to_string(),
7358 vec![Expression::Cast(Box::new(Cast {
7359 this: arg,
7360 to: DataType::Boolean,
7361 trailing_comments: Vec::new(),
7362 double_colon_syntax: false,
7363 format: None,
7364 default: None,
7365 inferred_type: None,
7366 }))],
7367 ))),
7368 right: Expression::number(1),
7369 left_comments: Vec::new(),
7370 operator_comments: Vec::new(),
7371 trailing_comments: Vec::new(),
7372 inferred_type: None,
7373 })))
7374 }
7375
7376 "MAX_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
7378 crate::expressions::AggregateFunction {
7379 name: "ARG_MAX".to_string(),
7380 ..(*f)
7381 },
7382 ))),
7383
7384 "MIN_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
7386 crate::expressions::AggregateFunction {
7387 name: "ARG_MIN".to_string(),
7388 ..(*f)
7389 },
7390 ))),
7391
7392 "CORR" if f.args.len() == 2 => Ok(Expression::AggregateFunction(f)),
7394
7395 "BITMAP_CONSTRUCT_AGG" if f.args.len() == 1 => {
7397 let v_sql = Self::expr_to_sql(&f.args[0]);
7398
7399 let template = format!(
7400 "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))",
7401 v = v_sql
7402 );
7403
7404 Self::parse_as_subquery(&template)
7405 }
7406
7407 _ => Ok(Expression::AggregateFunction(f)),
7409 }
7410 }
7411
7412 fn convert_format_to_duckdb(expr: &Expression) -> Expression {
7416 if let Expression::Literal(lit) = expr {
7417 if let Literal::String(s) = lit.as_ref() {
7418 let duckdb_fmt = Self::presto_to_duckdb_format(s);
7419 Expression::Literal(Box::new(Literal::String(duckdb_fmt)))
7420 } else {
7421 expr.clone()
7422 }
7423 } else {
7424 expr.clone()
7425 }
7426 }
7427
7428 fn presto_to_duckdb_format(fmt: &str) -> String {
7430 let mut result = String::new();
7431 let chars: Vec<char> = fmt.chars().collect();
7432 let mut i = 0;
7433 while i < chars.len() {
7434 if chars[i] == '%' && i + 1 < chars.len() {
7435 match chars[i + 1] {
7436 'i' => {
7437 result.push_str("%M");
7439 i += 2;
7440 }
7441 'T' => {
7442 result.push_str("%H:%M:%S");
7444 i += 2;
7445 }
7446 'F' => {
7447 result.push_str("%Y-%m-%d");
7449 i += 2;
7450 }
7451 _ => {
7452 result.push('%');
7453 result.push(chars[i + 1]);
7454 i += 2;
7455 }
7456 }
7457 } else {
7458 result.push(chars[i]);
7459 i += 1;
7460 }
7461 }
7462 result
7463 }
7464}
7465
7466#[cfg(test)]
7467mod tests {
7468 use super::*;
7469 use crate::dialects::Dialect;
7470
7471 fn transpile_to_duckdb(sql: &str) -> String {
7472 let dialect = Dialect::get(DialectType::Generic);
7473 let result = dialect
7474 .transpile_to(sql, DialectType::DuckDB)
7475 .expect("Transpile failed");
7476 result[0].clone()
7477 }
7478
7479 #[test]
7480 fn test_ifnull_to_coalesce() {
7481 let result = transpile_to_duckdb("SELECT IFNULL(a, b)");
7482 assert!(
7483 result.contains("COALESCE"),
7484 "Expected COALESCE, got: {}",
7485 result
7486 );
7487 }
7488
7489 #[test]
7490 fn test_nvl_to_coalesce() {
7491 let result = transpile_to_duckdb("SELECT NVL(a, b)");
7492 assert!(
7493 result.contains("COALESCE"),
7494 "Expected COALESCE, got: {}",
7495 result
7496 );
7497 }
7498
7499 #[test]
7500 fn test_basic_select() {
7501 let result = transpile_to_duckdb("SELECT a, b FROM users WHERE id = 1");
7502 assert!(result.contains("SELECT"));
7503 assert!(result.contains("FROM users"));
7504 }
7505
7506 #[test]
7507 fn test_group_concat_to_listagg() {
7508 let result = transpile_to_duckdb("SELECT GROUP_CONCAT(name)");
7509 assert!(
7510 result.contains("LISTAGG"),
7511 "Expected LISTAGG, got: {}",
7512 result
7513 );
7514 }
7515
7516 #[test]
7517 fn test_listagg_preserved() {
7518 let result = transpile_to_duckdb("SELECT LISTAGG(name)");
7519 assert!(
7520 result.contains("LISTAGG"),
7521 "Expected LISTAGG, got: {}",
7522 result
7523 );
7524 }
7525
7526 #[test]
7527 fn test_date_format_to_strftime() {
7528 let result = transpile_to_duckdb("SELECT DATE_FORMAT(d, '%Y-%m-%d')");
7529 assert!(
7531 result.to_uppercase().contains("STRFTIME"),
7532 "Expected STRFTIME, got: {}",
7533 result
7534 );
7535 }
7536
7537 #[test]
7538 fn test_regexp_like_to_regexp_matches() {
7539 let result = transpile_to_duckdb("SELECT REGEXP_LIKE(name, 'pattern')");
7540 assert!(
7542 result.to_uppercase().contains("REGEXP_MATCHES"),
7543 "Expected REGEXP_MATCHES, got: {}",
7544 result
7545 );
7546 }
7547
7548 #[test]
7549 fn test_double_quote_identifiers() {
7550 let dialect = Dialect::get(DialectType::DuckDB);
7552 let config = dialect.generator_config();
7553 assert_eq!(config.identifier_quote, '"');
7554 }
7555
7556 fn duckdb_identity(sql: &str) -> String {
7558 let dialect = Dialect::get(DialectType::DuckDB);
7559 let ast = dialect.parse(sql).expect("Parse failed");
7560 let transformed = dialect.transform(ast[0].clone()).expect("Transform failed");
7561 dialect.generate(&transformed).expect("Generate failed")
7562 }
7563
7564 #[test]
7565 fn test_interval_quoting() {
7566 let result = duckdb_identity("SELECT DATE_ADD(CAST('2020-01-01' AS DATE), INTERVAL 1 DAY)");
7568 assert_eq!(
7569 result, "SELECT CAST('2020-01-01' AS DATE) + INTERVAL '1' DAY",
7570 "Interval value should be quoted as string"
7571 );
7572 }
7573
7574 #[test]
7575 fn test_struct_pack_to_curly_brace() {
7576 let result = duckdb_identity("CAST([STRUCT_PACK(a := 1)] AS STRUCT(a BIGINT)[])");
7578 assert_eq!(
7579 result, "CAST([{'a': 1}] AS STRUCT(a BIGINT)[])",
7580 "STRUCT_PACK should be transformed to curly brace notation"
7581 );
7582 }
7583
7584 #[test]
7585 fn test_struct_pack_nested() {
7586 let result = duckdb_identity("CAST([[STRUCT_PACK(a := 1)]] AS STRUCT(a BIGINT)[][])");
7588 assert_eq!(
7589 result, "CAST([[{'a': 1}]] AS STRUCT(a BIGINT)[][])",
7590 "Nested STRUCT_PACK should be transformed"
7591 );
7592 }
7593
7594 #[test]
7595 fn test_struct_pack_cast() {
7596 let result = duckdb_identity("STRUCT_PACK(a := 'b')::json");
7598 assert_eq!(
7599 result, "CAST({'a': 'b'} AS JSON)",
7600 "STRUCT_PACK with cast should be transformed"
7601 );
7602 }
7603
7604 #[test]
7605 fn test_list_value_to_bracket() {
7606 let result = duckdb_identity("SELECT LIST_VALUE(1)[i]");
7608 assert_eq!(
7609 result, "SELECT [1][i]",
7610 "LIST_VALUE should be transformed to bracket notation"
7611 );
7612 }
7613
7614 #[test]
7615 fn test_list_value_in_struct_literal() {
7616 let result = duckdb_identity("{'x': LIST_VALUE(1)[i]}");
7618 assert_eq!(
7619 result, "{'x': [1][i]}",
7620 "LIST_VALUE inside struct literal should be transformed"
7621 );
7622 }
7623
7624 #[test]
7625 fn test_struct_pack_simple() {
7626 let result = duckdb_identity("SELECT STRUCT_PACK(a := 1)");
7628 eprintln!("STRUCT_PACK result: {}", result);
7629 assert!(
7630 result.contains("{"),
7631 "Expected curly brace, got: {}",
7632 result
7633 );
7634 }
7635
7636 #[test]
7637 fn test_not_in_position() {
7638 let result = duckdb_identity(
7641 "SELECT col FROM t WHERE JSON_EXTRACT_STRING(col, '$.id') NOT IN ('b')",
7642 );
7643 assert_eq!(
7644 result, "SELECT col FROM t WHERE NOT (col ->> '$.id') IN ('b')",
7645 "NOT IN should have NOT moved outside and JSON expression wrapped"
7646 );
7647 }
7648
7649 #[test]
7650 fn test_unnest_comma_join_to_join_on_true() {
7651 let result = duckdb_identity(
7653 "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",
7654 );
7655 assert_eq!(
7656 result,
7657 "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",
7658 "Comma-join with UNNEST should become JOIN ON TRUE"
7659 );
7660 }
7661}