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