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