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