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