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 "TODAY" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1866
1867 "CURDATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1869
1870 "GET_CURRENT_TIME" => Ok(Expression::CurrentTime(crate::expressions::CurrentTime {
1872 precision: None,
1873 })),
1874
1875 "CURRENT_LOCALTIMESTAMP" => {
1877 Ok(Expression::Localtimestamp(Box::new(
1878 crate::expressions::Localtimestamp { this: None },
1879 )))
1880 }
1881
1882 "REGEXP_EXTRACT_ALL" if f.args.len() == 3 => {
1884 if matches!(&f.args[2], Expression::Literal(crate::expressions::Literal::Number(n)) if n == "0") {
1886 Ok(Expression::Function(Box::new(Function::new(
1887 "REGEXP_EXTRACT_ALL".to_string(),
1888 vec![f.args[0].clone(), f.args[1].clone()],
1889 ))))
1890 } else {
1891 Ok(Expression::Function(Box::new(Function::new(
1892 "REGEXP_EXTRACT_ALL".to_string(),
1893 f.args,
1894 ))))
1895 }
1896 }
1897
1898 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1900
1901 "TO_DATE" if f.args.len() == 1 => {
1903 let arg = f.args.into_iter().next().unwrap();
1904 Ok(Expression::Cast(Box::new(Cast {
1905 this: arg,
1906 to: DataType::Date,
1907 trailing_comments: Vec::new(),
1908 double_colon_syntax: false,
1909 format: None,
1910 default: None,
1911 inferred_type: None,
1912 })))
1913 }
1914
1915 "DATE_FORMAT" if f.args.len() >= 2 => {
1919 let mut args = f.args;
1920 args[1] = Self::convert_format_to_duckdb(&args[1]);
1921 Ok(Expression::Function(Box::new(Function::new(
1922 "STRFTIME".to_string(),
1923 args,
1924 ))))
1925 }
1926
1927 "DATE_PARSE" if f.args.len() >= 2 => {
1929 let mut args = f.args;
1930 args[1] = Self::convert_format_to_duckdb(&args[1]);
1931 Ok(Expression::Function(Box::new(Function::new(
1932 "STRPTIME".to_string(),
1933 args,
1934 ))))
1935 }
1936
1937 "FORMAT_DATE" if f.args.len() >= 2 => {
1939 let mut args = f.args;
1940 args[1] = Self::convert_format_to_duckdb(&args[1]);
1941 Ok(Expression::Function(Box::new(Function::new(
1942 "STRFTIME".to_string(),
1943 args,
1944 ))))
1945 }
1946
1947 "TO_CHAR" if f.args.len() >= 2 => {
1949 let mut args = f.args;
1950 args[1] = Self::convert_format_to_duckdb(&args[1]);
1951 Ok(Expression::Function(Box::new(Function::new(
1952 "STRFTIME".to_string(),
1953 args,
1954 ))))
1955 }
1956
1957 "EPOCH_MS" => Ok(Expression::Function(Box::new(f))),
1959
1960 "EPOCH" => Ok(Expression::Function(Box::new(f))),
1962
1963 "FROM_UNIXTIME" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1965 Function::new("TO_TIMESTAMP".to_string(), f.args),
1966 ))),
1967
1968 "UNIX_TIMESTAMP" => Ok(Expression::Function(Box::new(Function::new(
1970 "EPOCH".to_string(),
1971 f.args,
1972 )))),
1973
1974 "JSON_EXTRACT" if f.args.len() == 2 => {
1976 let mut args = f.args;
1977 let path = args.pop().unwrap();
1978 let this = args.pop().unwrap();
1979 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
1980 this,
1981 path,
1982 returning: None,
1983 arrow_syntax: true,
1984 hash_arrow_syntax: false,
1985 wrapper_option: None,
1986 quotes_option: None,
1987 on_scalar_string: false,
1988 on_error: None,
1989 })))
1990 }
1991
1992 "JSON_EXTRACT_STRING" if f.args.len() == 2 => {
1994 let mut args = f.args;
1995 let path = args.pop().unwrap();
1996 let this = args.pop().unwrap();
1997 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
1998 this,
1999 path,
2000 returning: None,
2001 arrow_syntax: true,
2002 hash_arrow_syntax: false,
2003 wrapper_option: None,
2004 quotes_option: None,
2005 on_scalar_string: false,
2006 on_error: None,
2007 })))
2008 }
2009
2010 "ARRAY_CONSTRUCT" => Ok(Expression::Function(Box::new(Function::new(
2012 "list_value".to_string(),
2013 f.args,
2014 )))),
2015
2016 "ARRAY" => {
2019 let has_query = f
2021 .args
2022 .iter()
2023 .any(|a| matches!(a, Expression::Subquery(_) | Expression::Select(_)));
2024 if has_query {
2025 Ok(Expression::Function(Box::new(Function::new(
2027 "ARRAY".to_string(),
2028 f.args,
2029 ))))
2030 } else {
2031 Ok(Expression::Function(Box::new(Function::new(
2032 "list_value".to_string(),
2033 f.args,
2034 ))))
2035 }
2036 }
2037
2038 "LIST_VALUE" => Ok(Expression::Array(Box::new(crate::expressions::Array {
2040 expressions: f.args,
2041 }))),
2042
2043 "ARRAY_AGG" => Ok(Expression::Function(Box::new(Function::new(
2045 "list".to_string(),
2046 f.args,
2047 )))),
2048
2049 "LIST_CONTAINS" | "ARRAY_CONTAINS" => Ok(Expression::Function(Box::new(
2051 Function::new("ARRAY_CONTAINS".to_string(), f.args),
2052 ))),
2053
2054 "ARRAY_SIZE" | "CARDINALITY" => Ok(Expression::Function(Box::new(Function::new(
2056 "ARRAY_LENGTH".to_string(),
2057 f.args,
2058 )))),
2059
2060 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
2062 f.args.into_iter().next().unwrap(),
2063 )))),
2064
2065 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
2067 this: f.args.into_iter().next().unwrap(),
2068 decimals: None,
2069 to: None,
2070 }))),
2071
2072 "LOGICAL_OR" if f.args.len() == 1 => {
2074 let arg = f.args.into_iter().next().unwrap();
2075 Ok(Expression::Function(Box::new(Function::new(
2076 "BOOL_OR".to_string(),
2077 vec![Expression::Cast(Box::new(crate::expressions::Cast {
2078 this: arg,
2079 to: crate::expressions::DataType::Boolean,
2080 trailing_comments: Vec::new(),
2081 double_colon_syntax: false,
2082 format: None,
2083 default: None,
2084 inferred_type: None,
2085 }))],
2086 ))))
2087 }
2088
2089 "LOGICAL_AND" if f.args.len() == 1 => {
2091 let arg = f.args.into_iter().next().unwrap();
2092 Ok(Expression::Function(Box::new(Function::new(
2093 "BOOL_AND".to_string(),
2094 vec![Expression::Cast(Box::new(crate::expressions::Cast {
2095 this: arg,
2096 to: crate::expressions::DataType::Boolean,
2097 trailing_comments: Vec::new(),
2098 double_colon_syntax: false,
2099 format: None,
2100 default: None,
2101 inferred_type: None,
2102 }))],
2103 ))))
2104 }
2105
2106 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(Function::new(
2108 "REGEXP_MATCHES".to_string(),
2109 f.args,
2110 )))),
2111
2112 "POSITION" => Ok(Expression::Function(Box::new(f))),
2114
2115 "SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2117 "STR_SPLIT".to_string(),
2118 f.args,
2119 )))),
2120
2121 "STRING_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2123 "STR_SPLIT".to_string(),
2124 f.args,
2125 )))),
2126
2127 "STRTOK_TO_ARRAY" => Ok(Expression::Function(Box::new(Function::new(
2129 "STR_SPLIT".to_string(),
2130 f.args,
2131 )))),
2132
2133 "REGEXP_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2135 "STR_SPLIT_REGEX".to_string(),
2136 f.args,
2137 )))),
2138
2139 "EDITDIST3" => Ok(Expression::Function(Box::new(Function::new(
2141 "LEVENSHTEIN".to_string(),
2142 f.args,
2143 )))),
2144
2145 "JSON_EXTRACT_PATH" if f.args.len() >= 2 => {
2147 let mut args = f.args;
2148 let this = args.remove(0);
2149 let path = args.remove(0);
2150 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2151 this,
2152 path,
2153 returning: None,
2154 arrow_syntax: true,
2155 hash_arrow_syntax: false,
2156 wrapper_option: None,
2157 quotes_option: None,
2158 on_scalar_string: false,
2159 on_error: None,
2160 })))
2161 }
2162
2163 "JSON_EXTRACT_PATH_TEXT" if f.args.len() >= 2 => {
2165 let mut args = f.args;
2166 let this = args.remove(0);
2167 let path = args.remove(0);
2168 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
2169 this,
2170 path,
2171 returning: None,
2172 arrow_syntax: true,
2173 hash_arrow_syntax: false,
2174 wrapper_option: None,
2175 quotes_option: None,
2176 on_scalar_string: false,
2177 on_error: None,
2178 })))
2179 }
2180
2181 "DATE_ADD" if f.args.len() == 2 => {
2183 let mut args = f.args;
2184 let date = args.remove(0);
2185 let interval = args.remove(0);
2186 Ok(Expression::Add(Box::new(BinaryOp {
2187 left: date,
2188 right: interval,
2189 left_comments: Vec::new(),
2190 operator_comments: Vec::new(),
2191 trailing_comments: Vec::new(),
2192 inferred_type: None,
2193 })))
2194 }
2195
2196 "DATE_SUB" if f.args.len() == 2 => {
2198 let mut args = f.args;
2199 let date = args.remove(0);
2200 let interval = args.remove(0);
2201 Ok(Expression::Sub(Box::new(BinaryOp {
2202 left: date,
2203 right: interval,
2204 left_comments: Vec::new(),
2205 operator_comments: Vec::new(),
2206 trailing_comments: Vec::new(),
2207 inferred_type: None,
2208 })))
2209 }
2210
2211 "RANGE" if f.args.len() == 1 => {
2213 let mut new_args = vec![Expression::number(0)];
2214 new_args.extend(f.args);
2215 Ok(Expression::Function(Box::new(Function::new(
2216 "RANGE".to_string(),
2217 new_args,
2218 ))))
2219 }
2220
2221 "GENERATE_SERIES" if f.args.len() == 1 => {
2223 let mut new_args = vec![Expression::number(0)];
2224 new_args.extend(f.args);
2225 Ok(Expression::Function(Box::new(Function::new(
2226 "GENERATE_SERIES".to_string(),
2227 new_args,
2228 ))))
2229 }
2230
2231 "REGEXP_EXTRACT" if f.args.len() == 3 => {
2234 let drop_group = match &f.args[2] {
2236 Expression::Literal(Literal::Number(n)) => n == "0",
2237 _ => false,
2238 };
2239 if drop_group {
2240 Ok(Expression::Function(Box::new(Function::new(
2241 "REGEXP_EXTRACT".to_string(),
2242 vec![f.args[0].clone(), f.args[1].clone()],
2243 ))))
2244 } else {
2245 Ok(Expression::Function(Box::new(f)))
2246 }
2247 }
2248
2249 "STRUCT_PACK" => {
2251 let mut fields = Vec::new();
2252 for arg in f.args {
2253 match arg {
2254 Expression::NamedArgument(na) => {
2255 fields.push((Some(na.name.name.clone()), na.value));
2256 }
2257 other => {
2259 fields.push((None, other));
2260 }
2261 }
2262 }
2263 Ok(Expression::Struct(Box::new(Struct { fields })))
2264 }
2265
2266 "REPLACE" if f.args.len() == 2 => {
2268 let mut args = f.args;
2269 args.push(Expression::Literal(Literal::String(String::new())));
2270 Ok(Expression::Function(Box::new(Function::new(
2271 "REPLACE".to_string(),
2272 args,
2273 ))))
2274 }
2275
2276 "TO_UNIXTIME" => Ok(Expression::Function(Box::new(Function::new(
2278 "EPOCH".to_string(),
2279 f.args,
2280 )))),
2281
2282 "FROM_ISO8601_TIMESTAMP" if f.args.len() == 1 => {
2284 use crate::expressions::{Cast, DataType};
2285 Ok(Expression::Cast(Box::new(Cast {
2286 this: f.args.into_iter().next().unwrap(),
2287 to: DataType::Timestamp {
2288 precision: None,
2289 timezone: true,
2290 },
2291 trailing_comments: Vec::new(),
2292 double_colon_syntax: false,
2293 format: None,
2294 default: None,
2295 inferred_type: None,
2296 })))
2297 }
2298
2299 "APPROX_DISTINCT" => {
2301 let args = if f.args.len() > 1 {
2303 vec![f.args.into_iter().next().unwrap()]
2304 } else {
2305 f.args
2306 };
2307 Ok(Expression::Function(Box::new(Function::new(
2308 "APPROX_COUNT_DISTINCT".to_string(),
2309 args,
2310 ))))
2311 }
2312
2313 "ARRAY_SORT" => {
2315 let args = vec![f.args.into_iter().next().unwrap()];
2316 Ok(Expression::Function(Box::new(Function::new(
2317 "ARRAY_SORT".to_string(),
2318 args,
2319 ))))
2320 }
2321
2322 "TO_UTF8" => Ok(Expression::Function(Box::new(Function::new(
2324 "ENCODE".to_string(),
2325 f.args,
2326 )))),
2327
2328 "FROM_UTF8" => Ok(Expression::Function(Box::new(Function::new(
2330 "DECODE".to_string(),
2331 f.args,
2332 )))),
2333
2334 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
2336 "ANY_VALUE".to_string(),
2337 f.args,
2338 )))),
2339
2340 "MAX_BY" => Ok(Expression::Function(Box::new(Function::new(
2342 "ARG_MAX".to_string(),
2343 f.args,
2344 )))),
2345
2346 "MIN_BY" => Ok(Expression::Function(Box::new(Function::new(
2348 "ARG_MIN".to_string(),
2349 f.args,
2350 )))),
2351
2352 "IFF" if f.args.len() == 3 => {
2354 let mut args = f.args;
2355 let cond = args.remove(0);
2356 let true_val = args.remove(0);
2357 let false_val = args.remove(0);
2358 Ok(Expression::Case(Box::new(Case {
2359 operand: None,
2360 whens: vec![(cond, true_val)],
2361 else_: Some(false_val),
2362 comments: Vec::new(),
2363 inferred_type: None,
2364 })))
2365 }
2366 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
2367 "SKEWNESS".to_string(),
2368 f.args,
2369 )))),
2370 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2371 "VARIANCE".to_string(),
2372 f.args,
2373 )))),
2374 "VARIANCE_POP" => Ok(Expression::Function(Box::new(Function::new(
2375 "VAR_POP".to_string(),
2376 f.args,
2377 )))),
2378 "REGR_VALX" if f.args.len() == 2 => {
2379 let mut args = f.args;
2380 let y = args.remove(0);
2381 let x = args.remove(0);
2382 Ok(Expression::Case(Box::new(Case {
2383 operand: None,
2384 whens: vec![(
2385 Expression::IsNull(Box::new(crate::expressions::IsNull {
2386 this: y,
2387 not: false,
2388 postfix_form: false,
2389 })),
2390 Expression::Cast(Box::new(Cast {
2391 this: Expression::Null(crate::expressions::Null),
2392 to: DataType::Double {
2393 precision: None,
2394 scale: None,
2395 },
2396 trailing_comments: Vec::new(),
2397 double_colon_syntax: false,
2398 format: None,
2399 default: None,
2400 inferred_type: None,
2401 })),
2402 )],
2403 else_: Some(x),
2404 comments: Vec::new(),
2405 inferred_type: None,
2406 })))
2407 }
2408 "REGR_VALY" if f.args.len() == 2 => {
2409 let mut args = f.args;
2410 let y = args.remove(0);
2411 let x = args.remove(0);
2412 Ok(Expression::Case(Box::new(Case {
2413 operand: None,
2414 whens: vec![(
2415 Expression::IsNull(Box::new(crate::expressions::IsNull {
2416 this: x,
2417 not: false,
2418 postfix_form: false,
2419 })),
2420 Expression::Cast(Box::new(Cast {
2421 this: Expression::Null(crate::expressions::Null),
2422 to: DataType::Double {
2423 precision: None,
2424 scale: None,
2425 },
2426 trailing_comments: Vec::new(),
2427 double_colon_syntax: false,
2428 format: None,
2429 default: None,
2430 inferred_type: None,
2431 })),
2432 )],
2433 else_: Some(y),
2434 comments: Vec::new(),
2435 inferred_type: None,
2436 })))
2437 }
2438 "BOOLNOT" if f.args.len() == 1 => {
2439 let arg = f.args.into_iter().next().unwrap();
2440 let rounded = Expression::Function(Box::new(Function::new(
2442 "ROUND".to_string(),
2443 vec![arg, Expression::number(0)],
2444 )));
2445 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
2446 this: Expression::Paren(Box::new(Paren {
2447 this: rounded,
2448 trailing_comments: Vec::new(),
2449 })),
2450 inferred_type: None,
2451 })))
2452 }
2453 "BITMAP_BIT_POSITION" if f.args.len() == 1 => {
2454 let n = f.args.into_iter().next().unwrap();
2455 let case_expr = Expression::Case(Box::new(Case {
2456 operand: None,
2457 whens: vec![(
2458 Expression::Gt(Box::new(BinaryOp {
2459 left: n.clone(),
2460 right: Expression::number(0),
2461 left_comments: Vec::new(),
2462 operator_comments: Vec::new(),
2463 trailing_comments: Vec::new(),
2464 inferred_type: None,
2465 })),
2466 Expression::Sub(Box::new(BinaryOp {
2467 left: n.clone(),
2468 right: Expression::number(1),
2469 left_comments: Vec::new(),
2470 operator_comments: Vec::new(),
2471 trailing_comments: Vec::new(),
2472 inferred_type: None,
2473 })),
2474 )],
2475 else_: Some(Expression::Abs(Box::new(UnaryFunc {
2476 this: n,
2477 original_name: None,
2478 inferred_type: None,
2479 }))),
2480 comments: Vec::new(),
2481 inferred_type: None,
2482 }));
2483 Ok(Expression::Mod(Box::new(BinaryOp {
2484 left: Expression::Paren(Box::new(Paren {
2485 this: case_expr,
2486 trailing_comments: Vec::new(),
2487 })),
2488 right: Expression::number(32768),
2489 left_comments: Vec::new(),
2490 operator_comments: Vec::new(),
2491 trailing_comments: Vec::new(),
2492 inferred_type: None,
2493 })))
2494 }
2495 "GREATEST" | "LEAST" => Ok(Expression::Function(Box::new(f))),
2497 "GREATEST_IGNORE_NULLS" => Ok(Expression::Greatest(Box::new(VarArgFunc {
2498 expressions: f.args,
2499 original_name: None,
2500 inferred_type: None,
2501 }))),
2502 "LEAST_IGNORE_NULLS" => Ok(Expression::Least(Box::new(VarArgFunc {
2503 expressions: f.args,
2504 original_name: None,
2505 inferred_type: None,
2506 }))),
2507 "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
2508 "JSON".to_string(),
2509 f.args,
2510 )))),
2511 "OBJECT_CONSTRUCT_KEEP_NULL" => {
2512 Ok(Expression::Function(Box::new(Function::new(
2514 "JSON_OBJECT".to_string(),
2515 f.args,
2516 ))))
2517 }
2518 "OBJECT_CONSTRUCT" => {
2519 let args = f.args;
2521 if args.is_empty() {
2522 Ok(Expression::Function(Box::new(Function::new(
2524 "STRUCT_PACK".to_string(),
2525 vec![],
2526 ))))
2527 } else {
2528 let mut fields = Vec::new();
2530 let mut i = 0;
2531 while i + 1 < args.len() {
2532 let key = &args[i];
2533 let value = args[i + 1].clone();
2534 let key_name = match key {
2535 Expression::Literal(Literal::String(s)) => Some(s.clone()),
2536 _ => None,
2537 };
2538 fields.push((key_name, value));
2539 i += 2;
2540 }
2541 Ok(Expression::Struct(Box::new(Struct { fields })))
2542 }
2543 }
2544 "IS_NULL_VALUE" if f.args.len() == 1 => {
2545 let arg = f.args.into_iter().next().unwrap();
2546 Ok(Expression::Eq(Box::new(BinaryOp {
2547 left: Expression::Function(Box::new(Function::new(
2548 "JSON_TYPE".to_string(),
2549 vec![arg],
2550 ))),
2551 right: Expression::Literal(Literal::String("NULL".to_string())),
2552 left_comments: Vec::new(),
2553 operator_comments: Vec::new(),
2554 trailing_comments: Vec::new(),
2555 inferred_type: None,
2556 })))
2557 }
2558 "TRY_TO_DOUBLE" | "TRY_TO_NUMBER" | "TRY_TO_NUMERIC" | "TRY_TO_DECIMAL"
2559 if f.args.len() == 1 =>
2560 {
2561 let arg = f.args.into_iter().next().unwrap();
2562 Ok(Expression::TryCast(Box::new(Cast {
2563 this: arg,
2564 to: DataType::Double {
2565 precision: None,
2566 scale: None,
2567 },
2568 trailing_comments: Vec::new(),
2569 double_colon_syntax: false,
2570 format: None,
2571 default: None,
2572 inferred_type: None,
2573 })))
2574 }
2575 "TRY_TO_TIME" if f.args.len() == 1 => {
2576 let arg = f.args.into_iter().next().unwrap();
2577 Ok(Expression::TryCast(Box::new(Cast {
2578 this: arg,
2579 to: DataType::Time {
2580 precision: None,
2581 timezone: false,
2582 },
2583 trailing_comments: Vec::new(),
2584 double_colon_syntax: false,
2585 format: None,
2586 default: None,
2587 inferred_type: None,
2588 })))
2589 }
2590 "TRY_TO_TIME" if f.args.len() == 2 => {
2591 let mut args = f.args;
2592 let value = args.remove(0);
2593 let fmt = self.convert_snowflake_time_format(args.remove(0));
2594 Ok(Expression::TryCast(Box::new(Cast {
2595 this: Expression::Function(Box::new(Function::new(
2596 "TRY_STRPTIME".to_string(),
2597 vec![value, fmt],
2598 ))),
2599 to: DataType::Time {
2600 precision: None,
2601 timezone: false,
2602 },
2603 trailing_comments: Vec::new(),
2604 double_colon_syntax: false,
2605 format: None,
2606 default: None,
2607 inferred_type: None,
2608 })))
2609 }
2610 "TRY_TO_TIMESTAMP" if f.args.len() == 1 => {
2611 let arg = f.args.into_iter().next().unwrap();
2612 Ok(Expression::TryCast(Box::new(Cast {
2613 this: arg,
2614 to: DataType::Timestamp {
2615 precision: None,
2616 timezone: false,
2617 },
2618 trailing_comments: Vec::new(),
2619 double_colon_syntax: false,
2620 format: None,
2621 default: None,
2622 inferred_type: None,
2623 })))
2624 }
2625 "TRY_TO_TIMESTAMP" if f.args.len() == 2 => {
2626 let mut args = f.args;
2627 let value = args.remove(0);
2628 let fmt = self.convert_snowflake_time_format(args.remove(0));
2629 Ok(Expression::Cast(Box::new(Cast {
2630 this: Expression::Function(Box::new(Function::new(
2631 "TRY_STRPTIME".to_string(),
2632 vec![value, fmt],
2633 ))),
2634 to: DataType::Timestamp {
2635 precision: None,
2636 timezone: false,
2637 },
2638 trailing_comments: Vec::new(),
2639 double_colon_syntax: false,
2640 format: None,
2641 default: None,
2642 inferred_type: None,
2643 })))
2644 }
2645 "TRY_TO_DATE" if f.args.len() == 1 => {
2646 let arg = f.args.into_iter().next().unwrap();
2647 Ok(Expression::TryCast(Box::new(Cast {
2648 this: arg,
2649 to: DataType::Date,
2650 trailing_comments: Vec::new(),
2651 double_colon_syntax: false,
2652 format: None,
2653 default: None,
2654 inferred_type: None,
2655 })))
2656 }
2657 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Function(Box::new(Function::new(
2658 "ISODOW".to_string(),
2659 f.args,
2660 )))),
2661 "YEAROFWEEK" | "YEAROFWEEKISO" if f.args.len() == 1 => {
2662 let arg = f.args.into_iter().next().unwrap();
2663 Ok(Expression::Extract(Box::new(
2664 crate::expressions::ExtractFunc {
2665 this: arg,
2666 field: crate::expressions::DateTimeField::Custom("ISOYEAR".to_string()),
2667 },
2668 )))
2669 }
2670 "WEEKISO" => Ok(Expression::Function(Box::new(Function::new(
2671 "WEEKOFYEAR".to_string(),
2672 f.args,
2673 )))),
2674 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 3 => {
2675 let args_ref = &f.args;
2676 let all_in_range = if let (Some(h_val), Some(m_val), Some(s_val)) = (
2678 Self::extract_number_value(&args_ref[0]),
2679 Self::extract_number_value(&args_ref[1]),
2680 Self::extract_number_value(&args_ref[2]),
2681 ) {
2682 h_val >= 0.0
2683 && h_val < 24.0
2684 && m_val >= 0.0
2685 && m_val < 60.0
2686 && s_val >= 0.0
2687 && s_val < 60.0
2688 } else {
2689 false
2690 };
2691 if all_in_range {
2692 Ok(Expression::Function(Box::new(Function::new(
2694 "MAKE_TIME".to_string(),
2695 f.args,
2696 ))))
2697 } else {
2698 let mut args = f.args;
2701 let h = args.remove(0);
2702 let m = args.remove(0);
2703 let s = args.remove(0);
2704 let seconds_expr = Expression::Add(Box::new(BinaryOp {
2705 left: Expression::Add(Box::new(BinaryOp {
2706 left: Expression::Paren(Box::new(Paren {
2707 this: Expression::Mul(Box::new(BinaryOp {
2708 left: h,
2709 right: Expression::number(3600),
2710 left_comments: Vec::new(),
2711 operator_comments: Vec::new(),
2712 trailing_comments: Vec::new(),
2713 inferred_type: None,
2714 })),
2715 trailing_comments: Vec::new(),
2716 })),
2717 right: Expression::Paren(Box::new(Paren {
2718 this: Expression::Mul(Box::new(BinaryOp {
2719 left: m,
2720 right: Expression::number(60),
2721 left_comments: Vec::new(),
2722 operator_comments: Vec::new(),
2723 trailing_comments: Vec::new(),
2724 inferred_type: None,
2725 })),
2726 trailing_comments: Vec::new(),
2727 })),
2728 left_comments: Vec::new(),
2729 operator_comments: Vec::new(),
2730 trailing_comments: Vec::new(),
2731 inferred_type: None,
2732 })),
2733 right: s,
2734 left_comments: Vec::new(),
2735 operator_comments: Vec::new(),
2736 trailing_comments: Vec::new(),
2737 inferred_type: None,
2738 }));
2739 let base_time = Expression::Cast(Box::new(Cast {
2740 this: Expression::Literal(Literal::String("00:00:00".to_string())),
2741 to: DataType::Time {
2742 precision: None,
2743 timezone: false,
2744 },
2745 trailing_comments: Vec::new(),
2746 double_colon_syntax: false,
2747 format: None,
2748 default: None,
2749 inferred_type: None,
2750 }));
2751 Ok(Expression::Add(Box::new(BinaryOp {
2752 left: base_time,
2753 right: Expression::Interval(Box::new(Interval {
2754 this: Some(Expression::Paren(Box::new(crate::expressions::Paren {
2755 this: seconds_expr,
2756 trailing_comments: Vec::new(),
2757 }))),
2758 unit: Some(IntervalUnitSpec::Simple {
2759 unit: IntervalUnit::Second,
2760 use_plural: false,
2761 }),
2762 })),
2763 left_comments: Vec::new(),
2764 operator_comments: Vec::new(),
2765 trailing_comments: Vec::new(),
2766 inferred_type: None,
2767 })))
2768 }
2769 }
2770 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 4 => {
2771 let mut args = f.args;
2772 let h = args.remove(0);
2773 let m = args.remove(0);
2774 let s = args.remove(0);
2775 let ns = args.remove(0);
2776 let seconds_expr = Expression::Add(Box::new(BinaryOp {
2777 left: Expression::Add(Box::new(BinaryOp {
2778 left: Expression::Add(Box::new(BinaryOp {
2779 left: Expression::Paren(Box::new(Paren {
2780 this: Expression::Mul(Box::new(BinaryOp {
2781 left: h,
2782 right: Expression::number(3600),
2783 left_comments: Vec::new(),
2784 operator_comments: Vec::new(),
2785 trailing_comments: Vec::new(),
2786 inferred_type: None,
2787 })),
2788 trailing_comments: Vec::new(),
2789 })),
2790 right: Expression::Paren(Box::new(Paren {
2791 this: Expression::Mul(Box::new(BinaryOp {
2792 left: m,
2793 right: Expression::number(60),
2794 left_comments: Vec::new(),
2795 operator_comments: Vec::new(),
2796 trailing_comments: Vec::new(),
2797 inferred_type: None,
2798 })),
2799 trailing_comments: Vec::new(),
2800 })),
2801 left_comments: Vec::new(),
2802 operator_comments: Vec::new(),
2803 trailing_comments: Vec::new(),
2804 inferred_type: None,
2805 })),
2806 right: s,
2807 left_comments: Vec::new(),
2808 operator_comments: Vec::new(),
2809 trailing_comments: Vec::new(),
2810 inferred_type: None,
2811 })),
2812 right: Expression::Paren(Box::new(Paren {
2813 this: Expression::Div(Box::new(BinaryOp {
2814 left: ns,
2815 right: Expression::Literal(Literal::Number("1000000000.0".to_string())),
2816 left_comments: Vec::new(),
2817 operator_comments: Vec::new(),
2818 trailing_comments: Vec::new(),
2819 inferred_type: None,
2820 })),
2821 trailing_comments: Vec::new(),
2822 })),
2823 left_comments: Vec::new(),
2824 operator_comments: Vec::new(),
2825 trailing_comments: Vec::new(),
2826 inferred_type: None,
2827 }));
2828 let base_time = Expression::Cast(Box::new(Cast {
2829 this: Expression::Literal(Literal::String("00:00:00".to_string())),
2830 to: DataType::Time {
2831 precision: None,
2832 timezone: false,
2833 },
2834 trailing_comments: Vec::new(),
2835 double_colon_syntax: false,
2836 format: None,
2837 default: None,
2838 inferred_type: None,
2839 }));
2840 Ok(Expression::Add(Box::new(BinaryOp {
2841 left: base_time,
2842 right: Expression::Interval(Box::new(Interval {
2843 this: Some(Expression::Paren(Box::new(crate::expressions::Paren {
2844 this: seconds_expr,
2845 trailing_comments: Vec::new(),
2846 }))),
2847 unit: Some(IntervalUnitSpec::Simple {
2848 unit: IntervalUnit::Second,
2849 use_plural: false,
2850 }),
2851 })),
2852 left_comments: Vec::new(),
2853 operator_comments: Vec::new(),
2854 trailing_comments: Vec::new(),
2855 inferred_type: None,
2856 })))
2857 }
2858 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" if f.args.len() == 6 => {
2859 Ok(Expression::Function(Box::new(Function::new(
2860 "MAKE_TIMESTAMP".to_string(),
2861 f.args,
2862 ))))
2863 }
2864 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMP_NTZ_FROM_PARTS"
2865 if f.args.len() == 2 =>
2866 {
2867 let mut args = f.args;
2868 let d = args.remove(0);
2869 let t = args.remove(0);
2870 Ok(Expression::Add(Box::new(BinaryOp {
2871 left: d,
2872 right: t,
2873 left_comments: Vec::new(),
2874 operator_comments: Vec::new(),
2875 trailing_comments: Vec::new(),
2876 inferred_type: None,
2877 })))
2878 }
2879 "TIMESTAMP_LTZ_FROM_PARTS" if f.args.len() == 6 => {
2880 Ok(Expression::Cast(Box::new(Cast {
2881 this: Expression::Function(Box::new(Function::new(
2882 "MAKE_TIMESTAMP".to_string(),
2883 f.args,
2884 ))),
2885 to: DataType::Timestamp {
2886 precision: None,
2887 timezone: true,
2888 },
2889 trailing_comments: Vec::new(),
2890 double_colon_syntax: false,
2891 format: None,
2892 default: None,
2893 inferred_type: None,
2894 })))
2895 }
2896 "TIMESTAMP_TZ_FROM_PARTS" if f.args.len() == 8 => {
2897 let mut args = f.args;
2898 let ts_args = vec![
2899 args.remove(0),
2900 args.remove(0),
2901 args.remove(0),
2902 args.remove(0),
2903 args.remove(0),
2904 args.remove(0),
2905 ];
2906 let _nano = args.remove(0);
2907 let tz = args.remove(0);
2908 Ok(Expression::AtTimeZone(Box::new(
2909 crate::expressions::AtTimeZone {
2910 this: Expression::Function(Box::new(Function::new(
2911 "MAKE_TIMESTAMP".to_string(),
2912 ts_args,
2913 ))),
2914 zone: tz,
2915 },
2916 )))
2917 }
2918 "BOOLAND_AGG" if f.args.len() == 1 => {
2919 let arg = f.args.into_iter().next().unwrap();
2920 Ok(Expression::Function(Box::new(Function::new(
2921 "BOOL_AND".to_string(),
2922 vec![Expression::Cast(Box::new(Cast {
2923 this: arg,
2924 to: DataType::Boolean,
2925 trailing_comments: Vec::new(),
2926 double_colon_syntax: false,
2927 format: None,
2928 default: None,
2929 inferred_type: None,
2930 }))],
2931 ))))
2932 }
2933 "BOOLOR_AGG" if f.args.len() == 1 => {
2934 let arg = f.args.into_iter().next().unwrap();
2935 Ok(Expression::Function(Box::new(Function::new(
2936 "BOOL_OR".to_string(),
2937 vec![Expression::Cast(Box::new(Cast {
2938 this: arg,
2939 to: DataType::Boolean,
2940 trailing_comments: Vec::new(),
2941 double_colon_syntax: false,
2942 format: None,
2943 default: None,
2944 inferred_type: None,
2945 }))],
2946 ))))
2947 }
2948 "NVL2" if f.args.len() == 3 => {
2949 let mut args = f.args;
2950 let a = args.remove(0);
2951 let b = args.remove(0);
2952 let c = args.remove(0);
2953 Ok(Expression::Case(Box::new(Case {
2954 operand: None,
2955 whens: vec![(
2956 Expression::Not(Box::new(crate::expressions::UnaryOp {
2957 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
2958 this: a,
2959 not: false,
2960 postfix_form: false,
2961 })),
2962 inferred_type: None,
2963 })),
2964 b,
2965 )],
2966 else_: Some(c),
2967 comments: Vec::new(),
2968 inferred_type: None,
2969 })))
2970 }
2971 "EQUAL_NULL" if f.args.len() == 2 => {
2972 let mut args = f.args;
2973 let a = args.remove(0);
2974 let b = args.remove(0);
2975 Ok(Expression::NullSafeEq(Box::new(BinaryOp {
2976 left: a,
2977 right: b,
2978 left_comments: Vec::new(),
2979 operator_comments: Vec::new(),
2980 trailing_comments: Vec::new(),
2981 inferred_type: None,
2982 })))
2983 }
2984 "EDITDISTANCE" if f.args.len() == 3 => {
2985 let mut args = f.args;
2987 let a = args.remove(0);
2988 let b = args.remove(0);
2989 let max_dist = args.remove(0);
2990 let lev = Expression::Function(Box::new(Function::new(
2991 "LEVENSHTEIN".to_string(),
2992 vec![a, b],
2993 )));
2994 let lev_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
2995 this: lev.clone(),
2996 not: false,
2997 postfix_form: false,
2998 }));
2999 let max_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
3000 this: max_dist.clone(),
3001 not: false,
3002 postfix_form: false,
3003 }));
3004 let null_check = Expression::Or(Box::new(BinaryOp {
3005 left: lev_is_null,
3006 right: max_is_null,
3007 left_comments: Vec::new(),
3008 operator_comments: Vec::new(),
3009 trailing_comments: Vec::new(),
3010 inferred_type: None,
3011 }));
3012 let least = Expression::Least(Box::new(VarArgFunc {
3013 expressions: vec![lev, max_dist],
3014 original_name: None,
3015 inferred_type: None,
3016 }));
3017 Ok(Expression::Case(Box::new(Case {
3018 operand: None,
3019 whens: vec![(null_check, Expression::Null(crate::expressions::Null))],
3020 else_: Some(least),
3021 comments: Vec::new(),
3022 inferred_type: None,
3023 })))
3024 }
3025 "EDITDISTANCE" => Ok(Expression::Function(Box::new(Function::new(
3026 "LEVENSHTEIN".to_string(),
3027 f.args,
3028 )))),
3029 "BITAND" if f.args.len() == 2 => {
3030 let mut args = f.args;
3031 let left = args.remove(0);
3032 let right = args.remove(0);
3033 let wrap = |e: Expression| -> Expression {
3035 match &e {
3036 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) => {
3037 Expression::Paren(Box::new(Paren {
3038 this: e,
3039 trailing_comments: Vec::new(),
3040 }))
3041 }
3042 _ => e,
3043 }
3044 };
3045 Ok(Expression::BitwiseAnd(Box::new(BinaryOp {
3046 left: wrap(left),
3047 right: wrap(right),
3048 left_comments: Vec::new(),
3049 operator_comments: Vec::new(),
3050 trailing_comments: Vec::new(),
3051 inferred_type: None,
3052 })))
3053 }
3054 "BITOR" if f.args.len() == 2 => {
3055 let mut args = f.args;
3056 let left = args.remove(0);
3057 let right = args.remove(0);
3058 let wrap = |e: Expression| -> Expression {
3060 match &e {
3061 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) => {
3062 Expression::Paren(Box::new(Paren {
3063 this: e,
3064 trailing_comments: Vec::new(),
3065 }))
3066 }
3067 _ => e,
3068 }
3069 };
3070 Ok(Expression::BitwiseOr(Box::new(BinaryOp {
3071 left: wrap(left),
3072 right: wrap(right),
3073 left_comments: Vec::new(),
3074 operator_comments: Vec::new(),
3075 trailing_comments: Vec::new(),
3076 inferred_type: None,
3077 })))
3078 }
3079 "BITXOR" if f.args.len() == 2 => {
3080 let mut args = f.args;
3081 Ok(Expression::BitwiseXor(Box::new(BinaryOp {
3082 left: args.remove(0),
3083 right: args.remove(0),
3084 left_comments: Vec::new(),
3085 operator_comments: Vec::new(),
3086 trailing_comments: Vec::new(),
3087 inferred_type: None,
3088 })))
3089 }
3090 "BITNOT" if f.args.len() == 1 => {
3091 let arg = f.args.into_iter().next().unwrap();
3092 Ok(Expression::BitwiseNot(Box::new(
3093 crate::expressions::UnaryOp {
3094 this: Expression::Paren(Box::new(Paren {
3095 this: arg,
3096 trailing_comments: Vec::new(),
3097 })),
3098 inferred_type: None,
3099 },
3100 )))
3101 }
3102 "BITSHIFTLEFT" if f.args.len() == 2 => {
3103 let mut args = f.args;
3104 let a = args.remove(0);
3105 let b = args.remove(0);
3106 let is_binary = if let Expression::Cast(ref c) = a {
3108 matches!(
3109 &c.to,
3110 DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob
3111 ) || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
3112 } else {
3113 false
3114 };
3115 if is_binary {
3116 let cast_to_bit = Expression::Cast(Box::new(Cast {
3118 this: a,
3119 to: DataType::Custom {
3120 name: "BIT".to_string(),
3121 },
3122 trailing_comments: Vec::new(),
3123 double_colon_syntax: false,
3124 format: None,
3125 default: None,
3126 inferred_type: None,
3127 }));
3128 let shift = Expression::BitwiseLeftShift(Box::new(BinaryOp {
3129 left: cast_to_bit,
3130 right: b,
3131 left_comments: Vec::new(),
3132 operator_comments: Vec::new(),
3133 trailing_comments: Vec::new(),
3134 inferred_type: None,
3135 }));
3136 Ok(Expression::Cast(Box::new(Cast {
3137 this: shift,
3138 to: DataType::Custom {
3139 name: "BLOB".to_string(),
3140 },
3141 trailing_comments: Vec::new(),
3142 double_colon_syntax: false,
3143 format: None,
3144 default: None,
3145 inferred_type: None,
3146 })))
3147 } else {
3148 Ok(Expression::BitwiseLeftShift(Box::new(BinaryOp {
3149 left: Expression::Cast(Box::new(Cast {
3150 this: a,
3151 to: DataType::Custom {
3152 name: "INT128".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 right: b,
3161 left_comments: Vec::new(),
3162 operator_comments: Vec::new(),
3163 trailing_comments: Vec::new(),
3164 inferred_type: None,
3165 })))
3166 }
3167 }
3168 "BITSHIFTRIGHT" if f.args.len() == 2 => {
3169 let mut args = f.args;
3170 let a = args.remove(0);
3171 let b = args.remove(0);
3172 let is_binary = if let Expression::Cast(ref c) = a {
3174 matches!(
3175 &c.to,
3176 DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob
3177 ) || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
3178 } else {
3179 false
3180 };
3181 if is_binary {
3182 let cast_to_bit = Expression::Cast(Box::new(Cast {
3184 this: a,
3185 to: DataType::Custom {
3186 name: "BIT".to_string(),
3187 },
3188 trailing_comments: Vec::new(),
3189 double_colon_syntax: false,
3190 format: None,
3191 default: None,
3192 inferred_type: None,
3193 }));
3194 let shift = Expression::BitwiseRightShift(Box::new(BinaryOp {
3195 left: cast_to_bit,
3196 right: b,
3197 left_comments: Vec::new(),
3198 operator_comments: Vec::new(),
3199 trailing_comments: Vec::new(),
3200 inferred_type: None,
3201 }));
3202 Ok(Expression::Cast(Box::new(Cast {
3203 this: shift,
3204 to: DataType::Custom {
3205 name: "BLOB".to_string(),
3206 },
3207 trailing_comments: Vec::new(),
3208 double_colon_syntax: false,
3209 format: None,
3210 default: None,
3211 inferred_type: None,
3212 })))
3213 } else {
3214 Ok(Expression::BitwiseRightShift(Box::new(BinaryOp {
3215 left: Expression::Cast(Box::new(Cast {
3216 this: a,
3217 to: DataType::Custom {
3218 name: "INT128".to_string(),
3219 },
3220 trailing_comments: Vec::new(),
3221 double_colon_syntax: false,
3222 format: None,
3223 default: None,
3224 inferred_type: None,
3225 })),
3226 right: b,
3227 left_comments: Vec::new(),
3228 operator_comments: Vec::new(),
3229 trailing_comments: Vec::new(),
3230 inferred_type: None,
3231 })))
3232 }
3233 }
3234 "SQUARE" if f.args.len() == 1 => {
3235 let arg = f.args.into_iter().next().unwrap();
3236 Ok(Expression::Function(Box::new(Function::new(
3237 "POWER".to_string(),
3238 vec![arg, Expression::number(2)],
3239 ))))
3240 }
3241 "UUID_STRING" => Ok(Expression::Function(Box::new(Function::new(
3242 "UUID".to_string(),
3243 vec![],
3244 )))),
3245 "ENDSWITH" => Ok(Expression::Function(Box::new(Function::new(
3246 "ENDS_WITH".to_string(),
3247 f.args,
3248 )))),
3249 "REGEXP_REPLACE" if f.args.len() == 2 => {
3253 let mut args = f.args;
3255 args.push(Expression::Literal(Literal::String(String::new())));
3256 Ok(Expression::Function(Box::new(Function::new(
3257 "REGEXP_REPLACE".to_string(),
3258 args,
3259 ))))
3260 }
3261 "DIV0" if f.args.len() == 2 => {
3262 let mut args = f.args;
3263 let a = args.remove(0);
3264 let b = args.remove(0);
3265 Ok(Expression::Case(Box::new(Case {
3266 operand: None,
3267 whens: vec![(
3268 Expression::And(Box::new(BinaryOp {
3269 left: Expression::Eq(Box::new(BinaryOp {
3270 left: b.clone(),
3271 right: Expression::number(0),
3272 left_comments: Vec::new(),
3273 operator_comments: Vec::new(),
3274 trailing_comments: Vec::new(),
3275 inferred_type: None,
3276 })),
3277 right: Expression::Not(Box::new(crate::expressions::UnaryOp {
3278 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3279 this: a.clone(),
3280 not: false,
3281 postfix_form: false,
3282 })),
3283 inferred_type: None,
3284 })),
3285 left_comments: Vec::new(),
3286 operator_comments: Vec::new(),
3287 trailing_comments: Vec::new(),
3288 inferred_type: None,
3289 })),
3290 Expression::number(0),
3291 )],
3292 else_: Some(Expression::Div(Box::new(BinaryOp {
3293 left: a,
3294 right: b,
3295 left_comments: Vec::new(),
3296 operator_comments: Vec::new(),
3297 trailing_comments: Vec::new(),
3298 inferred_type: None,
3299 }))),
3300 comments: Vec::new(),
3301 inferred_type: None,
3302 })))
3303 }
3304 "DIV0NULL" if f.args.len() == 2 => {
3305 let mut args = f.args;
3306 let a = args.remove(0);
3307 let b = args.remove(0);
3308 Ok(Expression::Case(Box::new(Case {
3309 operand: None,
3310 whens: vec![(
3311 Expression::Or(Box::new(BinaryOp {
3312 left: Expression::Eq(Box::new(BinaryOp {
3313 left: b.clone(),
3314 right: Expression::number(0),
3315 left_comments: Vec::new(),
3316 operator_comments: Vec::new(),
3317 trailing_comments: Vec::new(),
3318 inferred_type: None,
3319 })),
3320 right: Expression::IsNull(Box::new(crate::expressions::IsNull {
3321 this: b.clone(),
3322 not: false,
3323 postfix_form: false,
3324 })),
3325 left_comments: Vec::new(),
3326 operator_comments: Vec::new(),
3327 trailing_comments: Vec::new(),
3328 inferred_type: None,
3329 })),
3330 Expression::number(0),
3331 )],
3332 else_: Some(Expression::Div(Box::new(BinaryOp {
3333 left: a,
3334 right: b,
3335 left_comments: Vec::new(),
3336 operator_comments: Vec::new(),
3337 trailing_comments: Vec::new(),
3338 inferred_type: None,
3339 }))),
3340 comments: Vec::new(),
3341 inferred_type: None,
3342 })))
3343 }
3344 "ZEROIFNULL" if f.args.len() == 1 => {
3345 let x = f.args.into_iter().next().unwrap();
3346 Ok(Expression::Case(Box::new(Case {
3347 operand: None,
3348 whens: vec![(
3349 Expression::IsNull(Box::new(crate::expressions::IsNull {
3350 this: x.clone(),
3351 not: false,
3352 postfix_form: false,
3353 })),
3354 Expression::number(0),
3355 )],
3356 else_: Some(x),
3357 comments: Vec::new(),
3358 inferred_type: None,
3359 })))
3360 }
3361 "NULLIFZERO" if f.args.len() == 1 => {
3362 let x = f.args.into_iter().next().unwrap();
3363 Ok(Expression::Case(Box::new(Case {
3364 operand: None,
3365 whens: vec![(
3366 Expression::Eq(Box::new(BinaryOp {
3367 left: x.clone(),
3368 right: Expression::number(0),
3369 left_comments: Vec::new(),
3370 operator_comments: Vec::new(),
3371 trailing_comments: Vec::new(),
3372 inferred_type: None,
3373 })),
3374 Expression::Null(crate::expressions::Null),
3375 )],
3376 else_: Some(x),
3377 comments: Vec::new(),
3378 inferred_type: None,
3379 })))
3380 }
3381 "TO_DOUBLE" if f.args.len() == 1 => {
3382 let arg = f.args.into_iter().next().unwrap();
3383 Ok(Expression::Cast(Box::new(Cast {
3384 this: arg,
3385 to: DataType::Double {
3386 precision: None,
3387 scale: None,
3388 },
3389 trailing_comments: Vec::new(),
3390 double_colon_syntax: false,
3391 format: None,
3392 default: None,
3393 inferred_type: None,
3394 })))
3395 }
3396 "DATE" if f.args.len() == 1 => {
3397 let arg = f.args.into_iter().next().unwrap();
3398 Ok(Expression::Cast(Box::new(Cast {
3399 this: arg,
3400 to: DataType::Date,
3401 trailing_comments: Vec::new(),
3402 double_colon_syntax: false,
3403 format: None,
3404 default: None,
3405 inferred_type: None,
3406 })))
3407 }
3408 "DATE" if f.args.len() == 2 => {
3409 let mut args = f.args;
3410 let value = args.remove(0);
3411 let fmt = self.convert_snowflake_date_format(args.remove(0));
3412 Ok(Expression::Cast(Box::new(Cast {
3413 this: Expression::Function(Box::new(Function::new(
3414 "STRPTIME".to_string(),
3415 vec![value, fmt],
3416 ))),
3417 to: DataType::Date,
3418 trailing_comments: Vec::new(),
3419 double_colon_syntax: false,
3420 format: None,
3421 default: None,
3422 inferred_type: None,
3423 })))
3424 }
3425 "SYSDATE" => Ok(Expression::AtTimeZone(Box::new(
3426 crate::expressions::AtTimeZone {
3427 this: Expression::CurrentTimestamp(crate::expressions::CurrentTimestamp {
3428 precision: None,
3429 sysdate: false,
3430 }),
3431 zone: Expression::Literal(Literal::String("UTC".to_string())),
3432 },
3433 ))),
3434 "HEX_DECODE_BINARY" => Ok(Expression::Function(Box::new(Function::new(
3435 "UNHEX".to_string(),
3436 f.args,
3437 )))),
3438 "CONVERT_TIMEZONE" if f.args.len() == 3 => {
3439 let mut args = f.args;
3440 let src_tz = args.remove(0);
3441 let tgt_tz = args.remove(0);
3442 let ts = args.remove(0);
3443 let cast_ts = Expression::Cast(Box::new(Cast {
3444 this: ts,
3445 to: DataType::Timestamp {
3446 precision: None,
3447 timezone: false,
3448 },
3449 trailing_comments: Vec::new(),
3450 double_colon_syntax: false,
3451 format: None,
3452 default: None,
3453 inferred_type: None,
3454 }));
3455 Ok(Expression::AtTimeZone(Box::new(
3456 crate::expressions::AtTimeZone {
3457 this: Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone {
3458 this: cast_ts,
3459 zone: src_tz,
3460 })),
3461 zone: tgt_tz,
3462 },
3463 )))
3464 }
3465 "CONVERT_TIMEZONE" if f.args.len() == 2 => {
3466 let mut args = f.args;
3467 let tgt_tz = args.remove(0);
3468 let ts = args.remove(0);
3469 let cast_ts = Expression::Cast(Box::new(Cast {
3470 this: ts,
3471 to: DataType::Timestamp {
3472 precision: None,
3473 timezone: false,
3474 },
3475 trailing_comments: Vec::new(),
3476 double_colon_syntax: false,
3477 format: None,
3478 default: None,
3479 inferred_type: None,
3480 }));
3481 Ok(Expression::AtTimeZone(Box::new(
3482 crate::expressions::AtTimeZone {
3483 this: cast_ts,
3484 zone: tgt_tz,
3485 },
3486 )))
3487 }
3488 "DATE_PART" | "DATEPART" if f.args.len() == 2 => self.transform_date_part(f.args),
3489 "DATEADD" | "TIMEADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3490 "TIMESTAMPADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
3491 "DATEDIFF" | "TIMEDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3492 "TIMESTAMPDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
3493 "CORR" if f.args.len() == 2 => {
3494 Ok(Expression::Function(Box::new(f)))
3496 }
3497 "TO_TIMESTAMP" | "TO_TIMESTAMP_NTZ" if f.args.len() == 2 => {
3498 let mut args = f.args;
3499 let value = args.remove(0);
3500 let second_arg = args.remove(0);
3501 match &second_arg {
3502 Expression::Literal(Literal::Number(_)) => Ok(Expression::AtTimeZone(
3503 Box::new(crate::expressions::AtTimeZone {
3504 this: Expression::Function(Box::new(Function::new(
3505 "TO_TIMESTAMP".to_string(),
3506 vec![Expression::Div(Box::new(BinaryOp {
3507 left: value,
3508 right: Expression::Function(Box::new(Function::new(
3509 "POWER".to_string(),
3510 vec![Expression::number(10), second_arg],
3511 ))),
3512 left_comments: Vec::new(),
3513 operator_comments: Vec::new(),
3514 trailing_comments: Vec::new(),
3515 inferred_type: None,
3516 }))],
3517 ))),
3518 zone: Expression::Literal(Literal::String("UTC".to_string())),
3519 }),
3520 )),
3521 _ => {
3522 let fmt = self.convert_snowflake_time_format(second_arg);
3523 Ok(Expression::Function(Box::new(Function::new(
3524 "STRPTIME".to_string(),
3525 vec![value, fmt],
3526 ))))
3527 }
3528 }
3529 }
3530 "TO_TIME" if f.args.len() == 1 => {
3531 let arg = f.args.into_iter().next().unwrap();
3532 Ok(Expression::Cast(Box::new(Cast {
3533 this: arg,
3534 to: DataType::Time {
3535 precision: None,
3536 timezone: false,
3537 },
3538 trailing_comments: Vec::new(),
3539 double_colon_syntax: false,
3540 format: None,
3541 default: None,
3542 inferred_type: None,
3543 })))
3544 }
3545 "TO_TIME" if f.args.len() == 2 => {
3546 let mut args = f.args;
3547 let value = args.remove(0);
3548 let fmt = self.convert_snowflake_time_format(args.remove(0));
3549 Ok(Expression::Cast(Box::new(Cast {
3550 this: Expression::Function(Box::new(Function::new(
3551 "STRPTIME".to_string(),
3552 vec![value, fmt],
3553 ))),
3554 to: DataType::Time {
3555 precision: None,
3556 timezone: false,
3557 },
3558 trailing_comments: Vec::new(),
3559 double_colon_syntax: false,
3560 format: None,
3561 default: None,
3562 inferred_type: None,
3563 })))
3564 }
3565 "TO_DATE" if f.args.len() == 2 => {
3566 let mut args = f.args;
3567 let value = args.remove(0);
3568 let fmt = self.convert_snowflake_date_format(args.remove(0));
3569 Ok(Expression::Cast(Box::new(Cast {
3570 this: Expression::Function(Box::new(Function::new(
3571 "STRPTIME".to_string(),
3572 vec![value, fmt],
3573 ))),
3574 to: DataType::Date,
3575 trailing_comments: Vec::new(),
3576 double_colon_syntax: false,
3577 format: None,
3578 default: None,
3579 inferred_type: None,
3580 })))
3581 }
3582 "SAFE_DIVIDE" if f.args.len() == 2 => {
3586 let mut args = f.args;
3587 let x = args.remove(0);
3588 let y = args.remove(0);
3589 Ok(Expression::Case(Box::new(Case {
3590 operand: None,
3591 whens: vec![(
3592 Expression::Neq(Box::new(BinaryOp {
3593 left: y.clone(),
3594 right: Expression::number(0),
3595 left_comments: Vec::new(),
3596 operator_comments: Vec::new(),
3597 trailing_comments: Vec::new(),
3598 inferred_type: None,
3599 })),
3600 Expression::Div(Box::new(BinaryOp {
3601 left: x,
3602 right: y,
3603 left_comments: Vec::new(),
3604 operator_comments: Vec::new(),
3605 trailing_comments: Vec::new(),
3606 inferred_type: None,
3607 })),
3608 )],
3609 else_: Some(Expression::Null(crate::expressions::Null)),
3610 comments: Vec::new(),
3611 inferred_type: None,
3612 })))
3613 }
3614
3615 "TO_HEX" if f.args.len() == 1 => {
3617 let arg = f.args.into_iter().next().unwrap();
3618 Ok(Expression::Lower(Box::new(UnaryFunc::new(
3619 Expression::Function(Box::new(Function::new("HEX".to_string(), vec![arg]))),
3620 ))))
3621 }
3622
3623 "EDIT_DISTANCE" if f.args.len() >= 2 => {
3625 let mut args = f.args;
3627 let a = args.remove(0);
3628 let b = args.remove(0);
3629 Ok(Expression::Function(Box::new(Function::new(
3630 "LEVENSHTEIN".to_string(),
3631 vec![a, b],
3632 ))))
3633 }
3634
3635 "UNIX_DATE" if f.args.len() == 1 => {
3637 let arg = f.args.into_iter().next().unwrap();
3638 Ok(Expression::Function(Box::new(Function::new(
3639 "DATE_DIFF".to_string(),
3640 vec![
3641 Expression::Literal(Literal::String("DAY".to_string())),
3642 Expression::Cast(Box::new(Cast {
3643 this: Expression::Literal(Literal::String("1970-01-01".to_string())),
3644 to: DataType::Date,
3645 trailing_comments: Vec::new(),
3646 double_colon_syntax: false,
3647 format: None,
3648 default: None,
3649 inferred_type: None,
3650 })),
3651 arg,
3652 ],
3653 ))))
3654 }
3655
3656 "TIMESTAMP" if f.args.len() == 1 => {
3658 let arg = f.args.into_iter().next().unwrap();
3659 Ok(Expression::Cast(Box::new(Cast {
3660 this: arg,
3661 to: DataType::Custom {
3662 name: "TIMESTAMPTZ".to_string(),
3663 },
3664 trailing_comments: Vec::new(),
3665 double_colon_syntax: false,
3666 format: None,
3667 default: None,
3668 inferred_type: None,
3669 })))
3670 }
3671
3672 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3674 "MAKE_TIME".to_string(),
3675 f.args,
3676 )))),
3677
3678 "DATE" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3680 "MAKE_DATE".to_string(),
3681 f.args,
3682 )))),
3683
3684 "DATETIME" if f.args.len() == 6 => Ok(Expression::Function(Box::new(Function::new(
3686 "MAKE_TIMESTAMP".to_string(),
3687 f.args,
3688 )))),
3689
3690 "PARSE_TIMESTAMP" if f.args.len() >= 2 => {
3692 let mut args = f.args;
3693 let fmt = args.remove(0);
3694 let value = args.remove(0);
3695 let duckdb_fmt = self.convert_bq_to_strptime_format(fmt);
3697 Ok(Expression::Function(Box::new(Function::new(
3698 "STRPTIME".to_string(),
3699 vec![value, duckdb_fmt],
3700 ))))
3701 }
3702
3703 "BOOLAND" if f.args.len() == 2 => {
3705 let mut args = f.args;
3706 let a = args.remove(0);
3707 let b = args.remove(0);
3708 let ra = Expression::Function(Box::new(Function::new(
3709 "ROUND".to_string(),
3710 vec![a, Expression::number(0)],
3711 )));
3712 let rb = Expression::Function(Box::new(Function::new(
3713 "ROUND".to_string(),
3714 vec![b, Expression::number(0)],
3715 )));
3716 Ok(Expression::Paren(Box::new(Paren {
3717 this: Expression::And(Box::new(BinaryOp {
3718 left: Expression::Paren(Box::new(Paren {
3719 this: ra,
3720 trailing_comments: Vec::new(),
3721 })),
3722 right: Expression::Paren(Box::new(Paren {
3723 this: rb,
3724 trailing_comments: Vec::new(),
3725 })),
3726 left_comments: Vec::new(),
3727 operator_comments: Vec::new(),
3728 trailing_comments: Vec::new(),
3729 inferred_type: None,
3730 })),
3731 trailing_comments: Vec::new(),
3732 })))
3733 }
3734
3735 "BOOLOR" if f.args.len() == 2 => {
3737 let mut args = f.args;
3738 let a = args.remove(0);
3739 let b = args.remove(0);
3740 let ra = Expression::Function(Box::new(Function::new(
3741 "ROUND".to_string(),
3742 vec![a, Expression::number(0)],
3743 )));
3744 let rb = Expression::Function(Box::new(Function::new(
3745 "ROUND".to_string(),
3746 vec![b, Expression::number(0)],
3747 )));
3748 Ok(Expression::Paren(Box::new(Paren {
3749 this: Expression::Or(Box::new(BinaryOp {
3750 left: Expression::Paren(Box::new(Paren {
3751 this: ra,
3752 trailing_comments: Vec::new(),
3753 })),
3754 right: Expression::Paren(Box::new(Paren {
3755 this: rb,
3756 trailing_comments: Vec::new(),
3757 })),
3758 left_comments: Vec::new(),
3759 operator_comments: Vec::new(),
3760 trailing_comments: Vec::new(),
3761 inferred_type: None,
3762 })),
3763 trailing_comments: Vec::new(),
3764 })))
3765 }
3766
3767 "BOOLXOR" if f.args.len() == 2 => {
3769 let mut args = f.args;
3770 let a = args.remove(0);
3771 let b = args.remove(0);
3772 let ra = Expression::Function(Box::new(Function::new(
3773 "ROUND".to_string(),
3774 vec![a, Expression::number(0)],
3775 )));
3776 let rb = Expression::Function(Box::new(Function::new(
3777 "ROUND".to_string(),
3778 vec![b, Expression::number(0)],
3779 )));
3780 let not_rb = Expression::Not(Box::new(crate::expressions::UnaryOp {
3782 this: rb.clone(),
3783 inferred_type: None,
3784 }));
3785 let not_ra = Expression::Not(Box::new(crate::expressions::UnaryOp {
3786 this: ra.clone(),
3787 inferred_type: None,
3788 }));
3789 let left_and = Expression::And(Box::new(BinaryOp {
3790 left: ra,
3791 right: Expression::Paren(Box::new(Paren {
3792 this: not_rb,
3793 trailing_comments: Vec::new(),
3794 })),
3795 left_comments: Vec::new(),
3796 operator_comments: Vec::new(),
3797 trailing_comments: Vec::new(),
3798 inferred_type: None,
3799 }));
3800 let right_and = Expression::And(Box::new(BinaryOp {
3801 left: Expression::Paren(Box::new(Paren {
3802 this: not_ra,
3803 trailing_comments: Vec::new(),
3804 })),
3805 right: rb,
3806 left_comments: Vec::new(),
3807 operator_comments: Vec::new(),
3808 trailing_comments: Vec::new(),
3809 inferred_type: None,
3810 }));
3811 Ok(Expression::Or(Box::new(BinaryOp {
3812 left: Expression::Paren(Box::new(Paren {
3813 this: left_and,
3814 trailing_comments: Vec::new(),
3815 })),
3816 right: Expression::Paren(Box::new(Paren {
3817 this: right_and,
3818 trailing_comments: Vec::new(),
3819 })),
3820 left_comments: Vec::new(),
3821 operator_comments: Vec::new(),
3822 trailing_comments: Vec::new(),
3823 inferred_type: None,
3824 })))
3825 }
3826
3827 "DECODE" if f.args.len() >= 3 => {
3830 let mut args = f.args;
3831 let expr = args.remove(0);
3832 let mut whens = Vec::new();
3833 let mut else_expr = None;
3834 while args.len() >= 2 {
3835 let search = args.remove(0);
3836 let result = args.remove(0);
3837 let condition = if matches!(&search, Expression::Null(_)) {
3839 Expression::IsNull(Box::new(crate::expressions::IsNull {
3840 this: expr.clone(),
3841 not: false,
3842 postfix_form: false,
3843 }))
3844 } else {
3845 Expression::Eq(Box::new(BinaryOp {
3846 left: expr.clone(),
3847 right: search,
3848 left_comments: Vec::new(),
3849 operator_comments: Vec::new(),
3850 trailing_comments: Vec::new(),
3851 inferred_type: None,
3852 }))
3853 };
3854 whens.push((condition, result));
3855 }
3856 if !args.is_empty() {
3857 else_expr = Some(args.remove(0));
3858 }
3859 Ok(Expression::Case(Box::new(Case {
3860 operand: None,
3861 whens,
3862 else_: else_expr,
3863 comments: Vec::new(),
3864 inferred_type: None,
3865 })))
3866 }
3867
3868 "TRY_TO_BOOLEAN" if f.args.len() == 1 => {
3870 let arg = f.args.into_iter().next().unwrap();
3871 let cast_text = Expression::Cast(Box::new(Cast {
3872 this: arg.clone(),
3873 to: DataType::Text,
3874 trailing_comments: Vec::new(),
3875 double_colon_syntax: false,
3876 format: None,
3877 default: None,
3878 inferred_type: None,
3879 }));
3880 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
3881 Ok(Expression::Case(Box::new(Case {
3882 operand: None,
3883 whens: vec![
3884 (
3885 Expression::Eq(Box::new(BinaryOp {
3886 left: upper_text.clone(),
3887 right: Expression::Literal(Literal::String("ON".to_string())),
3888 left_comments: Vec::new(),
3889 operator_comments: Vec::new(),
3890 trailing_comments: Vec::new(),
3891 inferred_type: None,
3892 })),
3893 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
3894 ),
3895 (
3896 Expression::Eq(Box::new(BinaryOp {
3897 left: upper_text,
3898 right: Expression::Literal(Literal::String("OFF".to_string())),
3899 left_comments: Vec::new(),
3900 operator_comments: Vec::new(),
3901 trailing_comments: Vec::new(),
3902 inferred_type: None,
3903 })),
3904 Expression::Boolean(crate::expressions::BooleanLiteral {
3905 value: false,
3906 }),
3907 ),
3908 ],
3909 else_: Some(Expression::TryCast(Box::new(Cast {
3910 this: arg,
3911 to: DataType::Boolean,
3912 trailing_comments: Vec::new(),
3913 double_colon_syntax: false,
3914 format: None,
3915 default: None,
3916 inferred_type: None,
3917 }))),
3918 comments: Vec::new(),
3919 inferred_type: None,
3920 })))
3921 }
3922
3923 "TO_BOOLEAN" if f.args.len() == 1 => {
3925 let arg = f.args.into_iter().next().unwrap();
3926 let cast_text = Expression::Cast(Box::new(Cast {
3927 this: arg.clone(),
3928 to: DataType::Text,
3929 trailing_comments: Vec::new(),
3930 double_colon_syntax: false,
3931 format: None,
3932 default: None,
3933 inferred_type: None,
3934 }));
3935 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
3936 Ok(Expression::Case(Box::new(Case {
3937 operand: None,
3938 whens: vec![
3939 (
3940 Expression::Eq(Box::new(BinaryOp {
3941 left: upper_text.clone(),
3942 right: Expression::Literal(Literal::String("ON".to_string())),
3943 left_comments: Vec::new(),
3944 operator_comments: Vec::new(),
3945 trailing_comments: Vec::new(),
3946 inferred_type: None,
3947 })),
3948 Expression::Boolean(crate::expressions::BooleanLiteral { value: true }),
3949 ),
3950 (
3951 Expression::Eq(Box::new(BinaryOp {
3952 left: upper_text,
3953 right: Expression::Literal(Literal::String("OFF".to_string())),
3954 left_comments: Vec::new(),
3955 operator_comments: Vec::new(),
3956 trailing_comments: Vec::new(),
3957 inferred_type: None,
3958 })),
3959 Expression::Boolean(crate::expressions::BooleanLiteral {
3960 value: false,
3961 }),
3962 ),
3963 (
3964 Expression::Or(Box::new(BinaryOp {
3965 left: Expression::Function(Box::new(Function::new(
3966 "ISNAN".to_string(),
3967 vec![Expression::TryCast(Box::new(Cast {
3968 this: arg.clone(),
3969 to: DataType::Custom {
3970 name: "REAL".to_string(),
3971 },
3972 trailing_comments: Vec::new(),
3973 double_colon_syntax: false,
3974 format: None,
3975 default: None,
3976 inferred_type: None,
3977 }))],
3978 ))),
3979 right: Expression::Function(Box::new(Function::new(
3980 "ISINF".to_string(),
3981 vec![Expression::TryCast(Box::new(Cast {
3982 this: arg.clone(),
3983 to: DataType::Custom {
3984 name: "REAL".to_string(),
3985 },
3986 trailing_comments: Vec::new(),
3987 double_colon_syntax: false,
3988 format: None,
3989 default: None,
3990 inferred_type: None,
3991 }))],
3992 ))),
3993 left_comments: Vec::new(),
3994 operator_comments: Vec::new(),
3995 trailing_comments: Vec::new(),
3996 inferred_type: None,
3997 })),
3998 Expression::Function(Box::new(Function::new(
3999 "ERROR".to_string(),
4000 vec![Expression::Literal(Literal::String(
4001 "TO_BOOLEAN: Non-numeric values NaN and INF are not supported"
4002 .to_string(),
4003 ))],
4004 ))),
4005 ),
4006 ],
4007 else_: Some(Expression::Cast(Box::new(Cast {
4008 this: arg,
4009 to: DataType::Boolean,
4010 trailing_comments: Vec::new(),
4011 double_colon_syntax: false,
4012 format: None,
4013 default: None,
4014 inferred_type: None,
4015 }))),
4016 comments: Vec::new(),
4017 inferred_type: None,
4018 })))
4019 }
4020
4021 "OBJECT_INSERT" if f.args.len() == 3 => {
4024 let mut args = f.args;
4025 let obj = args.remove(0);
4026 let key = args.remove(0);
4027 let value = args.remove(0);
4028 let key_name = match &key {
4030 Expression::Literal(Literal::String(s)) => s.clone(),
4031 _ => "key".to_string(),
4032 };
4033 let named_arg =
4034 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
4035 name: Identifier::new(&key_name),
4036 value,
4037 separator: crate::expressions::NamedArgSeparator::ColonEq,
4038 }));
4039 let is_empty_struct = match &obj {
4041 Expression::Struct(s) if s.fields.is_empty() => true,
4042 Expression::Function(f) => {
4043 let n = f.name.to_uppercase();
4044 (n == "STRUCT_PACK" || n == "OBJECT_CONSTRUCT") && f.args.is_empty()
4045 }
4046 _ => false,
4047 };
4048 if is_empty_struct {
4049 Ok(Expression::Function(Box::new(Function::new(
4051 "STRUCT_PACK".to_string(),
4052 vec![named_arg],
4053 ))))
4054 } else {
4055 Ok(Expression::Function(Box::new(Function::new(
4056 "STRUCT_INSERT".to_string(),
4057 vec![obj, named_arg],
4058 ))))
4059 }
4060 }
4061
4062 "GET" if f.args.len() == 2 => {
4064 let mut args = f.args;
4065 let this = args.remove(0);
4066 let key = args.remove(0);
4067 match &key {
4068 Expression::Literal(Literal::String(s)) => {
4070 let json_path = format!("$.{}", s);
4071 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4072 this,
4073 path: Expression::Literal(Literal::String(json_path)),
4074 returning: None,
4075 arrow_syntax: true,
4076 hash_arrow_syntax: false,
4077 wrapper_option: None,
4078 quotes_option: None,
4079 on_scalar_string: false,
4080 on_error: None,
4081 })))
4082 }
4083 Expression::Literal(Literal::Number(n)) => {
4087 let idx: i64 = n.parse().unwrap_or(0);
4088 let is_map = matches!(&this, Expression::Cast(c) if matches!(c.to, DataType::Map { .. }));
4089 let index_val = if is_map { idx } else { idx + 1 };
4090 Ok(Expression::Subscript(Box::new(
4091 crate::expressions::Subscript {
4092 this,
4093 index: Expression::number(index_val),
4094 },
4095 )))
4096 }
4097 _ => {
4098 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4100 this,
4101 path: Expression::JSONPath(Box::new(JSONPath {
4102 expressions: vec![
4103 Expression::JSONPathRoot(JSONPathRoot),
4104 Expression::JSONPathKey(Box::new(JSONPathKey {
4105 this: Box::new(key),
4106 })),
4107 ],
4108 escape: None,
4109 })),
4110 returning: None,
4111 arrow_syntax: true,
4112 hash_arrow_syntax: false,
4113 wrapper_option: None,
4114 quotes_option: None,
4115 on_scalar_string: false,
4116 on_error: None,
4117 })))
4118 }
4119 }
4120 }
4121
4122 "GET_PATH" if f.args.len() == 2 => {
4124 let mut args = f.args;
4125 let this = args.remove(0);
4126 let path = args.remove(0);
4127 let json_path = match &path {
4129 Expression::Literal(Literal::String(s)) => {
4130 let s = Self::convert_bracket_to_quoted_path(s);
4132 let normalized = if s.starts_with('$') {
4134 s
4135 } else if s.starts_with('[') {
4136 format!("${}", s)
4137 } else {
4138 format!("$.{}", s)
4139 };
4140 Expression::Literal(Literal::String(normalized))
4141 }
4142 _ => path,
4143 };
4144 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
4145 this,
4146 path: json_path,
4147 returning: None,
4148 arrow_syntax: true,
4149 hash_arrow_syntax: false,
4150 wrapper_option: None,
4151 quotes_option: None,
4152 on_scalar_string: false,
4153 on_error: None,
4154 })))
4155 }
4156
4157 "BASE64_ENCODE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
4159 Function::new("TO_BASE64".to_string(), f.args),
4160 ))),
4161
4162 "BASE64_ENCODE" if f.args.len() >= 2 => {
4164 let mut args = f.args;
4165 let x = args.remove(0);
4166 let line_len = args.remove(0);
4167 let line_len_str = match &line_len {
4168 Expression::Literal(Literal::Number(n)) => n.clone(),
4169 _ => "76".to_string(),
4170 };
4171 let to_base64 =
4172 Expression::Function(Box::new(Function::new("TO_BASE64".to_string(), vec![x])));
4173 let pattern = format!("(.{{{}}})", line_len_str);
4174 let chr_10 = Expression::Function(Box::new(Function::new(
4175 "CHR".to_string(),
4176 vec![Expression::number(10)],
4177 )));
4178 let replacement = Expression::Concat(Box::new(BinaryOp {
4179 left: Expression::Literal(Literal::String("\\1".to_string())),
4180 right: chr_10.clone(),
4181 left_comments: Vec::new(),
4182 operator_comments: Vec::new(),
4183 trailing_comments: Vec::new(),
4184 inferred_type: None,
4185 }));
4186 let regexp_replace = Expression::Function(Box::new(Function::new(
4187 "REGEXP_REPLACE".to_string(),
4188 vec![
4189 to_base64,
4190 Expression::Literal(Literal::String(pattern)),
4191 replacement,
4192 Expression::Literal(Literal::String("g".to_string())),
4193 ],
4194 )));
4195 Ok(Expression::Function(Box::new(Function::new(
4196 "RTRIM".to_string(),
4197 vec![regexp_replace, chr_10],
4198 ))))
4199 }
4200
4201 "TRY_TO_DATE" if f.args.len() == 2 => {
4203 let mut args = f.args;
4204 let value = args.remove(0);
4205 let fmt = self.convert_snowflake_date_format(args.remove(0));
4206 Ok(Expression::Cast(Box::new(Cast {
4207 this: Expression::Cast(Box::new(Cast {
4208 this: Expression::Function(Box::new(Function::new(
4209 "TRY_STRPTIME".to_string(),
4210 vec![value, fmt],
4211 ))),
4212 to: DataType::Timestamp {
4213 precision: None,
4214 timezone: false,
4215 },
4216 trailing_comments: Vec::new(),
4217 double_colon_syntax: false,
4218 format: None,
4219 default: None,
4220 inferred_type: None,
4221 })),
4222 to: DataType::Date,
4223 trailing_comments: Vec::new(),
4224 double_colon_syntax: false,
4225 format: None,
4226 default: None,
4227 inferred_type: None,
4228 })))
4229 }
4230
4231 "REGEXP_REPLACE" if f.args.len() == 4 => {
4234 let is_snowflake_position =
4235 matches!(&f.args[3], Expression::Literal(Literal::Number(_)));
4236 if is_snowflake_position {
4237 let mut args = f.args;
4239 let subject = args.remove(0);
4240 let pattern = args.remove(0);
4241 let replacement = args.remove(0);
4242 Ok(Expression::Function(Box::new(Function::new(
4243 "REGEXP_REPLACE".to_string(),
4244 vec![
4245 subject,
4246 pattern,
4247 replacement,
4248 Expression::Literal(Literal::String("g".to_string())),
4249 ],
4250 ))))
4251 } else {
4252 Ok(Expression::Function(Box::new(f)))
4254 }
4255 }
4256
4257 "REGEXP_REPLACE" if f.args.len() >= 5 => {
4259 let mut args = f.args;
4260 let subject = args.remove(0);
4261 let pattern = args.remove(0);
4262 let replacement = args.remove(0);
4263 let _position = args.remove(0);
4264 let occurrence = if !args.is_empty() {
4265 Some(args.remove(0))
4266 } else {
4267 None
4268 };
4269 let params = if !args.is_empty() {
4270 Some(args.remove(0))
4271 } else {
4272 None
4273 };
4274
4275 let mut flags = String::new();
4276 if let Some(Expression::Literal(Literal::String(p))) = ¶ms {
4277 flags = p.clone();
4278 }
4279 let is_global = match &occurrence {
4280 Some(Expression::Literal(Literal::Number(n))) => n == "0",
4281 None => true,
4282 _ => false,
4283 };
4284 if is_global && !flags.contains('g') {
4285 flags.push('g');
4286 }
4287
4288 Ok(Expression::Function(Box::new(Function::new(
4289 "REGEXP_REPLACE".to_string(),
4290 vec![
4291 subject,
4292 pattern,
4293 replacement,
4294 Expression::Literal(Literal::String(flags)),
4295 ],
4296 ))))
4297 }
4298
4299 "ROUND"
4301 if f.args
4302 .iter()
4303 .any(|a| matches!(a, Expression::NamedArgument(_))) =>
4304 {
4305 let mut expr_val = None;
4306 let mut scale_val = None;
4307 let mut rounding_mode = None;
4308 for arg in &f.args {
4309 if let Expression::NamedArgument(na) = arg {
4310 match na.name.name.to_uppercase().as_str() {
4311 "EXPR" => expr_val = Some(na.value.clone()),
4312 "SCALE" => scale_val = Some(na.value.clone()),
4313 "ROUNDING_MODE" => rounding_mode = Some(na.value.clone()),
4314 _ => {}
4315 }
4316 }
4317 }
4318 if let Some(expr) = expr_val {
4319 let scale = scale_val.unwrap_or(Expression::number(0));
4320 let is_half_to_even = match &rounding_mode {
4321 Some(Expression::Literal(Literal::String(s))) => s == "HALF_TO_EVEN",
4322 _ => false,
4323 };
4324 if is_half_to_even {
4325 Ok(Expression::Function(Box::new(Function::new(
4326 "ROUND_EVEN".to_string(),
4327 vec![expr, scale],
4328 ))))
4329 } else {
4330 Ok(Expression::Function(Box::new(Function::new(
4331 "ROUND".to_string(),
4332 vec![expr, scale],
4333 ))))
4334 }
4335 } else {
4336 Ok(Expression::Function(Box::new(f)))
4337 }
4338 }
4339
4340 "ROUND" if f.args.len() == 3 => {
4343 let mut args = f.args;
4344 let x = args.remove(0);
4345 let scale = args.remove(0);
4346 let mode = args.remove(0);
4347 let is_half_to_even = match &mode {
4348 Expression::Literal(Literal::String(s)) => s == "HALF_TO_EVEN",
4349 _ => false,
4350 };
4351 if is_half_to_even {
4352 Ok(Expression::Function(Box::new(Function::new(
4353 "ROUND_EVEN".to_string(),
4354 vec![x, scale],
4355 ))))
4356 } else {
4357 Ok(Expression::Function(Box::new(Function::new(
4359 "ROUND".to_string(),
4360 vec![x, scale],
4361 ))))
4362 }
4363 }
4364
4365 "ROUND" if f.args.len() == 2 => {
4367 let mut args = f.args;
4368 let x = args.remove(0);
4369 let scale = args.remove(0);
4370 let needs_cast = match &scale {
4371 Expression::Literal(Literal::Number(n)) => n.contains('.'),
4372 Expression::Cast(_) => {
4373 true
4375 }
4376 _ => false,
4377 };
4378 if needs_cast {
4379 Ok(Expression::Function(Box::new(Function::new(
4380 "ROUND".to_string(),
4381 vec![
4382 x,
4383 Expression::Cast(Box::new(Cast {
4384 this: scale,
4385 to: DataType::Int {
4386 length: None,
4387 integer_spelling: false,
4388 },
4389 trailing_comments: Vec::new(),
4390 double_colon_syntax: false,
4391 format: None,
4392 default: None,
4393 inferred_type: None,
4394 })),
4395 ],
4396 ))))
4397 } else {
4398 Ok(Expression::Function(Box::new(Function::new(
4399 "ROUND".to_string(),
4400 vec![x, scale],
4401 ))))
4402 }
4403 }
4404
4405 "FLOOR" if f.args.len() == 2 => {
4407 let mut args = f.args;
4408 let x = args.remove(0);
4409 let scale = args.remove(0);
4410 let needs_cast = match &scale {
4412 Expression::Literal(Literal::Number(n)) => n.contains('.'),
4413 _ => false,
4414 };
4415 let int_scale = if needs_cast {
4416 Expression::Cast(Box::new(Cast {
4417 this: scale.clone(),
4418 to: DataType::Int {
4419 length: None,
4420 integer_spelling: false,
4421 },
4422 trailing_comments: Vec::new(),
4423 double_colon_syntax: false,
4424 format: None,
4425 default: None,
4426 inferred_type: None,
4427 }))
4428 } else {
4429 scale.clone()
4430 };
4431 let power_10 = Expression::Function(Box::new(Function::new(
4432 "POWER".to_string(),
4433 vec![Expression::number(10), int_scale.clone()],
4434 )));
4435 let x_paren = match &x {
4436 Expression::Add(_)
4437 | Expression::Sub(_)
4438 | Expression::Mul(_)
4439 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4440 this: x,
4441 trailing_comments: Vec::new(),
4442 })),
4443 _ => x,
4444 };
4445 let multiplied = Expression::Mul(Box::new(BinaryOp {
4446 left: x_paren,
4447 right: power_10.clone(),
4448 left_comments: Vec::new(),
4449 operator_comments: Vec::new(),
4450 trailing_comments: Vec::new(),
4451 inferred_type: None,
4452 }));
4453 let floored = Expression::Function(Box::new(Function::new(
4454 "FLOOR".to_string(),
4455 vec![multiplied],
4456 )));
4457 let divided = Expression::Div(Box::new(BinaryOp {
4458 left: floored,
4459 right: power_10,
4460 left_comments: Vec::new(),
4461 operator_comments: Vec::new(),
4462 trailing_comments: Vec::new(),
4463 inferred_type: None,
4464 }));
4465 Ok(Expression::Function(Box::new(Function::new(
4466 "ROUND".to_string(),
4467 vec![divided, int_scale],
4468 ))))
4469 }
4470
4471 "CEIL" | "CEILING" if f.args.len() == 2 => {
4473 let mut args = f.args;
4474 let x = args.remove(0);
4475 let scale = args.remove(0);
4476 let needs_cast = match &scale {
4477 Expression::Literal(Literal::Number(n)) => n.contains('.'),
4478 _ => false,
4479 };
4480 let int_scale = if needs_cast {
4481 Expression::Cast(Box::new(Cast {
4482 this: scale.clone(),
4483 to: DataType::Int {
4484 length: None,
4485 integer_spelling: false,
4486 },
4487 trailing_comments: Vec::new(),
4488 double_colon_syntax: false,
4489 format: None,
4490 default: None,
4491 inferred_type: None,
4492 }))
4493 } else {
4494 scale.clone()
4495 };
4496 let power_10 = Expression::Function(Box::new(Function::new(
4497 "POWER".to_string(),
4498 vec![Expression::number(10), int_scale.clone()],
4499 )));
4500 let x_paren = match &x {
4501 Expression::Add(_)
4502 | Expression::Sub(_)
4503 | Expression::Mul(_)
4504 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4505 this: x,
4506 trailing_comments: Vec::new(),
4507 })),
4508 _ => x,
4509 };
4510 let multiplied = Expression::Mul(Box::new(BinaryOp {
4511 left: x_paren,
4512 right: power_10.clone(),
4513 left_comments: Vec::new(),
4514 operator_comments: Vec::new(),
4515 trailing_comments: Vec::new(),
4516 inferred_type: None,
4517 }));
4518 let ceiled = Expression::Function(Box::new(Function::new(
4519 "CEIL".to_string(),
4520 vec![multiplied],
4521 )));
4522 let divided = Expression::Div(Box::new(BinaryOp {
4523 left: ceiled,
4524 right: power_10,
4525 left_comments: Vec::new(),
4526 operator_comments: Vec::new(),
4527 trailing_comments: Vec::new(),
4528 inferred_type: None,
4529 }));
4530 Ok(Expression::Function(Box::new(Function::new(
4531 "ROUND".to_string(),
4532 vec![divided, int_scale],
4533 ))))
4534 }
4535
4536 "ADD_MONTHS" if f.args.len() == 2 => {
4538 let mut args = f.args;
4539 let date_expr_raw = args.remove(0);
4540 let months_expr = args.remove(0);
4541
4542 let was_string_literal =
4544 matches!(&date_expr_raw, Expression::Literal(Literal::String(_)));
4545
4546 let date_expr = match &date_expr_raw {
4548 Expression::Literal(Literal::String(_)) => Expression::Cast(Box::new(Cast {
4549 this: date_expr_raw,
4550 to: DataType::Timestamp {
4551 precision: None,
4552 timezone: false,
4553 },
4554 trailing_comments: Vec::new(),
4555 double_colon_syntax: false,
4556 format: None,
4557 default: None,
4558 inferred_type: None,
4559 })),
4560 _ => date_expr_raw,
4561 };
4562
4563 let date_type = if was_string_literal {
4566 None
4567 } else {
4568 match &date_expr {
4569 Expression::Cast(c) => Some(c.to.clone()),
4570 _ => None,
4571 }
4572 };
4573
4574 let is_non_integer_months = match &months_expr {
4576 Expression::Literal(Literal::Number(n)) => n.contains('.'),
4577 Expression::Neg(_) => {
4578 if let Expression::Neg(um) = &months_expr {
4579 matches!(&um.this, Expression::Literal(Literal::Number(n)) if n.contains('.'))
4580 } else {
4581 false
4582 }
4583 }
4584 Expression::Cast(c) => matches!(&c.to, DataType::Decimal { .. }),
4586 _ => false,
4587 };
4588
4589 let is_negative = match &months_expr {
4590 Expression::Neg(_) => true,
4591 Expression::Literal(Literal::Number(n)) => n.starts_with('-'),
4592 _ => false,
4593 };
4594 let is_null = matches!(&months_expr, Expression::Null(_));
4595
4596 let interval_expr = if is_non_integer_months {
4597 Expression::Function(Box::new(Function::new(
4599 "TO_MONTHS".to_string(),
4600 vec![Expression::Cast(Box::new(Cast {
4601 this: Expression::Function(Box::new(Function::new(
4602 "ROUND".to_string(),
4603 vec![months_expr.clone()],
4604 ))),
4605 to: DataType::Int {
4606 length: None,
4607 integer_spelling: false,
4608 },
4609 trailing_comments: Vec::new(),
4610 double_colon_syntax: false,
4611 format: None,
4612 default: None,
4613 inferred_type: None,
4614 }))],
4615 )))
4616 } else if is_negative || is_null {
4617 Expression::Interval(Box::new(Interval {
4619 this: Some(Expression::Paren(Box::new(Paren {
4620 this: months_expr.clone(),
4621 trailing_comments: Vec::new(),
4622 }))),
4623 unit: Some(IntervalUnitSpec::Simple {
4624 unit: IntervalUnit::Month,
4625 use_plural: false,
4626 }),
4627 }))
4628 } else {
4629 Expression::Interval(Box::new(Interval {
4631 this: Some(months_expr.clone()),
4632 unit: Some(IntervalUnitSpec::Simple {
4633 unit: IntervalUnit::Month,
4634 use_plural: false,
4635 }),
4636 }))
4637 };
4638
4639 let date_plus_interval = Expression::Add(Box::new(BinaryOp {
4640 left: date_expr.clone(),
4641 right: interval_expr.clone(),
4642 left_comments: Vec::new(),
4643 operator_comments: Vec::new(),
4644 trailing_comments: Vec::new(),
4645 inferred_type: None,
4646 }));
4647
4648 let case_expr = Expression::Case(Box::new(Case {
4649 operand: None,
4650 whens: vec![(
4651 Expression::Eq(Box::new(BinaryOp {
4652 left: Expression::Function(Box::new(Function::new(
4653 "LAST_DAY".to_string(),
4654 vec![date_expr.clone()],
4655 ))),
4656 right: date_expr.clone(),
4657 left_comments: Vec::new(),
4658 operator_comments: Vec::new(),
4659 trailing_comments: Vec::new(),
4660 inferred_type: None,
4661 })),
4662 Expression::Function(Box::new(Function::new(
4663 "LAST_DAY".to_string(),
4664 vec![date_plus_interval.clone()],
4665 ))),
4666 )],
4667 else_: Some(date_plus_interval),
4668 comments: Vec::new(),
4669 inferred_type: None,
4670 }));
4671
4672 if let Some(dt) = date_type {
4674 Ok(Expression::Cast(Box::new(Cast {
4675 this: case_expr,
4676 to: dt,
4677 trailing_comments: Vec::new(),
4678 double_colon_syntax: false,
4679 format: None,
4680 default: None,
4681 inferred_type: None,
4682 })))
4683 } else {
4684 Ok(case_expr)
4685 }
4686 }
4687
4688 "TIME_SLICE" if f.args.len() >= 3 => {
4691 let mut args = f.args;
4692 let date_expr = args.remove(0);
4693 let n = args.remove(0);
4694 let unit_str = args.remove(0);
4695 let alignment = if !args.is_empty() {
4696 Some(args.remove(0))
4697 } else {
4698 None
4699 };
4700
4701 let unit = match &unit_str {
4703 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
4704 Expression::Column(c) => c.name.name.to_uppercase(),
4705 Expression::Identifier(i) => i.name.to_uppercase(),
4706 _ => "DAY".to_string(),
4707 };
4708
4709 let interval_unit = match unit.as_str() {
4710 "YEAR" => IntervalUnit::Year,
4711 "QUARTER" => IntervalUnit::Quarter,
4712 "MONTH" => IntervalUnit::Month,
4713 "WEEK" => IntervalUnit::Week,
4714 "DAY" => IntervalUnit::Day,
4715 "HOUR" => IntervalUnit::Hour,
4716 "MINUTE" => IntervalUnit::Minute,
4717 "SECOND" => IntervalUnit::Second,
4718 _ => IntervalUnit::Day,
4719 };
4720
4721 let interval = Expression::Interval(Box::new(Interval {
4722 this: Some(n.clone()),
4723 unit: Some(IntervalUnitSpec::Simple {
4724 unit: interval_unit.clone(),
4725 use_plural: false,
4726 }),
4727 }));
4728
4729 let time_bucket = Expression::Function(Box::new(Function::new(
4730 "TIME_BUCKET".to_string(),
4731 vec![interval.clone(), date_expr.clone()],
4732 )));
4733
4734 let is_end = match &alignment {
4735 Some(Expression::Literal(Literal::String(s))) => s.to_uppercase() == "END",
4736 _ => false,
4737 };
4738
4739 let is_date_type = match &date_expr {
4741 Expression::Cast(c) => matches!(&c.to, DataType::Date),
4742 _ => false,
4743 };
4744
4745 if is_end {
4746 let bucket_plus = Expression::Add(Box::new(BinaryOp {
4747 left: time_bucket,
4748 right: Expression::Interval(Box::new(Interval {
4749 this: Some(n),
4750 unit: Some(IntervalUnitSpec::Simple {
4751 unit: interval_unit,
4752 use_plural: false,
4753 }),
4754 })),
4755 left_comments: Vec::new(),
4756 operator_comments: Vec::new(),
4757 trailing_comments: Vec::new(),
4758 inferred_type: None,
4759 }));
4760 if is_date_type {
4761 Ok(Expression::Cast(Box::new(Cast {
4762 this: bucket_plus,
4763 to: DataType::Date,
4764 trailing_comments: Vec::new(),
4765 double_colon_syntax: false,
4766 format: None,
4767 default: None,
4768 inferred_type: None,
4769 })))
4770 } else {
4771 Ok(bucket_plus)
4772 }
4773 } else {
4774 Ok(time_bucket)
4775 }
4776 }
4777
4778 "DATE_FROM_PARTS" | "DATEFROMPARTS" if f.args.len() == 3 => {
4780 let mut args = f.args;
4781 let year = args.remove(0);
4782 let month = args.remove(0);
4783 let day = args.remove(0);
4784
4785 let make_date = Expression::Function(Box::new(Function::new(
4786 "MAKE_DATE".to_string(),
4787 vec![year, Expression::number(1), Expression::number(1)],
4788 )));
4789
4790 let month_wrapped = match &month {
4792 Expression::Add(_)
4793 | Expression::Sub(_)
4794 | Expression::Mul(_)
4795 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4796 this: month,
4797 trailing_comments: Vec::new(),
4798 })),
4799 _ => month,
4800 };
4801 let day_wrapped = match &day {
4802 Expression::Add(_)
4803 | Expression::Sub(_)
4804 | Expression::Mul(_)
4805 | Expression::Div(_) => Expression::Paren(Box::new(Paren {
4806 this: day,
4807 trailing_comments: Vec::new(),
4808 })),
4809 _ => day,
4810 };
4811 let month_minus_1 = Expression::Sub(Box::new(BinaryOp {
4812 left: month_wrapped,
4813 right: Expression::number(1),
4814 left_comments: Vec::new(),
4815 operator_comments: Vec::new(),
4816 trailing_comments: Vec::new(),
4817 inferred_type: None,
4818 }));
4819 let month_interval = Expression::Interval(Box::new(Interval {
4820 this: Some(Expression::Paren(Box::new(Paren {
4821 this: month_minus_1,
4822 trailing_comments: Vec::new(),
4823 }))),
4824 unit: Some(IntervalUnitSpec::Simple {
4825 unit: IntervalUnit::Month,
4826 use_plural: false,
4827 }),
4828 }));
4829
4830 let day_minus_1 = Expression::Sub(Box::new(BinaryOp {
4831 left: day_wrapped,
4832 right: Expression::number(1),
4833 left_comments: Vec::new(),
4834 operator_comments: Vec::new(),
4835 trailing_comments: Vec::new(),
4836 inferred_type: None,
4837 }));
4838 let day_interval = Expression::Interval(Box::new(Interval {
4839 this: Some(Expression::Paren(Box::new(Paren {
4840 this: day_minus_1,
4841 trailing_comments: Vec::new(),
4842 }))),
4843 unit: Some(IntervalUnitSpec::Simple {
4844 unit: IntervalUnit::Day,
4845 use_plural: false,
4846 }),
4847 }));
4848
4849 let result = Expression::Add(Box::new(BinaryOp {
4850 left: Expression::Add(Box::new(BinaryOp {
4851 left: make_date,
4852 right: month_interval,
4853 left_comments: Vec::new(),
4854 operator_comments: Vec::new(),
4855 trailing_comments: Vec::new(),
4856 inferred_type: None,
4857 })),
4858 right: day_interval,
4859 left_comments: Vec::new(),
4860 operator_comments: Vec::new(),
4861 trailing_comments: Vec::new(),
4862 inferred_type: None,
4863 }));
4864
4865 Ok(Expression::Cast(Box::new(Cast {
4866 this: result,
4867 to: DataType::Date,
4868 trailing_comments: Vec::new(),
4869 double_colon_syntax: false,
4870 format: None,
4871 default: None,
4872 inferred_type: None,
4873 })))
4874 }
4875
4876 "NEXT_DAY" if f.args.len() == 2 => {
4878 let mut args = f.args;
4879 let date = args.remove(0);
4880 let day_name = args.remove(0);
4881
4882 let day_num = match &day_name {
4884 Expression::Literal(Literal::String(s)) => {
4885 let upper = s.to_uppercase();
4886 if upper.starts_with("MO") {
4887 Some(1)
4888 } else if upper.starts_with("TU") {
4889 Some(2)
4890 } else if upper.starts_with("WE") {
4891 Some(3)
4892 } else if upper.starts_with("TH") {
4893 Some(4)
4894 } else if upper.starts_with("FR") {
4895 Some(5)
4896 } else if upper.starts_with("SA") {
4897 Some(6)
4898 } else if upper.starts_with("SU") {
4899 Some(7)
4900 } else {
4901 None
4902 }
4903 }
4904 _ => None,
4905 };
4906
4907 let target_day_expr = if let Some(n) = day_num {
4908 Expression::number(n)
4909 } else {
4910 Expression::Case(Box::new(Case {
4912 operand: None,
4913 whens: vec![
4914 (
4915 Expression::Function(Box::new(Function::new(
4916 "STARTS_WITH".to_string(),
4917 vec![
4918 Expression::Upper(Box::new(UnaryFunc::new(
4919 day_name.clone(),
4920 ))),
4921 Expression::Literal(Literal::String("MO".to_string())),
4922 ],
4923 ))),
4924 Expression::number(1),
4925 ),
4926 (
4927 Expression::Function(Box::new(Function::new(
4928 "STARTS_WITH".to_string(),
4929 vec![
4930 Expression::Upper(Box::new(UnaryFunc::new(
4931 day_name.clone(),
4932 ))),
4933 Expression::Literal(Literal::String("TU".to_string())),
4934 ],
4935 ))),
4936 Expression::number(2),
4937 ),
4938 (
4939 Expression::Function(Box::new(Function::new(
4940 "STARTS_WITH".to_string(),
4941 vec![
4942 Expression::Upper(Box::new(UnaryFunc::new(
4943 day_name.clone(),
4944 ))),
4945 Expression::Literal(Literal::String("WE".to_string())),
4946 ],
4947 ))),
4948 Expression::number(3),
4949 ),
4950 (
4951 Expression::Function(Box::new(Function::new(
4952 "STARTS_WITH".to_string(),
4953 vec![
4954 Expression::Upper(Box::new(UnaryFunc::new(
4955 day_name.clone(),
4956 ))),
4957 Expression::Literal(Literal::String("TH".to_string())),
4958 ],
4959 ))),
4960 Expression::number(4),
4961 ),
4962 (
4963 Expression::Function(Box::new(Function::new(
4964 "STARTS_WITH".to_string(),
4965 vec![
4966 Expression::Upper(Box::new(UnaryFunc::new(
4967 day_name.clone(),
4968 ))),
4969 Expression::Literal(Literal::String("FR".to_string())),
4970 ],
4971 ))),
4972 Expression::number(5),
4973 ),
4974 (
4975 Expression::Function(Box::new(Function::new(
4976 "STARTS_WITH".to_string(),
4977 vec![
4978 Expression::Upper(Box::new(UnaryFunc::new(
4979 day_name.clone(),
4980 ))),
4981 Expression::Literal(Literal::String("SA".to_string())),
4982 ],
4983 ))),
4984 Expression::number(6),
4985 ),
4986 (
4987 Expression::Function(Box::new(Function::new(
4988 "STARTS_WITH".to_string(),
4989 vec![
4990 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
4991 Expression::Literal(Literal::String("SU".to_string())),
4992 ],
4993 ))),
4994 Expression::number(7),
4995 ),
4996 ],
4997 else_: None,
4998 comments: Vec::new(),
4999 inferred_type: None,
5000 }))
5001 };
5002
5003 let isodow = Expression::Function(Box::new(Function::new(
5004 "ISODOW".to_string(),
5005 vec![date.clone()],
5006 )));
5007 let diff = Expression::Add(Box::new(BinaryOp {
5009 left: Expression::Paren(Box::new(Paren {
5010 this: Expression::Mod(Box::new(BinaryOp {
5011 left: Expression::Paren(Box::new(Paren {
5012 this: Expression::Add(Box::new(BinaryOp {
5013 left: Expression::Paren(Box::new(Paren {
5014 this: Expression::Sub(Box::new(BinaryOp {
5015 left: target_day_expr,
5016 right: isodow,
5017 left_comments: Vec::new(),
5018 operator_comments: Vec::new(),
5019 trailing_comments: Vec::new(),
5020 inferred_type: None,
5021 })),
5022 trailing_comments: Vec::new(),
5023 })),
5024 right: Expression::number(6),
5025 left_comments: Vec::new(),
5026 operator_comments: Vec::new(),
5027 trailing_comments: Vec::new(),
5028 inferred_type: None,
5029 })),
5030 trailing_comments: Vec::new(),
5031 })),
5032 right: Expression::number(7),
5033 left_comments: Vec::new(),
5034 operator_comments: Vec::new(),
5035 trailing_comments: Vec::new(),
5036 inferred_type: None,
5037 })),
5038 trailing_comments: Vec::new(),
5039 })),
5040 right: Expression::number(1),
5041 left_comments: Vec::new(),
5042 operator_comments: Vec::new(),
5043 trailing_comments: Vec::new(),
5044 inferred_type: None,
5045 }));
5046
5047 let result = Expression::Add(Box::new(BinaryOp {
5048 left: date,
5049 right: Expression::Interval(Box::new(Interval {
5050 this: Some(Expression::Paren(Box::new(Paren {
5051 this: diff,
5052 trailing_comments: Vec::new(),
5053 }))),
5054 unit: Some(IntervalUnitSpec::Simple {
5055 unit: IntervalUnit::Day,
5056 use_plural: false,
5057 }),
5058 })),
5059 left_comments: Vec::new(),
5060 operator_comments: Vec::new(),
5061 trailing_comments: Vec::new(),
5062 inferred_type: None,
5063 }));
5064
5065 Ok(Expression::Cast(Box::new(Cast {
5066 this: result,
5067 to: DataType::Date,
5068 trailing_comments: Vec::new(),
5069 double_colon_syntax: false,
5070 format: None,
5071 default: None,
5072 inferred_type: None,
5073 })))
5074 }
5075
5076 "PREVIOUS_DAY" if f.args.len() == 2 => {
5078 let mut args = f.args;
5079 let date = args.remove(0);
5080 let day_name = args.remove(0);
5081
5082 let day_num = match &day_name {
5083 Expression::Literal(Literal::String(s)) => {
5084 let upper = s.to_uppercase();
5085 if upper.starts_with("MO") {
5086 Some(1)
5087 } else if upper.starts_with("TU") {
5088 Some(2)
5089 } else if upper.starts_with("WE") {
5090 Some(3)
5091 } else if upper.starts_with("TH") {
5092 Some(4)
5093 } else if upper.starts_with("FR") {
5094 Some(5)
5095 } else if upper.starts_with("SA") {
5096 Some(6)
5097 } else if upper.starts_with("SU") {
5098 Some(7)
5099 } else {
5100 None
5101 }
5102 }
5103 _ => None,
5104 };
5105
5106 let target_day_expr = if let Some(n) = day_num {
5107 Expression::number(n)
5108 } else {
5109 Expression::Case(Box::new(Case {
5110 operand: None,
5111 whens: vec![
5112 (
5113 Expression::Function(Box::new(Function::new(
5114 "STARTS_WITH".to_string(),
5115 vec![
5116 Expression::Upper(Box::new(UnaryFunc::new(
5117 day_name.clone(),
5118 ))),
5119 Expression::Literal(Literal::String("MO".to_string())),
5120 ],
5121 ))),
5122 Expression::number(1),
5123 ),
5124 (
5125 Expression::Function(Box::new(Function::new(
5126 "STARTS_WITH".to_string(),
5127 vec![
5128 Expression::Upper(Box::new(UnaryFunc::new(
5129 day_name.clone(),
5130 ))),
5131 Expression::Literal(Literal::String("TU".to_string())),
5132 ],
5133 ))),
5134 Expression::number(2),
5135 ),
5136 (
5137 Expression::Function(Box::new(Function::new(
5138 "STARTS_WITH".to_string(),
5139 vec![
5140 Expression::Upper(Box::new(UnaryFunc::new(
5141 day_name.clone(),
5142 ))),
5143 Expression::Literal(Literal::String("WE".to_string())),
5144 ],
5145 ))),
5146 Expression::number(3),
5147 ),
5148 (
5149 Expression::Function(Box::new(Function::new(
5150 "STARTS_WITH".to_string(),
5151 vec![
5152 Expression::Upper(Box::new(UnaryFunc::new(
5153 day_name.clone(),
5154 ))),
5155 Expression::Literal(Literal::String("TH".to_string())),
5156 ],
5157 ))),
5158 Expression::number(4),
5159 ),
5160 (
5161 Expression::Function(Box::new(Function::new(
5162 "STARTS_WITH".to_string(),
5163 vec![
5164 Expression::Upper(Box::new(UnaryFunc::new(
5165 day_name.clone(),
5166 ))),
5167 Expression::Literal(Literal::String("FR".to_string())),
5168 ],
5169 ))),
5170 Expression::number(5),
5171 ),
5172 (
5173 Expression::Function(Box::new(Function::new(
5174 "STARTS_WITH".to_string(),
5175 vec![
5176 Expression::Upper(Box::new(UnaryFunc::new(
5177 day_name.clone(),
5178 ))),
5179 Expression::Literal(Literal::String("SA".to_string())),
5180 ],
5181 ))),
5182 Expression::number(6),
5183 ),
5184 (
5185 Expression::Function(Box::new(Function::new(
5186 "STARTS_WITH".to_string(),
5187 vec![
5188 Expression::Upper(Box::new(UnaryFunc::new(day_name))),
5189 Expression::Literal(Literal::String("SU".to_string())),
5190 ],
5191 ))),
5192 Expression::number(7),
5193 ),
5194 ],
5195 else_: None,
5196 comments: Vec::new(),
5197 inferred_type: None,
5198 }))
5199 };
5200
5201 let isodow = Expression::Function(Box::new(Function::new(
5202 "ISODOW".to_string(),
5203 vec![date.clone()],
5204 )));
5205 let diff = Expression::Add(Box::new(BinaryOp {
5207 left: Expression::Paren(Box::new(Paren {
5208 this: Expression::Mod(Box::new(BinaryOp {
5209 left: Expression::Paren(Box::new(Paren {
5210 this: Expression::Add(Box::new(BinaryOp {
5211 left: Expression::Paren(Box::new(Paren {
5212 this: Expression::Sub(Box::new(BinaryOp {
5213 left: isodow,
5214 right: target_day_expr,
5215 left_comments: Vec::new(),
5216 operator_comments: Vec::new(),
5217 trailing_comments: Vec::new(),
5218 inferred_type: None,
5219 })),
5220 trailing_comments: Vec::new(),
5221 })),
5222 right: Expression::number(6),
5223 left_comments: Vec::new(),
5224 operator_comments: Vec::new(),
5225 trailing_comments: Vec::new(),
5226 inferred_type: None,
5227 })),
5228 trailing_comments: Vec::new(),
5229 })),
5230 right: Expression::number(7),
5231 left_comments: Vec::new(),
5232 operator_comments: Vec::new(),
5233 trailing_comments: Vec::new(),
5234 inferred_type: None,
5235 })),
5236 trailing_comments: Vec::new(),
5237 })),
5238 right: Expression::number(1),
5239 left_comments: Vec::new(),
5240 operator_comments: Vec::new(),
5241 trailing_comments: Vec::new(),
5242 inferred_type: None,
5243 }));
5244
5245 let result = Expression::Sub(Box::new(BinaryOp {
5246 left: date,
5247 right: Expression::Interval(Box::new(Interval {
5248 this: Some(Expression::Paren(Box::new(Paren {
5249 this: diff,
5250 trailing_comments: Vec::new(),
5251 }))),
5252 unit: Some(IntervalUnitSpec::Simple {
5253 unit: IntervalUnit::Day,
5254 use_plural: false,
5255 }),
5256 })),
5257 left_comments: Vec::new(),
5258 operator_comments: Vec::new(),
5259 trailing_comments: Vec::new(),
5260 inferred_type: None,
5261 }));
5262
5263 Ok(Expression::Cast(Box::new(Cast {
5264 this: result,
5265 to: DataType::Date,
5266 trailing_comments: Vec::new(),
5267 double_colon_syntax: false,
5268 format: None,
5269 default: None,
5270 inferred_type: None,
5271 })))
5272 }
5273
5274 "LAST_DAY" if f.args.len() == 2 => {
5278 let mut args = f.args;
5279 let date = args.remove(0);
5280 let unit = args.remove(0);
5281 let unit_str = match &unit {
5282 Expression::Column(c) => c.name.name.to_uppercase(),
5283 Expression::Identifier(i) => i.name.to_uppercase(),
5284 _ => String::new(),
5285 };
5286
5287 match unit_str.as_str() {
5288 "MONTH" => Ok(Expression::Function(Box::new(Function::new(
5289 "LAST_DAY".to_string(),
5290 vec![date],
5291 )))),
5292 "YEAR" => Ok(Expression::Function(Box::new(Function::new(
5293 "MAKE_DATE".to_string(),
5294 vec![
5295 Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5296 this: date,
5297 field: crate::expressions::DateTimeField::Year,
5298 })),
5299 Expression::number(12),
5300 Expression::number(31),
5301 ],
5302 )))),
5303 "QUARTER" => {
5304 let year = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5305 this: date.clone(),
5306 field: crate::expressions::DateTimeField::Year,
5307 }));
5308 let quarter_month = Expression::Mul(Box::new(BinaryOp {
5309 left: Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5310 this: date,
5311 field: crate::expressions::DateTimeField::Custom(
5312 "QUARTER".to_string(),
5313 ),
5314 })),
5315 right: Expression::number(3),
5316 left_comments: Vec::new(),
5317 operator_comments: Vec::new(),
5318 trailing_comments: Vec::new(),
5319 inferred_type: None,
5320 }));
5321 let make_date = Expression::Function(Box::new(Function::new(
5322 "MAKE_DATE".to_string(),
5323 vec![year, quarter_month, Expression::number(1)],
5324 )));
5325 Ok(Expression::Function(Box::new(Function::new(
5326 "LAST_DAY".to_string(),
5327 vec![make_date],
5328 ))))
5329 }
5330 "WEEK" => {
5331 let dow = Expression::Extract(Box::new(crate::expressions::ExtractFunc {
5332 this: date.clone(),
5333 field: crate::expressions::DateTimeField::Custom(
5334 "DAYOFWEEK".to_string(),
5335 ),
5336 }));
5337 let diff = Expression::Mod(Box::new(BinaryOp {
5338 left: Expression::Paren(Box::new(Paren {
5339 this: Expression::Sub(Box::new(BinaryOp {
5340 left: Expression::number(7),
5341 right: dow,
5342 left_comments: Vec::new(),
5343 operator_comments: Vec::new(),
5344 trailing_comments: Vec::new(),
5345 inferred_type: None,
5346 })),
5347 trailing_comments: Vec::new(),
5348 })),
5349 right: Expression::number(7),
5350 left_comments: Vec::new(),
5351 operator_comments: Vec::new(),
5352 trailing_comments: Vec::new(),
5353 inferred_type: None,
5354 }));
5355 let result = Expression::Add(Box::new(BinaryOp {
5356 left: date,
5357 right: Expression::Interval(Box::new(Interval {
5358 this: Some(Expression::Paren(Box::new(Paren {
5359 this: diff,
5360 trailing_comments: Vec::new(),
5361 }))),
5362 unit: Some(IntervalUnitSpec::Simple {
5363 unit: IntervalUnit::Day,
5364 use_plural: false,
5365 }),
5366 })),
5367 left_comments: Vec::new(),
5368 operator_comments: Vec::new(),
5369 trailing_comments: Vec::new(),
5370 inferred_type: None,
5371 }));
5372 Ok(Expression::Cast(Box::new(Cast {
5373 this: result,
5374 to: DataType::Date,
5375 trailing_comments: Vec::new(),
5376 double_colon_syntax: false,
5377 format: None,
5378 default: None,
5379 inferred_type: None,
5380 })))
5381 }
5382 _ => Ok(Expression::Function(Box::new(Function::new(
5383 "LAST_DAY".to_string(),
5384 vec![date, unit],
5385 )))),
5386 }
5387 }
5388
5389 "SEQ1" | "SEQ2" | "SEQ4" | "SEQ8" => {
5392 let (range, half): (u128, u128) = match name_upper.as_str() {
5393 "SEQ1" => (256, 128),
5394 "SEQ2" => (65536, 32768),
5395 "SEQ4" => (4294967296, 2147483648),
5396 "SEQ8" => (18446744073709551616, 9223372036854775808),
5397 _ => unreachable!("sequence type already matched in caller"),
5398 };
5399
5400 let is_signed = match f.args.first() {
5401 Some(Expression::Literal(Literal::Number(n))) => n == "1",
5402 _ => false,
5403 };
5404
5405 let row_num = Expression::Sub(Box::new(BinaryOp {
5406 left: Expression::WindowFunction(Box::new(
5407 crate::expressions::WindowFunction {
5408 this: Expression::Function(Box::new(Function::new(
5409 "ROW_NUMBER".to_string(),
5410 vec![],
5411 ))),
5412 over: crate::expressions::Over {
5413 window_name: None,
5414 partition_by: vec![],
5415 order_by: vec![crate::expressions::Ordered {
5416 this: Expression::number(1),
5417 desc: false,
5418 nulls_first: Some(true),
5419 explicit_asc: false,
5420 with_fill: None,
5421 }],
5422 frame: None,
5423 alias: None,
5424 },
5425 keep: None,
5426 inferred_type: None,
5427 },
5428 )),
5429 right: Expression::number(1),
5430 left_comments: Vec::new(),
5431 operator_comments: Vec::new(),
5432 trailing_comments: Vec::new(),
5433 inferred_type: None,
5434 }));
5435
5436 let modded = Expression::Mod(Box::new(BinaryOp {
5437 left: Expression::Paren(Box::new(Paren {
5438 this: row_num,
5439 trailing_comments: Vec::new(),
5440 })),
5441 right: Expression::Literal(Literal::Number(range.to_string())),
5442 left_comments: Vec::new(),
5443 operator_comments: Vec::new(),
5444 trailing_comments: Vec::new(),
5445 inferred_type: None,
5446 }));
5447
5448 if is_signed {
5449 let cond = Expression::Gte(Box::new(BinaryOp {
5451 left: modded.clone(),
5452 right: Expression::Literal(Literal::Number(half.to_string())),
5453 left_comments: Vec::new(),
5454 operator_comments: Vec::new(),
5455 trailing_comments: Vec::new(),
5456 inferred_type: None,
5457 }));
5458 let signed_val = Expression::Sub(Box::new(BinaryOp {
5459 left: modded.clone(),
5460 right: Expression::Literal(Literal::Number(range.to_string())),
5461 left_comments: Vec::new(),
5462 operator_comments: Vec::new(),
5463 trailing_comments: Vec::new(),
5464 inferred_type: None,
5465 }));
5466 Ok(Expression::Paren(Box::new(Paren {
5467 this: Expression::Case(Box::new(Case {
5468 operand: None,
5469 whens: vec![(cond, signed_val)],
5470 else_: Some(modded),
5471 comments: Vec::new(),
5472 inferred_type: None,
5473 })),
5474 trailing_comments: Vec::new(),
5475 })))
5476 } else {
5477 Ok(modded)
5478 }
5479 }
5480
5481 "TABLE" if f.args.len() == 1 => {
5484 let inner = f.args.into_iter().next().unwrap();
5485 if let Expression::Function(ref gen_f) = inner {
5487 if gen_f.name.to_uppercase() == "GENERATOR" {
5488 let mut rowcount = None;
5489 for arg in &gen_f.args {
5490 if let Expression::NamedArgument(na) = arg {
5491 if na.name.name.to_uppercase() == "ROWCOUNT" {
5492 rowcount = Some(na.value.clone());
5493 }
5494 }
5495 }
5496 if let Some(n) = rowcount {
5497 return Ok(Expression::Function(Box::new(Function::new(
5498 "RANGE".to_string(),
5499 vec![n],
5500 ))));
5501 }
5502 }
5503 }
5504 Ok(inner)
5505 }
5506
5507 "GENERATOR" => {
5509 let mut rowcount = None;
5510 for arg in &f.args {
5511 if let Expression::NamedArgument(na) = arg {
5512 if na.name.name.to_uppercase() == "ROWCOUNT" {
5513 rowcount = Some(na.value.clone());
5514 }
5515 }
5516 }
5517 if let Some(n) = rowcount {
5518 Ok(Expression::Function(Box::new(Function::new(
5519 "RANGE".to_string(),
5520 vec![n],
5521 ))))
5522 } else {
5523 Ok(Expression::Function(Box::new(f)))
5524 }
5525 }
5526
5527 "UNIFORM" if f.args.len() == 3 => {
5530 let mut args = f.args;
5531 let low = args.remove(0);
5532 let high = args.remove(0);
5533 let gen = args.remove(0);
5534
5535 let range = Expression::Add(Box::new(BinaryOp {
5536 left: Expression::Sub(Box::new(BinaryOp {
5537 left: high,
5538 right: low.clone(),
5539 left_comments: Vec::new(),
5540 operator_comments: Vec::new(),
5541 trailing_comments: Vec::new(),
5542 inferred_type: None,
5543 })),
5544 right: Expression::number(1),
5545 left_comments: Vec::new(),
5546 operator_comments: Vec::new(),
5547 trailing_comments: Vec::new(),
5548 inferred_type: None,
5549 }));
5550
5551 let random_val = match &gen {
5553 Expression::Rand(_) | Expression::Random(_) => {
5554 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5556 }
5557 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
5558 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
5560 }
5561 _ => {
5562 let hash = Expression::Function(Box::new(Function::new(
5564 "HASH".to_string(),
5565 vec![gen],
5566 )));
5567 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
5568 let modded = Expression::Mod(Box::new(BinaryOp {
5569 left: abs_hash,
5570 right: Expression::number(1000000),
5571 left_comments: Vec::new(),
5572 operator_comments: Vec::new(),
5573 trailing_comments: Vec::new(),
5574 inferred_type: None,
5575 }));
5576 let paren_modded = Expression::Paren(Box::new(Paren {
5577 this: modded,
5578 trailing_comments: Vec::new(),
5579 }));
5580 Expression::Div(Box::new(BinaryOp {
5581 left: paren_modded,
5582 right: Expression::Literal(Literal::Number("1000000.0".to_string())),
5583 left_comments: Vec::new(),
5584 operator_comments: Vec::new(),
5585 trailing_comments: Vec::new(),
5586 inferred_type: None,
5587 }))
5588 }
5589 };
5590
5591 let inner = Expression::Function(Box::new(Function::new(
5592 "FLOOR".to_string(),
5593 vec![Expression::Add(Box::new(BinaryOp {
5594 left: low,
5595 right: Expression::Mul(Box::new(BinaryOp {
5596 left: random_val,
5597 right: Expression::Paren(Box::new(Paren {
5598 this: range,
5599 trailing_comments: Vec::new(),
5600 })),
5601 left_comments: Vec::new(),
5602 operator_comments: Vec::new(),
5603 trailing_comments: Vec::new(),
5604 inferred_type: None,
5605 })),
5606 left_comments: Vec::new(),
5607 operator_comments: Vec::new(),
5608 trailing_comments: Vec::new(),
5609 inferred_type: None,
5610 }))],
5611 )));
5612
5613 Ok(Expression::Cast(Box::new(Cast {
5614 this: inner,
5615 to: DataType::BigInt { length: None },
5616 trailing_comments: Vec::new(),
5617 double_colon_syntax: false,
5618 format: None,
5619 default: None,
5620 inferred_type: None,
5621 })))
5622 }
5623
5624 "NORMAL" if f.args.len() == 3 => {
5628 let mut args = f.args;
5629 let mean = args.remove(0);
5630 let stddev = args.remove(0);
5631 let gen = args.remove(0);
5632
5633 let make_seed_random = |seed: Expression| -> Expression {
5635 let hash = Expression::Function(Box::new(Function::new(
5636 "HASH".to_string(),
5637 vec![seed],
5638 )));
5639 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
5640 let modded = Expression::Mod(Box::new(BinaryOp {
5641 left: abs_hash,
5642 right: Expression::number(1000000),
5643 left_comments: Vec::new(),
5644 operator_comments: Vec::new(),
5645 trailing_comments: Vec::new(),
5646 inferred_type: None,
5647 }));
5648 let paren_modded = Expression::Paren(Box::new(Paren {
5649 this: modded,
5650 trailing_comments: Vec::new(),
5651 }));
5652 Expression::Div(Box::new(BinaryOp {
5653 left: paren_modded,
5654 right: Expression::Literal(Literal::Number("1000000.0".to_string())),
5655 left_comments: Vec::new(),
5656 operator_comments: Vec::new(),
5657 trailing_comments: Vec::new(),
5658 inferred_type: None,
5659 }))
5660 };
5661
5662 let is_random_no_seed = match &gen {
5664 Expression::Random(_) => true,
5665 Expression::Rand(r) => r.seed.is_none(),
5666 _ => false,
5667 };
5668 let (u1, u2) = if is_random_no_seed {
5669 let u1 =
5671 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
5672 let u2 =
5673 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
5674 (u1, u2)
5675 } else {
5676 let seed = match gen {
5678 Expression::Rand(r) => r.seed.map(|s| *s).unwrap_or(Expression::number(0)),
5679 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
5680 if func.args.len() == 1 {
5681 func.args.into_iter().next().unwrap()
5682 } else {
5683 Expression::number(0)
5684 }
5685 }
5686 other => other,
5687 };
5688 let u1 = make_seed_random(seed.clone());
5689 let seed_plus_1 = Expression::Add(Box::new(BinaryOp {
5690 left: seed,
5691 right: Expression::number(1),
5692 left_comments: Vec::new(),
5693 operator_comments: Vec::new(),
5694 trailing_comments: Vec::new(),
5695 inferred_type: None,
5696 }));
5697 let u2 = make_seed_random(seed_plus_1);
5698 (u1, u2)
5699 };
5700
5701 let greatest = Expression::Greatest(Box::new(VarArgFunc {
5703 expressions: vec![
5704 u1,
5705 Expression::Literal(Literal::Number("1e-10".to_string())),
5706 ],
5707 original_name: None,
5708 inferred_type: None,
5709 }));
5710
5711 let neg2 = Expression::Neg(Box::new(crate::expressions::UnaryOp {
5713 this: Expression::number(2),
5714 inferred_type: None,
5715 }));
5716 let ln_greatest =
5717 Expression::Function(Box::new(Function::new("LN".to_string(), vec![greatest])));
5718 let neg2_times_ln = Expression::Mul(Box::new(BinaryOp {
5719 left: neg2,
5720 right: ln_greatest,
5721 left_comments: Vec::new(),
5722 operator_comments: Vec::new(),
5723 trailing_comments: Vec::new(),
5724 inferred_type: None,
5725 }));
5726 let sqrt_part = Expression::Function(Box::new(Function::new(
5727 "SQRT".to_string(),
5728 vec![neg2_times_ln],
5729 )));
5730
5731 let pi = Expression::Function(Box::new(Function::new("PI".to_string(), vec![])));
5733 let two_pi = Expression::Mul(Box::new(BinaryOp {
5734 left: Expression::number(2),
5735 right: pi,
5736 left_comments: Vec::new(),
5737 operator_comments: Vec::new(),
5738 trailing_comments: Vec::new(),
5739 inferred_type: None,
5740 }));
5741 let two_pi_u2 = Expression::Mul(Box::new(BinaryOp {
5742 left: two_pi,
5743 right: u2,
5744 left_comments: Vec::new(),
5745 operator_comments: Vec::new(),
5746 trailing_comments: Vec::new(),
5747 inferred_type: None,
5748 }));
5749 let cos_part = Expression::Function(Box::new(Function::new(
5750 "COS".to_string(),
5751 vec![two_pi_u2],
5752 )));
5753
5754 let stddev_times_sqrt = Expression::Mul(Box::new(BinaryOp {
5756 left: stddev,
5757 right: sqrt_part,
5758 left_comments: Vec::new(),
5759 operator_comments: Vec::new(),
5760 trailing_comments: Vec::new(),
5761 inferred_type: None,
5762 }));
5763 let inner = Expression::Mul(Box::new(BinaryOp {
5764 left: stddev_times_sqrt,
5765 right: cos_part,
5766 left_comments: Vec::new(),
5767 operator_comments: Vec::new(),
5768 trailing_comments: Vec::new(),
5769 inferred_type: None,
5770 }));
5771 let paren_inner = Expression::Paren(Box::new(Paren {
5772 this: inner,
5773 trailing_comments: Vec::new(),
5774 }));
5775
5776 Ok(Expression::Add(Box::new(BinaryOp {
5778 left: mean,
5779 right: paren_inner,
5780 left_comments: Vec::new(),
5781 operator_comments: Vec::new(),
5782 trailing_comments: Vec::new(),
5783 inferred_type: None,
5784 })))
5785 }
5786
5787 "ZIPF" if f.args.len() == 3 => {
5797 let mut args = f.args;
5798 let s_expr = args.remove(0);
5799 let n_expr = args.remove(0);
5800 let gen_expr = args.remove(0);
5801
5802 let s_sql = Self::expr_to_sql(&s_expr);
5803 let n_sql = Self::expr_to_sql(&n_expr);
5804 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
5805
5806 let rand_sql = if is_random {
5807 format!("SELECT {} AS r", seed_sql)
5808 } else {
5809 format!(
5810 "SELECT (ABS(HASH({})) % 1000000) / 1000000.0 AS r",
5811 seed_sql
5812 )
5813 };
5814
5815 let template = format!(
5816 "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)",
5817 rand_sql, s_sql, n_sql
5818 );
5819
5820 Self::parse_as_subquery(&template)
5821 }
5822
5823 "RANDSTR" if f.args.len() == 2 => {
5825 let mut args = f.args;
5826 let len_expr = args.remove(0);
5827 let gen_expr = args.remove(0);
5828
5829 let len_sql = Self::expr_to_sql(&len_expr);
5830 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
5831
5832 let random_value_sql = if is_random {
5833 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
5834 } else {
5835 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
5836 };
5837
5838 let template = format!(
5839 "SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT {} AS random_value FROM RANGE({}) AS t(i))",
5840 random_value_sql, len_sql
5841 );
5842
5843 Self::parse_as_subquery(&template)
5844 }
5845
5846 "MAP_CAT" if f.args.len() == 2 => {
5848 let mut args = f.args;
5849 let left = Self::normalize_empty_map_expr(args.remove(0));
5850 let right = Self::normalize_empty_map_expr(args.remove(0));
5851 let left_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
5852 this: left.clone(),
5853 not: false,
5854 postfix_form: false,
5855 }));
5856 let right_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
5857 this: right.clone(),
5858 not: false,
5859 postfix_form: false,
5860 }));
5861 let null_cond = Expression::Or(Box::new(BinaryOp {
5862 left: left_is_null,
5863 right: right_is_null,
5864 left_comments: Vec::new(),
5865 operator_comments: Vec::new(),
5866 trailing_comments: Vec::new(),
5867 inferred_type: None,
5868 }));
5869
5870 let list_concat = Expression::Function(Box::new(Function::new(
5871 "LIST_CONCAT".to_string(),
5872 vec![
5873 Expression::Function(Box::new(Function::new(
5874 "MAP_KEYS".to_string(),
5875 vec![left.clone()],
5876 ))),
5877 Expression::Function(Box::new(Function::new(
5878 "MAP_KEYS".to_string(),
5879 vec![right.clone()],
5880 ))),
5881 ],
5882 )));
5883 let list_distinct = Expression::Function(Box::new(Function::new(
5884 "LIST_DISTINCT".to_string(),
5885 vec![list_concat],
5886 )));
5887
5888 let k_ident = Identifier::new("__k");
5889 let k_ref = Expression::Column(Column {
5890 table: None,
5891 name: k_ident.clone(),
5892 join_mark: false,
5893 trailing_comments: Vec::new(),
5894 span: None,
5895 inferred_type: None,
5896 });
5897 let right_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
5898 this: right.clone(),
5899 index: k_ref.clone(),
5900 }));
5901 let left_key = Expression::Subscript(Box::new(crate::expressions::Subscript {
5902 this: left.clone(),
5903 index: k_ref.clone(),
5904 }));
5905 let key_value = Expression::Coalesce(Box::new(VarArgFunc {
5906 expressions: vec![right_key, left_key],
5907 original_name: None,
5908 inferred_type: None,
5909 }));
5910 let struct_pack = Expression::Function(Box::new(Function::new(
5911 "STRUCT_PACK".to_string(),
5912 vec![
5913 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
5914 name: Identifier::new("key"),
5915 value: k_ref.clone(),
5916 separator: crate::expressions::NamedArgSeparator::ColonEq,
5917 })),
5918 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
5919 name: Identifier::new("value"),
5920 value: key_value,
5921 separator: crate::expressions::NamedArgSeparator::ColonEq,
5922 })),
5923 ],
5924 )));
5925 let lambda_k = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
5926 parameters: vec![k_ident],
5927 body: struct_pack,
5928 colon: false,
5929 parameter_types: Vec::new(),
5930 }));
5931
5932 let list_transform = Expression::Function(Box::new(Function::new(
5933 "LIST_TRANSFORM".to_string(),
5934 vec![list_distinct, lambda_k],
5935 )));
5936
5937 let x_ident = Identifier::new("__x");
5938 let x_ref = Expression::Column(Column {
5939 table: None,
5940 name: x_ident.clone(),
5941 join_mark: false,
5942 trailing_comments: Vec::new(),
5943 span: None,
5944 inferred_type: None,
5945 });
5946 let x_value = Expression::Dot(Box::new(crate::expressions::DotAccess {
5947 this: x_ref,
5948 field: Identifier::new("value"),
5949 }));
5950 let x_value_is_null = Expression::IsNull(Box::new(crate::expressions::IsNull {
5951 this: x_value,
5952 not: false,
5953 postfix_form: false,
5954 }));
5955 let lambda_x = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
5956 parameters: vec![x_ident],
5957 body: Expression::Not(Box::new(crate::expressions::UnaryOp {
5958 this: x_value_is_null,
5959 inferred_type: None,
5960 })),
5961 colon: false,
5962 parameter_types: Vec::new(),
5963 }));
5964
5965 let list_filter = Expression::Function(Box::new(Function::new(
5966 "LIST_FILTER".to_string(),
5967 vec![list_transform, lambda_x],
5968 )));
5969 let merged_map = Expression::Function(Box::new(Function::new(
5970 "MAP_FROM_ENTRIES".to_string(),
5971 vec![list_filter],
5972 )));
5973
5974 Ok(Expression::Case(Box::new(Case {
5975 operand: None,
5976 whens: vec![(null_cond, Expression::Null(crate::expressions::Null))],
5977 else_: Some(merged_map),
5978 comments: Vec::new(),
5979 inferred_type: None,
5980 })))
5981 }
5982
5983 "MINHASH" if f.args.len() == 2 => {
5985 let mut args = f.args;
5986 let num_perm = args.remove(0);
5987 let value = args.remove(0);
5988
5989 let num_perm_sql = Self::expr_to_sql(&num_perm);
5990 let value_sql = Self::expr_to_sql(&value);
5991
5992 let template = format!(
5993 "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))",
5994 value = value_sql,
5995 num_perm = num_perm_sql
5996 );
5997
5998 Self::parse_as_subquery(&template)
5999 }
6000
6001 "MINHASH_COMBINE" if f.args.len() == 1 => {
6003 let sig_sql = Self::expr_to_sql(&f.args[0]);
6004 let template = format!(
6005 "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)",
6006 sig = sig_sql
6007 );
6008 Self::parse_as_subquery(&template)
6009 }
6010
6011 "APPROXIMATE_SIMILARITY" if f.args.len() == 1 => {
6013 let sig_sql = Self::expr_to_sql(&f.args[0]);
6014 let template = format!(
6015 "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)",
6016 sig = sig_sql
6017 );
6018 Self::parse_as_subquery(&template)
6019 }
6020
6021 "ARRAYS_ZIP" if !f.args.is_empty() => {
6023 let args = f.args;
6024 let n = args.len();
6025 let is_null = |expr: Expression| {
6026 Expression::IsNull(Box::new(crate::expressions::IsNull {
6027 this: expr,
6028 not: false,
6029 postfix_form: false,
6030 }))
6031 };
6032 let length_of = |expr: Expression| {
6033 Expression::Function(Box::new(Function::new("LENGTH".to_string(), vec![expr])))
6034 };
6035 let eq_zero = |expr: Expression| {
6036 Expression::Eq(Box::new(BinaryOp {
6037 left: expr,
6038 right: Expression::number(0),
6039 left_comments: Vec::new(),
6040 operator_comments: Vec::new(),
6041 trailing_comments: Vec::new(),
6042 inferred_type: None,
6043 }))
6044 };
6045 let and_expr = |left: Expression, right: Expression| {
6046 Expression::And(Box::new(BinaryOp {
6047 left,
6048 right,
6049 left_comments: Vec::new(),
6050 operator_comments: Vec::new(),
6051 trailing_comments: Vec::new(),
6052 inferred_type: None,
6053 }))
6054 };
6055 let or_expr = |left: Expression, right: Expression| {
6056 Expression::Or(Box::new(BinaryOp {
6057 left,
6058 right,
6059 left_comments: Vec::new(),
6060 operator_comments: Vec::new(),
6061 trailing_comments: Vec::new(),
6062 inferred_type: None,
6063 }))
6064 };
6065
6066 let null_cond = args.iter().cloned().map(is_null).reduce(or_expr).unwrap();
6067 let empty_cond = args
6068 .iter()
6069 .cloned()
6070 .map(|a| eq_zero(length_of(a)))
6071 .reduce(and_expr)
6072 .unwrap();
6073
6074 let null_struct = Expression::Struct(Box::new(Struct {
6075 fields: (1..=n)
6076 .map(|i| {
6077 (
6078 Some(format!("${}", i)),
6079 Expression::Null(crate::expressions::Null),
6080 )
6081 })
6082 .collect(),
6083 }));
6084 let empty_result = Expression::Array(Box::new(crate::expressions::Array {
6085 expressions: vec![null_struct],
6086 }));
6087
6088 let range_upper = if n == 1 {
6089 length_of(args[0].clone())
6090 } else {
6091 let length_null_cond = args
6092 .iter()
6093 .cloned()
6094 .map(|a| is_null(length_of(a)))
6095 .reduce(or_expr)
6096 .unwrap();
6097 let greatest_len = Expression::Greatest(Box::new(VarArgFunc {
6098 expressions: args.iter().cloned().map(length_of).collect(),
6099 original_name: None,
6100 inferred_type: None,
6101 }));
6102 Expression::Case(Box::new(Case {
6103 operand: None,
6104 whens: vec![(length_null_cond, Expression::Null(crate::expressions::Null))],
6105 else_: Some(greatest_len),
6106 comments: Vec::new(),
6107 inferred_type: None,
6108 }))
6109 };
6110
6111 let range_expr = Expression::Function(Box::new(Function::new(
6112 "RANGE".to_string(),
6113 vec![Expression::number(0), range_upper],
6114 )));
6115
6116 let i_ident = Identifier::new("__i");
6117 let i_ref = Expression::Column(Column {
6118 table: None,
6119 name: i_ident.clone(),
6120 join_mark: false,
6121 trailing_comments: Vec::new(),
6122 span: None,
6123 inferred_type: None,
6124 });
6125 let i_plus_one = Expression::Add(Box::new(BinaryOp {
6126 left: i_ref,
6127 right: Expression::number(1),
6128 left_comments: Vec::new(),
6129 operator_comments: Vec::new(),
6130 trailing_comments: Vec::new(),
6131 inferred_type: None,
6132 }));
6133 let empty_array = Expression::Array(Box::new(crate::expressions::Array {
6134 expressions: vec![],
6135 }));
6136 let zipped_struct = Expression::Struct(Box::new(Struct {
6137 fields: args
6138 .iter()
6139 .enumerate()
6140 .map(|(i, a)| {
6141 let coalesced = Expression::Coalesce(Box::new(VarArgFunc {
6142 expressions: vec![a.clone(), empty_array.clone()],
6143 original_name: None,
6144 inferred_type: None,
6145 }));
6146 let item =
6147 Expression::Subscript(Box::new(crate::expressions::Subscript {
6148 this: coalesced,
6149 index: i_plus_one.clone(),
6150 }));
6151 (Some(format!("${}", i + 1)), item)
6152 })
6153 .collect(),
6154 }));
6155 let lambda_i = Expression::Lambda(Box::new(crate::expressions::LambdaExpr {
6156 parameters: vec![i_ident],
6157 body: zipped_struct,
6158 colon: false,
6159 parameter_types: Vec::new(),
6160 }));
6161 let zipped_result = Expression::Function(Box::new(Function::new(
6162 "LIST_TRANSFORM".to_string(),
6163 vec![range_expr, lambda_i],
6164 )));
6165
6166 Ok(Expression::Case(Box::new(Case {
6167 operand: None,
6168 whens: vec![
6169 (null_cond, Expression::Null(crate::expressions::Null)),
6170 (empty_cond, empty_result),
6171 ],
6172 else_: Some(zipped_result),
6173 comments: Vec::new(),
6174 inferred_type: None,
6175 })))
6176 }
6177
6178 _ => Ok(Expression::Function(Box::new(f))),
6180 }
6181 }
6182
6183 fn convert_snowflake_date_format(&self, fmt: Expression) -> Expression {
6185 match fmt {
6186 Expression::Literal(Literal::String(s)) => {
6187 let converted = Self::snowflake_to_strptime(&s);
6188 Expression::Literal(Literal::String(converted))
6189 }
6190 _ => fmt,
6191 }
6192 }
6193
6194 fn convert_snowflake_time_format(&self, fmt: Expression) -> Expression {
6196 match fmt {
6197 Expression::Literal(Literal::String(s)) => {
6198 let converted = Self::snowflake_to_strptime(&s);
6199 Expression::Literal(Literal::String(converted))
6200 }
6201 _ => fmt,
6202 }
6203 }
6204
6205 fn snowflake_to_strptime(s: &str) -> String {
6208 let mut result = String::new();
6209 let chars: Vec<char> = s.chars().collect();
6210 let len = chars.len();
6211 let mut i = 0;
6212 while i < len {
6213 let remaining = &s[i..];
6214 let remaining_upper: String =
6215 remaining.chars().take(8).collect::<String>().to_uppercase();
6216
6217 if remaining_upper.starts_with("HH24MISS") {
6219 result.push_str("%H%M%S");
6220 i += 8;
6221 } else if remaining_upper.starts_with("MMMM") {
6222 result.push_str("%B");
6223 i += 4;
6224 } else if remaining_upper.starts_with("YYYY") {
6225 result.push_str("%Y");
6226 i += 4;
6227 } else if remaining_upper.starts_with("YY") {
6228 result.push_str("%y");
6229 i += 2;
6230 } else if remaining_upper.starts_with("MON") {
6231 result.push_str("%b");
6232 i += 3;
6233 } else if remaining_upper.starts_with("HH24") {
6234 result.push_str("%H");
6235 i += 4;
6236 } else if remaining_upper.starts_with("HH12") {
6237 result.push_str("%I");
6238 i += 4;
6239 } else if remaining_upper.starts_with("HH") {
6240 result.push_str("%I");
6241 i += 2;
6242 } else if remaining_upper.starts_with("MISS") {
6243 result.push_str("%M%S");
6244 i += 4;
6245 } else if remaining_upper.starts_with("MI") {
6246 result.push_str("%M");
6247 i += 2;
6248 } else if remaining_upper.starts_with("MM") {
6249 result.push_str("%m");
6250 i += 2;
6251 } else if remaining_upper.starts_with("DD") {
6252 result.push_str("%d");
6253 i += 2;
6254 } else if remaining_upper.starts_with("DY") {
6255 result.push_str("%a");
6256 i += 2;
6257 } else if remaining_upper.starts_with("SS") {
6258 result.push_str("%S");
6259 i += 2;
6260 } else if remaining_upper.starts_with("FF") {
6261 let ff_pos = i + 2;
6264 if ff_pos < len && chars[ff_pos].is_ascii_digit() {
6265 let digit = chars[ff_pos].to_digit(10).unwrap_or(6);
6266 if digit >= 7 {
6267 result.push_str("%n");
6268 } else {
6269 result.push_str("%f");
6270 }
6271 i += 3; } else {
6273 result.push_str("%f");
6274 i += 2;
6275 }
6276 } else if remaining_upper.starts_with("PM") || remaining_upper.starts_with("AM") {
6277 result.push_str("%p");
6278 i += 2;
6279 } else if remaining_upper.starts_with("TZH") {
6280 result.push_str("%z");
6281 i += 3;
6282 } else if remaining_upper.starts_with("TZM") {
6283 i += 3;
6285 } else {
6286 result.push(chars[i]);
6287 i += 1;
6288 }
6289 }
6290 result
6291 }
6292
6293 fn convert_bq_to_strptime_format(&self, fmt: Expression) -> Expression {
6296 match fmt {
6297 Expression::Literal(Literal::String(s)) => {
6298 let converted = s.replace("%E6S", "%S.%f").replace("%E*S", "%S.%f");
6299 Expression::Literal(Literal::String(converted))
6300 }
6301 _ => fmt,
6302 }
6303 }
6304
6305 fn transform_date_part(&self, args: Vec<Expression>) -> Result<Expression> {
6307 let mut args = args;
6308 let unit_expr = args.remove(0);
6309 let date_expr = args.remove(0);
6310 let unit_name = match &unit_expr {
6311 Expression::Column(c) => c.name.name.to_uppercase(),
6312 Expression::Identifier(i) => i.name.to_uppercase(),
6313 Expression::Var(v) => v.this.to_uppercase(),
6314 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
6315 _ => {
6316 return Ok(Expression::Function(Box::new(Function::new(
6317 "DATE_PART".to_string(),
6318 vec![unit_expr, date_expr],
6319 ))))
6320 }
6321 };
6322 match unit_name.as_str() {
6323 "EPOCH_SECOND" | "EPOCH" => Ok(Expression::Cast(Box::new(Cast {
6324 this: Expression::Function(Box::new(Function::new(
6325 "EPOCH".to_string(),
6326 vec![date_expr],
6327 ))),
6328 to: DataType::BigInt { length: None },
6329 trailing_comments: Vec::new(),
6330 double_colon_syntax: false,
6331 format: None,
6332 default: None,
6333 inferred_type: None,
6334 }))),
6335 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Ok(Expression::Function(Box::new(
6336 Function::new("EPOCH_MS".to_string(), vec![date_expr]),
6337 ))),
6338 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Ok(Expression::Function(Box::new(
6339 Function::new("EPOCH_US".to_string(), vec![date_expr]),
6340 ))),
6341 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Ok(Expression::Function(Box::new(
6342 Function::new("EPOCH_NS".to_string(), vec![date_expr]),
6343 ))),
6344 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Extract(Box::new(
6345 crate::expressions::ExtractFunc {
6346 this: date_expr,
6347 field: crate::expressions::DateTimeField::Custom("ISODOW".to_string()),
6348 },
6349 ))),
6350 "YEAROFWEEK" | "YEAROFWEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6351 this: Expression::Function(Box::new(Function::new(
6352 "STRFTIME".to_string(),
6353 vec![
6354 date_expr,
6355 Expression::Literal(Literal::String("%G".to_string())),
6356 ],
6357 ))),
6358 to: DataType::Int {
6359 length: None,
6360 integer_spelling: false,
6361 },
6362 trailing_comments: Vec::new(),
6363 double_colon_syntax: false,
6364 format: None,
6365 default: None,
6366 inferred_type: None,
6367 }))),
6368 "WEEKISO" => Ok(Expression::Cast(Box::new(Cast {
6369 this: Expression::Function(Box::new(Function::new(
6370 "STRFTIME".to_string(),
6371 vec![
6372 date_expr,
6373 Expression::Literal(Literal::String("%V".to_string())),
6374 ],
6375 ))),
6376 to: DataType::Int {
6377 length: None,
6378 integer_spelling: false,
6379 },
6380 trailing_comments: Vec::new(),
6381 double_colon_syntax: false,
6382 format: None,
6383 default: None,
6384 inferred_type: None,
6385 }))),
6386 "NANOSECOND" | "NANOSECONDS" | "NS" => Ok(Expression::Cast(Box::new(Cast {
6387 this: Expression::Function(Box::new(Function::new(
6388 "STRFTIME".to_string(),
6389 vec![
6390 Expression::Cast(Box::new(Cast {
6391 this: date_expr,
6392 to: DataType::Custom {
6393 name: "TIMESTAMP_NS".to_string(),
6394 },
6395 trailing_comments: Vec::new(),
6396 double_colon_syntax: false,
6397 format: None,
6398 default: None,
6399 inferred_type: None,
6400 })),
6401 Expression::Literal(Literal::String("%n".to_string())),
6402 ],
6403 ))),
6404 to: DataType::BigInt { length: None },
6405 trailing_comments: Vec::new(),
6406 double_colon_syntax: false,
6407 format: None,
6408 default: None,
6409 inferred_type: None,
6410 }))),
6411 "DAYOFMONTH" => Ok(Expression::Extract(Box::new(
6412 crate::expressions::ExtractFunc {
6413 this: date_expr,
6414 field: crate::expressions::DateTimeField::Day,
6415 },
6416 ))),
6417 _ => {
6418 let field = match unit_name.as_str() {
6419 "YEAR" | "YY" | "YYYY" => crate::expressions::DateTimeField::Year,
6420 "MONTH" | "MON" | "MM" => crate::expressions::DateTimeField::Month,
6421 "DAY" | "DD" | "D" => crate::expressions::DateTimeField::Day,
6422 "HOUR" | "HH" => crate::expressions::DateTimeField::Hour,
6423 "MINUTE" | "MI" | "MIN" => crate::expressions::DateTimeField::Minute,
6424 "SECOND" | "SEC" | "SS" => crate::expressions::DateTimeField::Second,
6425 "MILLISECOND" | "MS" => crate::expressions::DateTimeField::Millisecond,
6426 "MICROSECOND" | "US" => crate::expressions::DateTimeField::Microsecond,
6427 "QUARTER" | "QTR" => crate::expressions::DateTimeField::Quarter,
6428 "WEEK" | "WK" => crate::expressions::DateTimeField::Week,
6429 "DAYOFWEEK" | "DOW" => crate::expressions::DateTimeField::DayOfWeek,
6430 "DAYOFYEAR" | "DOY" => crate::expressions::DateTimeField::DayOfYear,
6431 "TIMEZONE_HOUR" => crate::expressions::DateTimeField::TimezoneHour,
6432 "TIMEZONE_MINUTE" => crate::expressions::DateTimeField::TimezoneMinute,
6433 _ => crate::expressions::DateTimeField::Custom(unit_name),
6434 };
6435 Ok(Expression::Extract(Box::new(
6436 crate::expressions::ExtractFunc {
6437 this: date_expr,
6438 field,
6439 },
6440 )))
6441 }
6442 }
6443 }
6444
6445 fn transform_dateadd(&self, args: Vec<Expression>) -> Result<Expression> {
6447 let mut args = args;
6448 let unit_expr = args.remove(0);
6449 let amount = args.remove(0);
6450 let date = args.remove(0);
6451 let unit_name = match &unit_expr {
6452 Expression::Column(c) => c.name.name.to_uppercase(),
6453 Expression::Identifier(i) => i.name.to_uppercase(),
6454 Expression::Var(v) => v.this.to_uppercase(),
6455 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
6456 _ => String::new(),
6457 };
6458 if unit_name == "NANOSECOND" || unit_name == "NS" {
6459 let epoch_ns = Expression::Function(Box::new(Function::new(
6460 "EPOCH_NS".to_string(),
6461 vec![Expression::Cast(Box::new(Cast {
6462 this: date,
6463 to: DataType::Custom {
6464 name: "TIMESTAMP_NS".to_string(),
6465 },
6466 trailing_comments: Vec::new(),
6467 double_colon_syntax: false,
6468 format: None,
6469 default: None,
6470 inferred_type: None,
6471 }))],
6472 )));
6473 return Ok(Expression::Function(Box::new(Function::new(
6474 "MAKE_TIMESTAMP_NS".to_string(),
6475 vec![Expression::Add(Box::new(BinaryOp {
6476 left: epoch_ns,
6477 right: amount,
6478 left_comments: Vec::new(),
6479 operator_comments: Vec::new(),
6480 trailing_comments: Vec::new(),
6481 inferred_type: None,
6482 }))],
6483 ))));
6484 }
6485 let (interval_unit, multiplied_amount) = match unit_name.as_str() {
6486 "YEAR" | "YY" | "YYYY" => (IntervalUnit::Year, amount),
6487 "MONTH" | "MON" | "MM" => (IntervalUnit::Month, amount),
6488 "DAY" | "DD" | "D" => (IntervalUnit::Day, amount),
6489 "HOUR" | "HH" => (IntervalUnit::Hour, amount),
6490 "MINUTE" | "MI" | "MIN" => (IntervalUnit::Minute, amount),
6491 "SECOND" | "SEC" | "SS" => (IntervalUnit::Second, amount),
6492 "MILLISECOND" | "MS" => (IntervalUnit::Millisecond, amount),
6493 "MICROSECOND" | "US" => (IntervalUnit::Microsecond, amount),
6494 "WEEK" | "WK" => (
6495 IntervalUnit::Day,
6496 Expression::Mul(Box::new(BinaryOp {
6497 left: amount,
6498 right: Expression::number(7),
6499 left_comments: Vec::new(),
6500 operator_comments: Vec::new(),
6501 trailing_comments: Vec::new(),
6502 inferred_type: None,
6503 })),
6504 ),
6505 "QUARTER" | "QTR" => (
6506 IntervalUnit::Month,
6507 Expression::Mul(Box::new(BinaryOp {
6508 left: amount,
6509 right: Expression::number(3),
6510 left_comments: Vec::new(),
6511 operator_comments: Vec::new(),
6512 trailing_comments: Vec::new(),
6513 inferred_type: None,
6514 })),
6515 ),
6516 _ => (IntervalUnit::Day, amount),
6517 };
6518 Ok(Expression::Add(Box::new(BinaryOp {
6519 left: date,
6520 right: Expression::Interval(Box::new(Interval {
6521 this: Some(multiplied_amount),
6522 unit: Some(IntervalUnitSpec::Simple {
6523 unit: interval_unit,
6524 use_plural: false,
6525 }),
6526 })),
6527 left_comments: Vec::new(),
6528 operator_comments: Vec::new(),
6529 trailing_comments: Vec::new(),
6530 inferred_type: None,
6531 })))
6532 }
6533
6534 fn transform_datediff(&self, args: Vec<Expression>) -> Result<Expression> {
6536 let mut args = args;
6537 let unit_expr = args.remove(0);
6538 let start = args.remove(0);
6539 let end = args.remove(0);
6540 let unit_name = match &unit_expr {
6541 Expression::Column(c) => c.name.name.to_uppercase(),
6542 Expression::Identifier(i) => i.name.to_uppercase(),
6543 Expression::Var(v) => v.this.to_uppercase(),
6544 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
6545 _ => String::new(),
6546 };
6547 if unit_name == "NANOSECOND" || unit_name == "NS" {
6548 let epoch_end = Expression::Function(Box::new(Function::new(
6549 "EPOCH_NS".to_string(),
6550 vec![Expression::Cast(Box::new(Cast {
6551 this: end,
6552 to: DataType::Custom {
6553 name: "TIMESTAMP_NS".to_string(),
6554 },
6555 trailing_comments: Vec::new(),
6556 double_colon_syntax: false,
6557 format: None,
6558 default: None,
6559 inferred_type: None,
6560 }))],
6561 )));
6562 let epoch_start = Expression::Function(Box::new(Function::new(
6563 "EPOCH_NS".to_string(),
6564 vec![Expression::Cast(Box::new(Cast {
6565 this: start,
6566 to: DataType::Custom {
6567 name: "TIMESTAMP_NS".to_string(),
6568 },
6569 trailing_comments: Vec::new(),
6570 double_colon_syntax: false,
6571 format: None,
6572 default: None,
6573 inferred_type: None,
6574 }))],
6575 )));
6576 return Ok(Expression::Sub(Box::new(BinaryOp {
6577 left: epoch_end,
6578 right: epoch_start,
6579 left_comments: Vec::new(),
6580 operator_comments: Vec::new(),
6581 trailing_comments: Vec::new(),
6582 inferred_type: None,
6583 })));
6584 }
6585 if unit_name == "WEEK" || unit_name == "WK" {
6586 let trunc_start = Expression::Function(Box::new(Function::new(
6587 "DATE_TRUNC".to_string(),
6588 vec![
6589 Expression::Literal(Literal::String("WEEK".to_string())),
6590 Expression::Cast(Box::new(Cast {
6591 this: start,
6592 to: DataType::Date,
6593 trailing_comments: Vec::new(),
6594 double_colon_syntax: false,
6595 format: None,
6596 default: None,
6597 inferred_type: None,
6598 })),
6599 ],
6600 )));
6601 let trunc_end = Expression::Function(Box::new(Function::new(
6602 "DATE_TRUNC".to_string(),
6603 vec![
6604 Expression::Literal(Literal::String("WEEK".to_string())),
6605 Expression::Cast(Box::new(Cast {
6606 this: end,
6607 to: DataType::Date,
6608 trailing_comments: Vec::new(),
6609 double_colon_syntax: false,
6610 format: None,
6611 default: None,
6612 inferred_type: None,
6613 })),
6614 ],
6615 )));
6616 return Ok(Expression::Function(Box::new(Function::new(
6617 "DATE_DIFF".to_string(),
6618 vec![
6619 Expression::Literal(Literal::String("WEEK".to_string())),
6620 trunc_start,
6621 trunc_end,
6622 ],
6623 ))));
6624 }
6625 let cast_if_string = |e: Expression| -> Expression {
6626 match &e {
6627 Expression::Literal(Literal::String(_)) => Expression::Cast(Box::new(Cast {
6628 this: e,
6629 to: DataType::Date,
6630 trailing_comments: Vec::new(),
6631 double_colon_syntax: false,
6632 format: None,
6633 default: None,
6634 inferred_type: None,
6635 })),
6636 _ => e,
6637 }
6638 };
6639 let start = cast_if_string(start);
6640 let end = cast_if_string(end);
6641 Ok(Expression::Function(Box::new(Function::new(
6642 "DATE_DIFF".to_string(),
6643 vec![Expression::Literal(Literal::String(unit_name)), start, end],
6644 ))))
6645 }
6646
6647 fn transform_aggregate_function(
6648 &self,
6649 f: Box<crate::expressions::AggregateFunction>,
6650 ) -> Result<Expression> {
6651 let name_upper = f.name.to_uppercase();
6652 match name_upper.as_str() {
6653 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
6655 Function::new("LISTAGG".to_string(), f.args),
6656 ))),
6657
6658 "LISTAGG" => Ok(Expression::AggregateFunction(f)),
6660
6661 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
6663 Function::new("LISTAGG".to_string(), f.args),
6664 ))),
6665
6666 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
6668 "list".to_string(),
6669 f.args,
6670 )))),
6671
6672 "LOGICAL_OR" if !f.args.is_empty() => {
6674 let arg = f.args.into_iter().next().unwrap();
6675 Ok(Expression::Function(Box::new(Function::new(
6676 "BOOL_OR".to_string(),
6677 vec![Expression::Cast(Box::new(crate::expressions::Cast {
6678 this: arg,
6679 to: crate::expressions::DataType::Boolean,
6680 trailing_comments: Vec::new(),
6681 double_colon_syntax: false,
6682 format: None,
6683 default: None,
6684 inferred_type: None,
6685 }))],
6686 ))))
6687 }
6688
6689 "LOGICAL_AND" if !f.args.is_empty() => {
6691 let arg = f.args.into_iter().next().unwrap();
6692 Ok(Expression::Function(Box::new(Function::new(
6693 "BOOL_AND".to_string(),
6694 vec![Expression::Cast(Box::new(crate::expressions::Cast {
6695 this: arg,
6696 to: crate::expressions::DataType::Boolean,
6697 trailing_comments: Vec::new(),
6698 double_colon_syntax: false,
6699 format: None,
6700 default: None,
6701 inferred_type: None,
6702 }))],
6703 ))))
6704 }
6705
6706 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
6708 "SKEWNESS".to_string(),
6709 f.args,
6710 )))),
6711
6712 "REGR_VALX" if f.args.len() == 2 => {
6714 let mut args = f.args;
6715 let y = args.remove(0);
6716 let x = args.remove(0);
6717 Ok(Expression::Case(Box::new(Case {
6718 operand: None,
6719 whens: vec![(
6720 Expression::IsNull(Box::new(crate::expressions::IsNull {
6721 this: y,
6722 not: false,
6723 postfix_form: false,
6724 })),
6725 Expression::Cast(Box::new(Cast {
6726 this: Expression::Null(crate::expressions::Null),
6727 to: DataType::Double {
6728 precision: None,
6729 scale: None,
6730 },
6731 trailing_comments: Vec::new(),
6732 double_colon_syntax: false,
6733 format: None,
6734 default: None,
6735 inferred_type: None,
6736 })),
6737 )],
6738 else_: Some(x),
6739 comments: Vec::new(),
6740 inferred_type: None,
6741 })))
6742 }
6743
6744 "REGR_VALY" if f.args.len() == 2 => {
6746 let mut args = f.args;
6747 let y = args.remove(0);
6748 let x = args.remove(0);
6749 Ok(Expression::Case(Box::new(Case {
6750 operand: None,
6751 whens: vec![(
6752 Expression::IsNull(Box::new(crate::expressions::IsNull {
6753 this: x,
6754 not: false,
6755 postfix_form: false,
6756 })),
6757 Expression::Cast(Box::new(Cast {
6758 this: Expression::Null(crate::expressions::Null),
6759 to: DataType::Double {
6760 precision: None,
6761 scale: None,
6762 },
6763 trailing_comments: Vec::new(),
6764 double_colon_syntax: false,
6765 format: None,
6766 default: None,
6767 inferred_type: None,
6768 })),
6769 )],
6770 else_: Some(y),
6771 comments: Vec::new(),
6772 inferred_type: None,
6773 })))
6774 }
6775
6776 "BOOLAND_AGG" if !f.args.is_empty() => {
6778 let arg = f.args.into_iter().next().unwrap();
6779 Ok(Expression::Function(Box::new(Function::new(
6780 "BOOL_AND".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 }
6792
6793 "BOOLOR_AGG" if !f.args.is_empty() => {
6795 let arg = f.args.into_iter().next().unwrap();
6796 Ok(Expression::Function(Box::new(Function::new(
6797 "BOOL_OR".to_string(),
6798 vec![Expression::Cast(Box::new(Cast {
6799 this: arg,
6800 to: DataType::Boolean,
6801 trailing_comments: Vec::new(),
6802 double_colon_syntax: false,
6803 format: None,
6804 default: None,
6805 inferred_type: None,
6806 }))],
6807 ))))
6808 }
6809
6810 "BOOLXOR_AGG" if !f.args.is_empty() => {
6812 let arg = f.args.into_iter().next().unwrap();
6813 Ok(Expression::Eq(Box::new(BinaryOp {
6814 left: Expression::Function(Box::new(Function::new(
6815 "COUNT_IF".to_string(),
6816 vec![Expression::Cast(Box::new(Cast {
6817 this: arg,
6818 to: DataType::Boolean,
6819 trailing_comments: Vec::new(),
6820 double_colon_syntax: false,
6821 format: None,
6822 default: None,
6823 inferred_type: None,
6824 }))],
6825 ))),
6826 right: Expression::number(1),
6827 left_comments: Vec::new(),
6828 operator_comments: Vec::new(),
6829 trailing_comments: Vec::new(),
6830 inferred_type: None,
6831 })))
6832 }
6833
6834 "MAX_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
6836 crate::expressions::AggregateFunction {
6837 name: "ARG_MAX".to_string(),
6838 ..(*f)
6839 },
6840 ))),
6841
6842 "MIN_BY" if f.args.len() == 2 => Ok(Expression::AggregateFunction(Box::new(
6844 crate::expressions::AggregateFunction {
6845 name: "ARG_MIN".to_string(),
6846 ..(*f)
6847 },
6848 ))),
6849
6850 "CORR" if f.args.len() == 2 => Ok(Expression::AggregateFunction(f)),
6852
6853 "BITMAP_CONSTRUCT_AGG" if f.args.len() == 1 => {
6855 let v_sql = Self::expr_to_sql(&f.args[0]);
6856
6857 let template = format!(
6858 "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))",
6859 v = v_sql
6860 );
6861
6862 Self::parse_as_subquery(&template)
6863 }
6864
6865 _ => Ok(Expression::AggregateFunction(f)),
6867 }
6868 }
6869
6870 fn convert_format_to_duckdb(expr: &Expression) -> Expression {
6874 if let Expression::Literal(Literal::String(s)) = expr {
6875 let duckdb_fmt = Self::presto_to_duckdb_format(s);
6876 Expression::Literal(Literal::String(duckdb_fmt))
6877 } else {
6878 expr.clone()
6879 }
6880 }
6881
6882 fn presto_to_duckdb_format(fmt: &str) -> String {
6884 let mut result = String::new();
6885 let chars: Vec<char> = fmt.chars().collect();
6886 let mut i = 0;
6887 while i < chars.len() {
6888 if chars[i] == '%' && i + 1 < chars.len() {
6889 match chars[i + 1] {
6890 'i' => {
6891 result.push_str("%M");
6893 i += 2;
6894 }
6895 'T' => {
6896 result.push_str("%H:%M:%S");
6898 i += 2;
6899 }
6900 'F' => {
6901 result.push_str("%Y-%m-%d");
6903 i += 2;
6904 }
6905 _ => {
6906 result.push('%');
6907 result.push(chars[i + 1]);
6908 i += 2;
6909 }
6910 }
6911 } else {
6912 result.push(chars[i]);
6913 i += 1;
6914 }
6915 }
6916 result
6917 }
6918}
6919
6920#[cfg(test)]
6921mod tests {
6922 use super::*;
6923 use crate::dialects::Dialect;
6924
6925 fn transpile_to_duckdb(sql: &str) -> String {
6926 let dialect = Dialect::get(DialectType::Generic);
6927 let result = dialect
6928 .transpile_to(sql, DialectType::DuckDB)
6929 .expect("Transpile failed");
6930 result[0].clone()
6931 }
6932
6933 #[test]
6934 fn test_ifnull_to_coalesce() {
6935 let result = transpile_to_duckdb("SELECT IFNULL(a, b)");
6936 assert!(
6937 result.contains("COALESCE"),
6938 "Expected COALESCE, got: {}",
6939 result
6940 );
6941 }
6942
6943 #[test]
6944 fn test_nvl_to_coalesce() {
6945 let result = transpile_to_duckdb("SELECT NVL(a, b)");
6946 assert!(
6947 result.contains("COALESCE"),
6948 "Expected COALESCE, got: {}",
6949 result
6950 );
6951 }
6952
6953 #[test]
6954 fn test_basic_select() {
6955 let result = transpile_to_duckdb("SELECT a, b FROM users WHERE id = 1");
6956 assert!(result.contains("SELECT"));
6957 assert!(result.contains("FROM users"));
6958 }
6959
6960 #[test]
6961 fn test_group_concat_to_listagg() {
6962 let result = transpile_to_duckdb("SELECT GROUP_CONCAT(name)");
6963 assert!(
6964 result.contains("LISTAGG"),
6965 "Expected LISTAGG, got: {}",
6966 result
6967 );
6968 }
6969
6970 #[test]
6971 fn test_listagg_preserved() {
6972 let result = transpile_to_duckdb("SELECT LISTAGG(name)");
6973 assert!(
6974 result.contains("LISTAGG"),
6975 "Expected LISTAGG, got: {}",
6976 result
6977 );
6978 }
6979
6980 #[test]
6981 fn test_date_format_to_strftime() {
6982 let result = transpile_to_duckdb("SELECT DATE_FORMAT(d, '%Y-%m-%d')");
6983 assert!(
6985 result.to_uppercase().contains("STRFTIME"),
6986 "Expected STRFTIME, got: {}",
6987 result
6988 );
6989 }
6990
6991 #[test]
6992 fn test_regexp_like_to_regexp_matches() {
6993 let result = transpile_to_duckdb("SELECT REGEXP_LIKE(name, 'pattern')");
6994 assert!(
6996 result.to_uppercase().contains("REGEXP_MATCHES"),
6997 "Expected REGEXP_MATCHES, got: {}",
6998 result
6999 );
7000 }
7001
7002 #[test]
7003 fn test_double_quote_identifiers() {
7004 let dialect = Dialect::get(DialectType::DuckDB);
7006 let config = dialect.generator_config();
7007 assert_eq!(config.identifier_quote, '"');
7008 }
7009
7010 fn duckdb_identity(sql: &str) -> String {
7012 let dialect = Dialect::get(DialectType::DuckDB);
7013 let ast = dialect.parse(sql).expect("Parse failed");
7014 let transformed = dialect.transform(ast[0].clone()).expect("Transform failed");
7015 dialect.generate(&transformed).expect("Generate failed")
7016 }
7017
7018 #[test]
7019 fn test_interval_quoting() {
7020 let result = duckdb_identity("SELECT DATE_ADD(CAST('2020-01-01' AS DATE), INTERVAL 1 DAY)");
7022 assert_eq!(
7023 result, "SELECT CAST('2020-01-01' AS DATE) + INTERVAL '1' DAY",
7024 "Interval value should be quoted as string"
7025 );
7026 }
7027
7028 #[test]
7029 fn test_struct_pack_to_curly_brace() {
7030 let result = duckdb_identity("CAST([STRUCT_PACK(a := 1)] AS STRUCT(a BIGINT)[])");
7032 assert_eq!(
7033 result, "CAST([{'a': 1}] AS STRUCT(a BIGINT)[])",
7034 "STRUCT_PACK should be transformed to curly brace notation"
7035 );
7036 }
7037
7038 #[test]
7039 fn test_struct_pack_nested() {
7040 let result = duckdb_identity("CAST([[STRUCT_PACK(a := 1)]] AS STRUCT(a BIGINT)[][])");
7042 assert_eq!(
7043 result, "CAST([[{'a': 1}]] AS STRUCT(a BIGINT)[][])",
7044 "Nested STRUCT_PACK should be transformed"
7045 );
7046 }
7047
7048 #[test]
7049 fn test_struct_pack_cast() {
7050 let result = duckdb_identity("STRUCT_PACK(a := 'b')::json");
7052 assert_eq!(
7053 result, "CAST({'a': 'b'} AS JSON)",
7054 "STRUCT_PACK with cast should be transformed"
7055 );
7056 }
7057
7058 #[test]
7059 fn test_list_value_to_bracket() {
7060 let result = duckdb_identity("SELECT LIST_VALUE(1)[i]");
7062 assert_eq!(
7063 result, "SELECT [1][i]",
7064 "LIST_VALUE should be transformed to bracket notation"
7065 );
7066 }
7067
7068 #[test]
7069 fn test_list_value_in_struct_literal() {
7070 let result = duckdb_identity("{'x': LIST_VALUE(1)[i]}");
7072 assert_eq!(
7073 result, "{'x': [1][i]}",
7074 "LIST_VALUE inside struct literal should be transformed"
7075 );
7076 }
7077
7078 #[test]
7079 fn test_struct_pack_simple() {
7080 let result = duckdb_identity("SELECT STRUCT_PACK(a := 1)");
7082 eprintln!("STRUCT_PACK result: {}", result);
7083 assert!(
7084 result.contains("{"),
7085 "Expected curly brace, got: {}",
7086 result
7087 );
7088 }
7089
7090 #[test]
7091 fn test_not_in_position() {
7092 let result = duckdb_identity(
7095 "SELECT col FROM t WHERE JSON_EXTRACT_STRING(col, '$.id') NOT IN ('b')",
7096 );
7097 assert_eq!(
7098 result, "SELECT col FROM t WHERE NOT (col ->> '$.id') IN ('b')",
7099 "NOT IN should have NOT moved outside and JSON expression wrapped"
7100 );
7101 }
7102
7103 #[test]
7104 fn test_unnest_comma_join_to_join_on_true() {
7105 let result = duckdb_identity(
7107 "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",
7108 );
7109 assert_eq!(
7110 result,
7111 "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",
7112 "Comma-join with UNNEST should become JOIN ON TRUE"
7113 );
7114 }
7115}