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