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