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