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