1use super::{DialectImpl, DialectType};
13use crate::error::Result;
14use crate::expressions::{
15 AggFunc, BinaryOp, Cast, CeilFunc, DataType, Expression, Function, IntervalUnit, ListAggFunc,
16 Literal, UnaryFunc, VarArgFunc,
17};
18use crate::generator::GeneratorConfig;
19use crate::tokens::TokenizerConfig;
20
21fn interval_unit_to_str(unit: &IntervalUnit) -> String {
23 match unit {
24 IntervalUnit::Year => "YEAR".to_string(),
25 IntervalUnit::Quarter => "QUARTER".to_string(),
26 IntervalUnit::Month => "MONTH".to_string(),
27 IntervalUnit::Week => "WEEK".to_string(),
28 IntervalUnit::Day => "DAY".to_string(),
29 IntervalUnit::Hour => "HOUR".to_string(),
30 IntervalUnit::Minute => "MINUTE".to_string(),
31 IntervalUnit::Second => "SECOND".to_string(),
32 IntervalUnit::Millisecond => "MILLISECOND".to_string(),
33 IntervalUnit::Microsecond => "MICROSECOND".to_string(),
34 IntervalUnit::Nanosecond => "NANOSECOND".to_string(),
35 }
36}
37
38pub struct SnowflakeDialect;
40
41impl DialectImpl for SnowflakeDialect {
42 fn dialect_type(&self) -> DialectType {
43 DialectType::Snowflake
44 }
45
46 fn tokenizer_config(&self) -> TokenizerConfig {
47 let mut config = TokenizerConfig::default();
48 config.identifiers.insert('"', '"');
50 config.quotes.insert("$$".to_string(), "$$".to_string());
52 config.nested_comments = false;
54 config.comments.insert("//".to_string(), None);
56 config
57 }
58
59 fn generator_config(&self) -> GeneratorConfig {
60 use crate::generator::IdentifierQuoteStyle;
61 GeneratorConfig {
62 identifier_quote: '"',
63 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
64 dialect: Some(DialectType::Snowflake),
65 parameter_token: "$",
67 matched_by_source: false,
68 single_string_interval: true,
69 join_hints: false,
70 table_hints: false,
71 query_hints: false,
72 aggregate_filter_supported: false,
73 supports_table_copy: false,
74 collate_is_func: true,
75 limit_only_literals: true,
76 json_key_value_pair_sep: ",",
77 insert_overwrite: " OVERWRITE INTO",
78 struct_delimiter: ("(", ")"),
79 copy_params_are_wrapped: false,
80 copy_params_eq_required: true,
81 star_except: "EXCLUDE",
82 supports_exploding_projections: false,
83 array_concat_is_var_len: false,
84 supports_convert_timezone: true,
85 except_intersect_support_all_clause: false,
86 supports_median: true,
87 array_size_name: "ARRAY_SIZE",
88 supports_decode_case: true,
89 is_bool_allowed: false,
90 try_supported: true,
92 nvl2_supported: true,
94 unnest_with_ordinality: false,
96 quantified_no_paren_space: false,
98 ..Default::default()
99 }
100 }
101
102 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
103 match expr {
104 Expression::DataType(dt) => self.transform_data_type(dt),
106
107 Expression::In(in_expr) if in_expr.not && in_expr.query.is_some() => {
111 let inner = in_expr.query.unwrap();
113 let subquery = Expression::Subquery(Box::new(crate::expressions::Subquery {
115 this: inner,
116 alias: None,
117 column_aliases: Vec::new(),
118 order_by: None,
119 limit: None,
120 offset: None,
121 distribute_by: None,
122 sort_by: None,
123 cluster_by: None,
124 lateral: false,
125 modifiers_inside: false,
126 trailing_comments: Vec::new(),
127 inferred_type: None,
128 }));
129 Ok(Expression::All(Box::new(
130 crate::expressions::QuantifiedExpr {
131 this: in_expr.this,
132 subquery,
133 op: Some(crate::expressions::QuantifiedOp::Neq),
134 },
135 )))
136 }
137
138 Expression::In(in_expr) if in_expr.not => {
140 let in_without_not = crate::expressions::In {
142 this: in_expr.this,
143 expressions: in_expr.expressions,
144 query: in_expr.query,
145 not: false,
146 global: in_expr.global,
147 unnest: in_expr.unnest,
148 is_field: in_expr.is_field,
149 };
150 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
151 this: Expression::In(Box::new(in_without_not)),
152 inferred_type: None,
153 })))
154 }
155
156 Expression::Interval(interval) => self.transform_interval(*interval),
159
160 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
163 original_name: None,
164 expressions: vec![f.this, f.expression],
165 inferred_type: None,
166 }))),
167
168 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
170 original_name: None,
171 expressions: vec![f.this, f.expression],
172 inferred_type: None,
173 }))),
174
175 Expression::Coalesce(mut f) => {
177 f.original_name = None;
178 Ok(Expression::Coalesce(f))
179 }
180
181 Expression::GroupConcat(f) => Ok(Expression::ListAgg(Box::new(ListAggFunc {
183 this: f.this,
184 separator: f.separator,
185 on_overflow: None,
186 order_by: f.order_by,
187 distinct: f.distinct,
188 filter: f.filter,
189 }))),
190
191 Expression::Cast(c) => {
195 use crate::expressions::DataType;
196 let transformed_this = self.transform_expr(c.this)?;
198 match &c.to {
199 DataType::Geography { .. } => Ok(Expression::Function(Box::new(
200 Function::new("TO_GEOGRAPHY".to_string(), vec![transformed_this]),
201 ))),
202 DataType::Geometry { .. } => Ok(Expression::Function(Box::new(Function::new(
203 "TO_GEOMETRY".to_string(),
204 vec![transformed_this],
205 )))),
206 _ => {
207 let transformed_dt = match self.transform_data_type(c.to.clone())? {
209 Expression::DataType(dt) => dt,
210 _ => c.to.clone(),
211 };
212 Ok(Expression::Cast(Box::new(Cast {
213 this: transformed_this,
214 to: transformed_dt,
215 double_colon_syntax: false, trailing_comments: c.trailing_comments,
217 format: c.format,
218 default: c.default,
219 inferred_type: None,
220 })))
221 }
222 }
223 }
224
225 Expression::TryCast(c) => {
228 let transformed_this = self.transform_expr(c.this)?;
229 Ok(Expression::TryCast(Box::new(Cast {
230 this: transformed_this,
231 to: c.to,
232 double_colon_syntax: false, trailing_comments: c.trailing_comments,
234 format: c.format,
235 default: c.default,
236 inferred_type: None,
237 })))
238 }
239
240 Expression::SafeCast(c) => {
243 let to = match c.to {
244 DataType::Timestamp { .. } => DataType::Custom {
245 name: "TIMESTAMPTZ".to_string(),
246 },
247 DataType::Custom { name } if name.eq_ignore_ascii_case("TIMESTAMP") => {
248 DataType::Custom {
249 name: "TIMESTAMPTZ".to_string(),
250 }
251 }
252 other => other,
253 };
254 let transformed_this = self.transform_expr(c.this)?;
255 Ok(Expression::Cast(Box::new(Cast {
256 this: transformed_this,
257 to,
258 double_colon_syntax: c.double_colon_syntax,
259 trailing_comments: c.trailing_comments,
260 format: c.format,
261 default: c.default,
262 inferred_type: None,
263 })))
264 }
265
266 Expression::Literal(Literal::Timestamp(s)) => Ok(Expression::Cast(Box::new(Cast {
269 this: Expression::Literal(Literal::String(s)),
270 to: DataType::Timestamp {
271 precision: None,
272 timezone: false,
273 },
274 double_colon_syntax: false,
275 trailing_comments: Vec::new(),
276 format: None,
277 default: None,
278 inferred_type: None,
279 }))),
280
281 Expression::Literal(Literal::Date(s)) => Ok(Expression::Cast(Box::new(Cast {
283 this: Expression::Literal(Literal::String(s)),
284 to: DataType::Date,
285 double_colon_syntax: false,
286 trailing_comments: Vec::new(),
287 format: None,
288 default: None,
289 inferred_type: None,
290 }))),
291
292 Expression::Literal(Literal::Time(s)) => Ok(Expression::Cast(Box::new(Cast {
294 this: Expression::Literal(Literal::String(s)),
295 to: DataType::Time {
296 precision: None,
297 timezone: false,
298 },
299 double_colon_syntax: false,
300 trailing_comments: Vec::new(),
301 format: None,
302 default: None,
303 inferred_type: None,
304 }))),
305
306 Expression::Literal(Literal::Datetime(s)) => Ok(Expression::Cast(Box::new(Cast {
308 this: Expression::Literal(Literal::String(s)),
309 to: DataType::Custom {
310 name: "DATETIME".to_string(),
311 },
312 double_colon_syntax: false,
313 trailing_comments: Vec::new(),
314 format: None,
315 default: None,
316 inferred_type: None,
317 }))),
318
319 Expression::ILike(op) => Ok(Expression::ILike(op)),
322
323 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
326 "FLATTEN".to_string(),
327 vec![f.this],
328 )))),
329
330 Expression::ExplodeOuter(f) => Ok(Expression::Function(Box::new(Function::new(
332 "FLATTEN".to_string(),
333 vec![f.this],
334 )))),
335
336 Expression::Unnest(f) => {
338 let input_arg =
340 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
341 name: crate::expressions::Identifier::new("INPUT"),
342 value: f.this,
343 separator: crate::expressions::NamedArgSeparator::DArrow,
344 }));
345
346 let flatten = Expression::Function(Box::new(Function::new(
348 "FLATTEN".to_string(),
349 vec![input_arg],
350 )));
351
352 let table_func =
354 Expression::TableFromRows(Box::new(crate::expressions::TableFromRows {
355 this: Box::new(flatten),
356 alias: None,
357 joins: vec![],
358 pivots: None,
359 sample: None,
360 }));
361
362 Ok(Expression::Alias(Box::new(crate::expressions::Alias {
364 this: table_func,
365 alias: crate::expressions::Identifier::new("_t0"),
366 column_aliases: vec![
367 crate::expressions::Identifier::new("seq"),
368 crate::expressions::Identifier::new("key"),
369 crate::expressions::Identifier::new("path"),
370 crate::expressions::Identifier::new("index"),
371 crate::expressions::Identifier::new("value"),
372 crate::expressions::Identifier::new("this"),
373 ],
374 pre_alias_comments: vec![],
375 trailing_comments: vec![],
376 inferred_type: None,
377 })))
378 }
379
380 Expression::ArrayFunc(arr) => {
384 if arr.bracket_notation {
385 Ok(Expression::ArrayFunc(arr))
387 } else {
388 Ok(Expression::Function(Box::new(Function::new(
390 "ARRAY_CONSTRUCT".to_string(),
391 arr.expressions,
392 ))))
393 }
394 }
395
396 Expression::ArrayConcat(f) => Ok(Expression::Function(Box::new(Function::new(
398 "ARRAY_CAT".to_string(),
399 f.expressions,
400 )))),
401
402 Expression::ArrayConcatAgg(f) => Ok(Expression::Function(Box::new(Function::new(
404 "ARRAY_FLATTEN".to_string(),
405 vec![f.this],
406 )))),
407
408 Expression::ArrayContains(f) => Ok(Expression::Function(Box::new(Function::new(
410 "ARRAY_CONTAINS".to_string(),
411 vec![f.this, f.expression],
412 )))),
413
414 Expression::ArrayIntersect(f) => Ok(Expression::Function(Box::new(Function::new(
416 "ARRAY_INTERSECTION".to_string(),
417 f.expressions,
418 )))),
419
420 Expression::ArraySort(f) => Ok(Expression::Function(Box::new(Function::new(
422 "ARRAY_SORT".to_string(),
423 vec![f.this],
424 )))),
425
426 Expression::StringToArray(f) => {
428 let mut args = vec![*f.this];
429 if let Some(expr) = f.expression {
430 args.push(*expr);
431 }
432 Ok(Expression::Function(Box::new(Function::new(
433 "STRTOK_TO_ARRAY".to_string(),
434 args,
435 ))))
436 }
437
438 Expression::BitwiseOr(f) => Ok(Expression::Function(Box::new(Function::new(
441 "BITOR".to_string(),
442 vec![f.left, f.right],
443 )))),
444
445 Expression::BitwiseXor(f) => Ok(Expression::Function(Box::new(Function::new(
447 "BITXOR".to_string(),
448 vec![f.left, f.right],
449 )))),
450
451 Expression::BitwiseAnd(f) => Ok(Expression::Function(Box::new(Function::new(
453 "BITAND".to_string(),
454 vec![f.left, f.right],
455 )))),
456
457 Expression::BitwiseNot(f) => Ok(Expression::Function(Box::new(Function::new(
459 "BITNOT".to_string(),
460 vec![f.this],
461 )))),
462
463 Expression::BitwiseLeftShift(f) => Ok(Expression::Function(Box::new(Function::new(
465 "BITSHIFTLEFT".to_string(),
466 vec![f.left, f.right],
467 )))),
468
469 Expression::BitwiseRightShift(f) => Ok(Expression::Function(Box::new(Function::new(
471 "BITSHIFTRIGHT".to_string(),
472 vec![f.left, f.right],
473 )))),
474
475 Expression::BitwiseAndAgg(f) => Ok(Expression::Function(Box::new(Function::new(
477 "BITAND_AGG".to_string(),
478 vec![f.this],
479 )))),
480
481 Expression::BitwiseOrAgg(f) => Ok(Expression::Function(Box::new(Function::new(
483 "BITOR_AGG".to_string(),
484 vec![f.this],
485 )))),
486
487 Expression::BitwiseXorAgg(f) => Ok(Expression::Function(Box::new(Function::new(
489 "BITXOR_AGG".to_string(),
490 vec![f.this],
491 )))),
492
493 Expression::LogicalAnd(f) => Ok(Expression::Function(Box::new(Function::new(
496 "BOOLAND_AGG".to_string(),
497 vec![f.this],
498 )))),
499
500 Expression::LogicalOr(f) => Ok(Expression::Function(Box::new(Function::new(
502 "BOOLOR_AGG".to_string(),
503 vec![f.this],
504 )))),
505
506 Expression::Booland(f) => Ok(Expression::Function(Box::new(Function::new(
508 "BOOLAND".to_string(),
509 vec![*f.this, *f.expression],
510 )))),
511
512 Expression::Boolor(f) => Ok(Expression::Function(Box::new(Function::new(
514 "BOOLOR".to_string(),
515 vec![*f.this, *f.expression],
516 )))),
517
518 Expression::Xor(f) => {
520 let mut args = Vec::new();
521 if let Some(this) = f.this {
522 args.push(*this);
523 }
524 if let Some(expr) = f.expression {
525 args.push(*expr);
526 }
527 Ok(Expression::Function(Box::new(Function::new(
528 "BOOLXOR".to_string(),
529 args,
530 ))))
531 }
532
533 Expression::DayOfMonth(f) => Ok(Expression::Function(Box::new(Function::new(
536 "DAYOFMONTH".to_string(),
537 vec![f.this],
538 )))),
539
540 Expression::DayOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
542 "DAYOFWEEK".to_string(),
543 vec![f.this],
544 )))),
545
546 Expression::DayOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
548 "DAYOFWEEKISO".to_string(),
549 vec![f.this],
550 )))),
551
552 Expression::DayOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
554 "DAYOFYEAR".to_string(),
555 vec![f.this],
556 )))),
557
558 Expression::WeekOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
560 "WEEK".to_string(),
561 vec![f.this],
562 )))),
563
564 Expression::YearOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
566 "YEAROFWEEK".to_string(),
567 vec![f.this],
568 )))),
569
570 Expression::YearOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
572 "YEAROFWEEKISO".to_string(),
573 vec![f.this],
574 )))),
575
576 Expression::ByteLength(f) => Ok(Expression::Function(Box::new(Function::new(
578 "OCTET_LENGTH".to_string(),
579 vec![f.this],
580 )))),
581
582 Expression::TimestampDiff(f) => {
584 let mut args = vec![];
585 if let Some(ref unit_str) = f.unit {
587 args.push(Expression::Identifier(crate::expressions::Identifier::new(
588 unit_str.clone(),
589 )));
590 args.push(*f.this);
591 args.push(*f.expression);
592 } else {
593 args.push(*f.this);
594 args.push(*f.expression);
595 }
596 Ok(Expression::Function(Box::new(Function::new(
597 "TIMESTAMPDIFF".to_string(),
598 args,
599 ))))
600 }
601
602 Expression::TimestampAdd(f) => {
604 let mut args = vec![];
605 if let Some(ref unit_str) = f.unit {
606 args.push(Expression::Identifier(crate::expressions::Identifier::new(
607 unit_str.clone(),
608 )));
609 args.push(*f.this);
610 args.push(*f.expression);
611 } else {
612 args.push(*f.this);
613 args.push(*f.expression);
614 }
615 Ok(Expression::Function(Box::new(Function::new(
616 "TIMESTAMPADD".to_string(),
617 args,
618 ))))
619 }
620
621 Expression::ToArray(f) => Ok(Expression::Function(Box::new(Function::new(
623 "TO_ARRAY".to_string(),
624 vec![f.this],
625 )))),
626
627 Expression::DateAdd(f) => {
629 let unit_str = interval_unit_to_str(&f.unit);
630 let unit = Expression::Identifier(crate::expressions::Identifier {
631 name: unit_str,
632 quoted: false,
633 trailing_comments: Vec::new(),
634 span: None,
635 });
636 Ok(Expression::Function(Box::new(Function::new(
637 "DATEADD".to_string(),
638 vec![unit, f.interval, f.this],
639 ))))
640 }
641
642 Expression::DateSub(f) => {
644 let unit_str = interval_unit_to_str(&f.unit);
645 let unit = Expression::Identifier(crate::expressions::Identifier {
646 name: unit_str,
647 quoted: false,
648 trailing_comments: Vec::new(),
649 span: None,
650 });
651 let neg_expr = Expression::Mul(Box::new(crate::expressions::BinaryOp::new(
653 f.interval,
654 Expression::Neg(Box::new(crate::expressions::UnaryOp {
655 this: Expression::number(1),
656 inferred_type: None,
657 })),
658 )));
659 Ok(Expression::Function(Box::new(Function::new(
660 "DATEADD".to_string(),
661 vec![unit, neg_expr, f.this],
662 ))))
663 }
664
665 Expression::DateDiff(f) => {
667 let unit_str =
668 interval_unit_to_str(&f.unit.unwrap_or(crate::expressions::IntervalUnit::Day));
669 let unit = Expression::Identifier(crate::expressions::Identifier {
670 name: unit_str,
671 quoted: false,
672 trailing_comments: Vec::new(),
673 span: None,
674 });
675 Ok(Expression::Function(Box::new(Function::new(
676 "DATEDIFF".to_string(),
677 vec![unit, f.expression, f.this],
678 ))))
679 }
680
681 Expression::StringAgg(f) => {
684 let mut args = vec![f.this.clone()];
685 if let Some(separator) = &f.separator {
686 args.push(separator.clone());
687 }
688 Ok(Expression::Function(Box::new(Function::new(
689 "LISTAGG".to_string(),
690 args,
691 ))))
692 }
693
694 Expression::StartsWith(f) => Ok(Expression::Function(Box::new(Function::new(
696 "STARTSWITH".to_string(),
697 vec![f.this, f.expression],
698 )))),
699
700 Expression::EndsWith(f) => Ok(Expression::EndsWith(f)),
702
703 Expression::Stuff(f) => {
705 let mut args = vec![*f.this];
706 if let Some(start) = f.start {
707 args.push(*start);
708 }
709 if let Some(length) = f.length {
710 args.push(Expression::number(length));
711 }
712 args.push(*f.expression);
713 Ok(Expression::Function(Box::new(Function::new(
714 "INSERT".to_string(),
715 args,
716 ))))
717 }
718
719 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
722 "SHA1".to_string(),
723 vec![f.this],
724 )))),
725
726 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
728 "SHA1_BINARY".to_string(),
729 vec![f.this],
730 )))),
731
732 Expression::SHA2Digest(f) => Ok(Expression::Function(Box::new(Function::new(
734 "SHA2_BINARY".to_string(),
735 vec![*f.this],
736 )))),
737
738 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
740 "MD5_BINARY".to_string(),
741 vec![*f.this],
742 )))),
743
744 Expression::MD5NumberLower64(f) => Ok(Expression::Function(Box::new(Function::new(
746 "MD5_NUMBER_LOWER64".to_string(),
747 vec![f.this],
748 )))),
749
750 Expression::MD5NumberUpper64(f) => Ok(Expression::Function(Box::new(Function::new(
752 "MD5_NUMBER_UPPER64".to_string(),
753 vec![f.this],
754 )))),
755
756 Expression::CosineDistance(f) => Ok(Expression::Function(Box::new(Function::new(
759 "VECTOR_COSINE_SIMILARITY".to_string(),
760 vec![*f.this, *f.expression],
761 )))),
762
763 Expression::DotProduct(f) => Ok(Expression::Function(Box::new(Function::new(
765 "VECTOR_INNER_PRODUCT".to_string(),
766 vec![*f.this, *f.expression],
767 )))),
768
769 Expression::EuclideanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
771 "VECTOR_L2_DISTANCE".to_string(),
772 vec![*f.this, *f.expression],
773 )))),
774
775 Expression::ManhattanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
777 "VECTOR_L1_DISTANCE".to_string(),
778 vec![*f.this, *f.expression],
779 )))),
780
781 Expression::JSONFormat(f) => {
784 let mut args = Vec::new();
785 if let Some(this) = f.this {
786 args.push(*this);
787 }
788 Ok(Expression::Function(Box::new(Function::new(
789 "TO_JSON".to_string(),
790 args,
791 ))))
792 }
793
794 Expression::JSONKeys(f) => Ok(Expression::Function(Box::new(Function::new(
796 "OBJECT_KEYS".to_string(),
797 vec![*f.this],
798 )))),
799
800 Expression::GetExtract(f) => Ok(Expression::Function(Box::new(Function::new(
802 "GET".to_string(),
803 vec![*f.this, *f.expression],
804 )))),
805
806 Expression::StarMap(f) => Ok(Expression::Function(Box::new(Function::new(
808 "OBJECT_CONSTRUCT".to_string(),
809 vec![f.this, f.expression],
810 )))),
811
812 Expression::LowerHex(f) => Ok(Expression::Function(Box::new(Function::new(
814 "TO_CHAR".to_string(),
815 vec![f.this],
816 )))),
817
818 Expression::Skewness(f) => Ok(Expression::Function(Box::new(Function::new(
820 "SKEW".to_string(),
821 vec![f.this],
822 )))),
823
824 Expression::StPoint(f) => Ok(Expression::Function(Box::new(Function::new(
826 "ST_MAKEPOINT".to_string(),
827 vec![*f.this, *f.expression],
828 )))),
829
830 Expression::FromTimeZone(f) => Ok(Expression::Function(Box::new(Function::new(
832 "CONVERT_TIMEZONE".to_string(),
833 vec![*f.this],
834 )))),
835
836 Expression::Unhex(f) => Ok(Expression::Function(Box::new(Function::new(
839 "HEX_DECODE_BINARY".to_string(),
840 vec![*f.this],
841 )))),
842
843 Expression::UnixToTime(f) => {
845 let mut args = vec![*f.this];
846 if let Some(scale) = f.scale {
847 args.push(Expression::number(scale));
848 }
849 Ok(Expression::Function(Box::new(Function::new(
850 "TO_TIMESTAMP".to_string(),
851 args,
852 ))))
853 }
854
855 Expression::IfFunc(f) => Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
858 condition: f.condition,
859 true_value: f.true_value,
860 false_value: Some(
861 f.false_value
862 .unwrap_or(Expression::Null(crate::expressions::Null)),
863 ),
864 original_name: Some("IFF".to_string()),
865 }))),
866
867 Expression::ApproxDistinct(f) => Ok(Expression::Function(Box::new(Function::new(
870 "APPROX_COUNT_DISTINCT".to_string(),
871 vec![f.this],
872 )))),
873
874 Expression::ArgMax(f) => Ok(Expression::Function(Box::new(Function::new(
876 "MAX_BY".to_string(),
877 vec![*f.this, *f.expression],
878 )))),
879
880 Expression::ArgMin(f) => Ok(Expression::Function(Box::new(Function::new(
882 "MIN_BY".to_string(),
883 vec![*f.this, *f.expression],
884 )))),
885
886 Expression::Random(_) => Ok(Expression::Random(crate::expressions::Random)),
889
890 Expression::Rand(r) => Ok(Expression::Rand(r)),
892
893 Expression::Uuid(u) => Ok(Expression::Uuid(u)),
896
897 Expression::Map(f) => Ok(Expression::Function(Box::new(Function::new(
900 "OBJECT_CONSTRUCT".to_string(),
901 f.keys
902 .into_iter()
903 .zip(f.values.into_iter())
904 .flat_map(|(k, v)| vec![k, v])
905 .collect(),
906 )))),
907
908 Expression::MapFunc(f) => Ok(Expression::Function(Box::new(Function::new(
910 "OBJECT_CONSTRUCT".to_string(),
911 f.keys
912 .into_iter()
913 .zip(f.values.into_iter())
914 .flat_map(|(k, v)| vec![k, v])
915 .collect(),
916 )))),
917
918 Expression::VarMap(f) => Ok(Expression::Function(Box::new(Function::new(
920 "OBJECT_CONSTRUCT".to_string(),
921 f.keys
922 .into_iter()
923 .zip(f.values.into_iter())
924 .flat_map(|(k, v)| vec![k, v])
925 .collect(),
926 )))),
927
928 Expression::JsonObject(f) => Ok(Expression::Function(Box::new(Function::new(
931 "OBJECT_CONSTRUCT_KEEP_NULL".to_string(),
932 f.pairs.into_iter().flat_map(|(k, v)| vec![k, v]).collect(),
933 )))),
934
935 Expression::JsonExtractScalar(f) => Ok(Expression::Function(Box::new(Function::new(
937 "JSON_EXTRACT_PATH_TEXT".to_string(),
938 vec![f.this, f.path],
939 )))),
940
941 Expression::Struct(f) => Ok(Expression::Function(Box::new(Function::new(
944 "OBJECT_CONSTRUCT".to_string(),
945 f.fields
946 .into_iter()
947 .flat_map(|(name, expr)| {
948 let key = match name {
949 Some(n) => Expression::string(n),
950 None => Expression::Null(crate::expressions::Null),
951 };
952 vec![key, expr]
953 })
954 .collect(),
955 )))),
956
957 Expression::JSONPathRoot(_) => Ok(Expression::Literal(
960 crate::expressions::Literal::String(String::new()),
961 )),
962
963 Expression::VarSamp(agg) => Ok(Expression::Variance(agg)),
966
967 Expression::VarPop(agg) => Ok(Expression::VarPop(agg)),
970
971 Expression::Extract(f) => {
974 use crate::expressions::DateTimeField;
975 let transformed_this = self.transform_expr(f.this)?;
977 let field_name = match &f.field {
978 DateTimeField::Year => "YEAR",
979 DateTimeField::Month => "MONTH",
980 DateTimeField::Day => "DAY",
981 DateTimeField::Hour => "HOUR",
982 DateTimeField::Minute => "MINUTE",
983 DateTimeField::Second => "SECOND",
984 DateTimeField::Millisecond => "MILLISECOND",
985 DateTimeField::Microsecond => "MICROSECOND",
986 DateTimeField::Week => "WEEK",
987 DateTimeField::WeekWithModifier(m) => {
988 return Ok(Expression::Function(Box::new(Function::new(
989 "DATE_PART".to_string(),
990 vec![
991 Expression::Identifier(crate::expressions::Identifier {
992 name: format!("WEEK({})", m),
993 quoted: false,
994 trailing_comments: Vec::new(),
995 span: None,
996 }),
997 transformed_this,
998 ],
999 ))))
1000 }
1001 DateTimeField::DayOfWeek => "DAYOFWEEK",
1002 DateTimeField::DayOfYear => "DAYOFYEAR",
1003 DateTimeField::Quarter => "QUARTER",
1004 DateTimeField::Epoch => "EPOCH",
1005 DateTimeField::Timezone => "TIMEZONE",
1006 DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
1007 DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
1008 DateTimeField::Date => "DATE",
1009 DateTimeField::Time => "TIME",
1010 DateTimeField::Custom(s) => {
1011 match s.to_uppercase().as_str() {
1013 "DAYOFMONTH" => "DAY",
1014 "DOW" => "DAYOFWEEK",
1015 "DOY" => "DAYOFYEAR",
1016 "ISODOW" => "DAYOFWEEKISO",
1017 "EPOCH_SECOND" | "EPOCH_SECONDS" => "EPOCH_SECOND",
1018 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => "EPOCH_MILLISECOND",
1019 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => "EPOCH_MICROSECOND",
1020 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => "EPOCH_NANOSECOND",
1021 _ => {
1022 return {
1023 let field_ident =
1024 Expression::Identifier(crate::expressions::Identifier {
1025 name: s.to_string(),
1026 quoted: false,
1027 trailing_comments: Vec::new(),
1028 span: None,
1029 });
1030 Ok(Expression::Function(Box::new(Function::new(
1031 "DATE_PART".to_string(),
1032 vec![field_ident, transformed_this],
1033 ))))
1034 }
1035 }
1036 }
1037 }
1038 };
1039 let field_ident = Expression::Identifier(crate::expressions::Identifier {
1040 name: field_name.to_string(),
1041 quoted: false,
1042 trailing_comments: Vec::new(),
1043 span: None,
1044 });
1045 Ok(Expression::Function(Box::new(Function::new(
1046 "DATE_PART".to_string(),
1047 vec![field_ident, transformed_this],
1048 ))))
1049 }
1050
1051 Expression::Function(f) => self.transform_function(*f),
1053
1054 Expression::Sum(mut agg) => {
1056 agg.this = self.transform_expr(agg.this)?;
1057 Ok(Expression::Sum(agg))
1058 }
1059
1060 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
1062
1063 Expression::NamedArgument(na) => {
1065 let transformed_value = self.transform_expr(na.value)?;
1066 Ok(Expression::NamedArgument(Box::new(
1067 crate::expressions::NamedArgument {
1068 name: na.name,
1069 value: transformed_value,
1070 separator: na.separator,
1071 },
1072 )))
1073 }
1074
1075 Expression::CreateTable(mut ct) => {
1077 for col in &mut ct.columns {
1078 if let Expression::DataType(new_dt) =
1079 self.transform_data_type(col.data_type.clone())?
1080 {
1081 col.data_type = new_dt;
1082 }
1083 if let Some(default_expr) = col.default.take() {
1085 col.default = Some(self.transform_expr(default_expr)?);
1086 }
1087 for constraint in &mut col.constraints {
1089 if let crate::expressions::ColumnConstraint::ComputedColumn(cc) = constraint
1090 {
1091 let transformed = self.transform_expr(*cc.expression.clone())?;
1092 cc.expression = Box::new(transformed);
1093 }
1094 }
1095 }
1096
1097 if ct.table_modifier.as_deref() == Some("EXTERNAL")
1100 && !ct.with_properties.is_empty()
1101 {
1102 for (key, value) in ct.with_properties.drain(..) {
1103 let formatted = Self::format_external_table_property(&key, &value);
1104 ct.properties
1105 .push(Expression::Raw(crate::expressions::Raw { sql: formatted }));
1106 }
1107 }
1108
1109 Ok(Expression::CreateTable(ct))
1110 }
1111
1112 Expression::AlterTable(mut at) => {
1114 for action in &mut at.actions {
1115 if let crate::expressions::AlterTableAction::AddColumn { column, .. } = action {
1116 if let Expression::DataType(new_dt) =
1117 self.transform_data_type(column.data_type.clone())?
1118 {
1119 column.data_type = new_dt;
1120 }
1121 }
1122 }
1123 Ok(Expression::AlterTable(at))
1124 }
1125
1126 Expression::Table(mut t) => {
1128 if let Some(when) = t.when.take() {
1129 let transformed_expr = self.transform_expr(*when.expression)?;
1131 t.when = Some(Box::new(crate::expressions::HistoricalData {
1132 this: when.this,
1133 kind: when.kind,
1134 expression: Box::new(transformed_expr),
1135 }));
1136 }
1137 Ok(Expression::Table(t))
1138 }
1139
1140 Expression::Subscript(s) => {
1142 let transformed_this = self.transform_expr(s.this)?;
1143 let transformed_index = self.transform_expr(s.index)?;
1144 Ok(Expression::Subscript(Box::new(
1145 crate::expressions::Subscript {
1146 this: transformed_this,
1147 index: transformed_index,
1148 },
1149 )))
1150 }
1151
1152 Expression::Paren(p) => {
1154 let transformed = self.transform_expr(p.this)?;
1155 Ok(Expression::Paren(Box::new(crate::expressions::Paren {
1156 this: transformed,
1157 trailing_comments: p.trailing_comments,
1158 })))
1159 }
1160
1161 Expression::Select(mut select) => {
1165 if let Some(ref mut order) = select.order_by {
1166 for ord in &mut order.expressions {
1167 if ord.nulls_first.is_none() {
1168 ord.nulls_first = Some(ord.desc);
1169 }
1170 }
1171 }
1172 Ok(Expression::Select(select))
1173 }
1174
1175 Expression::WindowFunction(mut wf) => {
1177 for ord in &mut wf.over.order_by {
1178 if ord.nulls_first.is_none() {
1179 ord.nulls_first = Some(ord.desc);
1180 }
1181 }
1182 Ok(Expression::WindowFunction(wf))
1183 }
1184
1185 Expression::Window(mut w) => {
1187 for ord in &mut w.order_by {
1188 if ord.nulls_first.is_none() {
1189 ord.nulls_first = Some(ord.desc);
1190 }
1191 }
1192 Ok(Expression::Window(w))
1193 }
1194
1195 Expression::Lateral(mut lat) => {
1197 let is_flatten = match lat.this.as_ref() {
1199 Expression::Function(f) => f.name.to_uppercase() == "FLATTEN",
1200 _ => false,
1201 };
1202 if is_flatten && lat.column_aliases.is_empty() {
1203 lat.column_aliases = vec![
1205 "SEQ".to_string(),
1206 "KEY".to_string(),
1207 "PATH".to_string(),
1208 "INDEX".to_string(),
1209 "VALUE".to_string(),
1210 "THIS".to_string(),
1211 ];
1212 if lat.alias.is_none() {
1214 lat.alias = Some("_flattened".to_string());
1215 }
1216 }
1217 Ok(Expression::Lateral(lat))
1218 }
1219
1220 _ => Ok(expr),
1222 }
1223 }
1224}
1225
1226impl SnowflakeDialect {
1227 fn format_external_table_property(key: &str, value: &str) -> String {
1230 let lower_key = key.to_lowercase();
1231 match lower_key.as_str() {
1232 "location" => format!("LOCATION={}", value),
1233 "file_format" => {
1234 let formatted_value = Self::format_file_format_value(value);
1236 format!("FILE_FORMAT={}", formatted_value)
1237 }
1238 _ => format!("{}={}", key, value),
1239 }
1240 }
1241
1242 fn format_file_format_value(value: &str) -> String {
1246 if !value.starts_with('(') {
1247 return value.to_string();
1248 }
1249 let inner = value[1..value.len() - 1].trim();
1251 let mut result = String::from("(");
1253 let mut parts: Vec<String> = Vec::new();
1254 let tokens: Vec<&str> = inner.split_whitespace().collect();
1256 let mut i = 0;
1257 while i < tokens.len() {
1258 let token = tokens[i];
1259 if i + 2 < tokens.len() && tokens[i + 1] == "=" {
1260 let val = Self::format_property_value(tokens[i + 2]);
1262 parts.push(format!("{}={}", token, val));
1263 i += 3;
1264 } else if token.contains('=') {
1265 let eq_pos = token.find('=').unwrap();
1267 let k = &token[..eq_pos];
1268 let v = Self::format_property_value(&token[eq_pos + 1..]);
1269 parts.push(format!("{}={}", k, v));
1270 i += 1;
1271 } else {
1272 parts.push(token.to_string());
1273 i += 1;
1274 }
1275 }
1276 result.push_str(&parts.join(" "));
1277 result.push(')');
1278 result
1279 }
1280
1281 fn format_property_value(value: &str) -> String {
1283 match value.to_lowercase().as_str() {
1284 "true" => "TRUE".to_string(),
1285 "false" => "FALSE".to_string(),
1286 _ => value.to_string(),
1287 }
1288 }
1289
1290 fn transform_data_type(&self, dt: crate::expressions::DataType) -> Result<Expression> {
1292 use crate::expressions::DataType;
1293 let transformed = match dt {
1294 DataType::Text => DataType::VarChar {
1296 length: None,
1297 parenthesized_length: false,
1298 },
1299 DataType::Struct { fields, .. } => {
1301 let _ = fields; DataType::Custom {
1304 name: "OBJECT".to_string(),
1305 }
1306 }
1307 DataType::Custom { name } => {
1309 let upper_name = name.to_uppercase();
1310 match upper_name.as_str() {
1311 "NVARCHAR" | "NCHAR" | "NATIONAL CHARACTER VARYING" | "NATIONAL CHAR" => {
1313 DataType::VarChar {
1314 length: None,
1315 parenthesized_length: false,
1316 }
1317 }
1318 "STRING" => DataType::VarChar {
1320 length: None,
1321 parenthesized_length: false,
1322 },
1323 "BIGDECIMAL" => DataType::Double {
1325 precision: None,
1326 scale: None,
1327 },
1328 "NESTED" => DataType::Custom {
1330 name: "OBJECT".to_string(),
1331 },
1332 "BYTEINT" => DataType::Int {
1334 length: None,
1335 integer_spelling: false,
1336 },
1337 "CHAR VARYING" | "CHARACTER VARYING" => DataType::VarChar {
1339 length: None,
1340 parenthesized_length: false,
1341 },
1342 "SQL_DOUBLE" => DataType::Double {
1344 precision: None,
1345 scale: None,
1346 },
1347 "SQL_VARCHAR" => DataType::VarChar {
1349 length: None,
1350 parenthesized_length: false,
1351 },
1352 "TIMESTAMP_NTZ" => DataType::Custom {
1354 name: "TIMESTAMPNTZ".to_string(),
1355 },
1356 "TIMESTAMP_LTZ" => DataType::Custom {
1358 name: "TIMESTAMPLTZ".to_string(),
1359 },
1360 "TIMESTAMP_TZ" => DataType::Custom {
1362 name: "TIMESTAMPTZ".to_string(),
1363 },
1364 "NCHAR VARYING" => DataType::VarChar {
1366 length: None,
1367 parenthesized_length: false,
1368 },
1369 "NUMBER" => DataType::Decimal {
1371 precision: Some(38),
1372 scale: Some(0),
1373 },
1374 _ if name.starts_with("NUMBER(") => {
1375 let inner = &name[7..name.len() - 1]; let parts: Vec<&str> = inner.split(',').map(|s| s.trim()).collect();
1379 let precision = parts.first().and_then(|p| p.parse::<u32>().ok());
1380 let scale = parts.get(1).and_then(|s| s.parse::<u32>().ok());
1381 DataType::Decimal { precision, scale }
1382 }
1383 _ => DataType::Custom { name },
1384 }
1385 }
1386 DataType::Decimal {
1388 precision: None,
1389 scale: None,
1390 } => DataType::Decimal {
1391 precision: Some(38),
1392 scale: Some(0),
1393 },
1394 DataType::Float { .. } => DataType::Double {
1396 precision: None,
1397 scale: None,
1398 },
1399 other => other,
1401 };
1402 Ok(Expression::DataType(transformed))
1403 }
1404
1405 fn map_date_part(abbr: &str) -> Option<&'static str> {
1407 match abbr.to_uppercase().as_str() {
1408 "Y" | "YY" | "YYY" | "YYYY" | "YR" | "YEARS" | "YRS" => Some("YEAR"),
1410 "MM" | "MON" | "MONS" | "MONTHS" => Some("MONTH"),
1412 "D" | "DD" | "DAYS" | "DAYOFMONTH" => Some("DAY"),
1414 "DAY OF WEEK" | "WEEKDAY" | "DOW" | "DW" => Some("DAYOFWEEK"),
1416 "WEEKDAY_ISO" | "DOW_ISO" | "DW_ISO" | "DAYOFWEEK_ISO" => Some("DAYOFWEEKISO"),
1417 "DAY OF YEAR" | "DOY" | "DY" => Some("DAYOFYEAR"),
1419 "W" | "WK" | "WEEKOFYEAR" | "WOY" | "WY" => Some("WEEK"),
1421 "WEEK_ISO" | "WEEKOFYEARISO" | "WEEKOFYEAR_ISO" => Some("WEEKISO"),
1422 "Q" | "QTR" | "QTRS" | "QUARTERS" => Some("QUARTER"),
1424 "H" | "HH" | "HR" | "HOURS" | "HRS" => Some("HOUR"),
1426 "MI" | "MIN" | "MINUTES" | "MINS" => Some("MINUTE"),
1428 "S" | "SEC" | "SECONDS" | "SECS" => Some("SECOND"),
1430 "MS" | "MSEC" | "MSECS" | "MSECOND" | "MSECONDS" | "MILLISEC" | "MILLISECS"
1432 | "MILLISECON" | "MILLISECONDS" => Some("MILLISECOND"),
1433 "US" | "USEC" | "USECS" | "MICROSEC" | "MICROSECS" | "USECOND" | "USECONDS"
1435 | "MICROSECONDS" => Some("MICROSECOND"),
1436 "NS" | "NSEC" | "NANOSEC" | "NSECOND" | "NSECONDS" | "NANOSECS" => Some("NANOSECOND"),
1438 "EPOCH_SECOND" | "EPOCH_SECONDS" => Some("EPOCH_SECOND"),
1440 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Some("EPOCH_MILLISECOND"),
1441 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Some("EPOCH_MICROSECOND"),
1442 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Some("EPOCH_NANOSECOND"),
1443 "TZH" => Some("TIMEZONE_HOUR"),
1445 "TZM" => Some("TIMEZONE_MINUTE"),
1446 "DEC" | "DECS" | "DECADES" => Some("DECADE"),
1448 "MIL" | "MILS" | "MILLENIA" => Some("MILLENNIUM"),
1450 "C" | "CENT" | "CENTS" | "CENTURIES" => Some("CENTURY"),
1452 _ => None,
1454 }
1455 }
1456
1457 fn transform_date_part_arg(&self, expr: Expression) -> Expression {
1459 match &expr {
1460 Expression::Literal(crate::expressions::Literal::String(s)) => {
1462 Expression::Identifier(crate::expressions::Identifier {
1463 name: s.clone(),
1464 quoted: false,
1465 trailing_comments: Vec::new(),
1466 span: None,
1467 })
1468 }
1469 Expression::Identifier(id) => {
1471 if let Some(canonical) = Self::map_date_part(&id.name) {
1472 Expression::Identifier(crate::expressions::Identifier {
1473 name: canonical.to_string(),
1474 quoted: false,
1475 trailing_comments: Vec::new(),
1476 span: None,
1477 })
1478 } else {
1479 expr
1481 }
1482 }
1483 Expression::Column(col) if col.table.is_none() => {
1485 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1486 Expression::Identifier(crate::expressions::Identifier {
1487 name: canonical.to_string(),
1488 quoted: false,
1489 trailing_comments: Vec::new(),
1490 span: None,
1491 })
1492 } else {
1493 expr
1495 }
1496 }
1497 _ => expr,
1498 }
1499 }
1500
1501 fn transform_date_part_arg_identifiers_only(&self, expr: Expression) -> Expression {
1504 match &expr {
1505 Expression::Identifier(id) => {
1506 if let Some(canonical) = Self::map_date_part(&id.name) {
1507 Expression::Identifier(crate::expressions::Identifier {
1508 name: canonical.to_string(),
1509 quoted: false,
1510 trailing_comments: Vec::new(),
1511 span: None,
1512 })
1513 } else {
1514 expr
1515 }
1516 }
1517 Expression::Column(col) if col.table.is_none() => {
1518 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1519 Expression::Identifier(crate::expressions::Identifier {
1520 name: canonical.to_string(),
1521 quoted: false,
1522 trailing_comments: Vec::new(),
1523 span: None,
1524 })
1525 } else {
1526 expr
1527 }
1528 }
1529 _ => expr,
1530 }
1531 }
1532
1533 fn transform_json_path(path: &str) -> String {
1537 fn is_safe_identifier(s: &str) -> bool {
1540 if s.is_empty() {
1541 return false;
1542 }
1543 let mut chars = s.chars();
1544 match chars.next() {
1545 Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
1546 _ => return false,
1547 }
1548 chars.all(|c| c.is_ascii_alphanumeric() || c == '_')
1549 }
1550
1551 if !path.contains('.') && !path.contains('[') && !path.contains(':') {
1554 if is_safe_identifier(path) {
1555 return path.to_string();
1556 } else {
1557 return format!("[\"{}\"]", path);
1559 }
1560 }
1561
1562 let result = path.replace(':', ".");
1565 result
1566 }
1567
1568 fn transform_interval(&self, interval: crate::expressions::Interval) -> Result<Expression> {
1570 use crate::expressions::{Interval, Literal};
1571
1572 fn expand_unit(abbr: &str) -> &'static str {
1574 match abbr.to_uppercase().as_str() {
1575 "D" => "DAY",
1576 "H" => "HOUR",
1577 "M" => "MINUTE",
1578 "MS" => "MILLISECOND",
1579 "NS" => "NANOSECOND",
1580 "Q" => "QUARTER",
1581 "S" => "SECOND",
1582 "US" => "MICROSECOND",
1583 "W" => "WEEK",
1584 "Y" => "YEAR",
1585 "WEEK" | "WEEKS" => "WEEK",
1587 "DAY" | "DAYS" => "DAY",
1588 "HOUR" | "HOURS" => "HOUR",
1589 "MINUTE" | "MINUTES" => "MINUTE",
1590 "SECOND" | "SECONDS" => "SECOND",
1591 "MONTH" | "MONTHS" => "MONTH",
1592 "YEAR" | "YEARS" => "YEAR",
1593 "QUARTER" | "QUARTERS" => "QUARTER",
1594 "MILLISECOND" | "MILLISECONDS" => "MILLISECOND",
1595 "MICROSECOND" | "MICROSECONDS" => "MICROSECOND",
1596 "NANOSECOND" | "NANOSECONDS" => "NANOSECOND",
1597 _ => "", }
1599 }
1600
1601 fn parse_interval_string(s: &str) -> Option<(&str, &str)> {
1603 let s = s.trim();
1604
1605 let mut num_end = 0;
1608 let mut chars = s.chars().peekable();
1609
1610 if chars.peek() == Some(&'-') {
1612 chars.next();
1613 num_end += 1;
1614 }
1615
1616 while let Some(&c) = chars.peek() {
1618 if c.is_ascii_digit() {
1619 chars.next();
1620 num_end += 1;
1621 } else {
1622 break;
1623 }
1624 }
1625
1626 if chars.peek() == Some(&'.') {
1628 chars.next();
1629 num_end += 1;
1630 while let Some(&c) = chars.peek() {
1631 if c.is_ascii_digit() {
1632 chars.next();
1633 num_end += 1;
1634 } else {
1635 break;
1636 }
1637 }
1638 }
1639
1640 if num_end == 0 || (num_end == 1 && s.starts_with('-')) {
1641 return None; }
1643
1644 let value = &s[..num_end];
1645 let rest = s[num_end..].trim();
1646
1647 if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_alphabetic()) {
1649 return None;
1650 }
1651
1652 Some((value, rest))
1653 }
1654
1655 if let Some(Expression::Literal(Literal::String(ref s))) = interval.this {
1657 if let Some((value, unit)) = parse_interval_string(s) {
1658 let expanded = expand_unit(unit);
1659 if !expanded.is_empty() {
1660 let new_value = format!("{} {}", value, expanded);
1662
1663 return Ok(Expression::Interval(Box::new(Interval {
1664 this: Some(Expression::Literal(Literal::String(new_value))),
1665 unit: None, })));
1667 }
1668 }
1669 }
1670
1671 Ok(Expression::Interval(Box::new(interval)))
1673 }
1674
1675 fn transform_function(&self, f: Function) -> Result<Expression> {
1676 let transformed_args: Vec<Expression> = f
1678 .args
1679 .into_iter()
1680 .map(|arg| self.transform_expr(arg))
1681 .collect::<Result<Vec<_>>>()?;
1682
1683 let f = Function {
1684 name: f.name,
1685 args: transformed_args,
1686 distinct: f.distinct,
1687 trailing_comments: f.trailing_comments,
1688 use_bracket_syntax: f.use_bracket_syntax,
1689 no_parens: f.no_parens,
1690 quoted: f.quoted,
1691 span: None,
1692 inferred_type: None,
1693 };
1694
1695 let name_upper = f.name.to_uppercase();
1696 match name_upper.as_str() {
1697 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1699 original_name: None,
1700 expressions: f.args,
1701 inferred_type: None,
1702 }))),
1703
1704 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1706 original_name: None,
1707 expressions: f.args,
1708 inferred_type: None,
1709 }))),
1710
1711 "NVL2" => Ok(Expression::Function(Box::new(f))),
1713
1714 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1716 Function::new("LISTAGG".to_string(), f.args),
1717 ))),
1718
1719 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1721 Function::new("LISTAGG".to_string(), f.args),
1722 ))),
1723
1724 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
1726 "SUBSTRING".to_string(),
1727 f.args,
1728 )))),
1729
1730 "UNNEST" => Ok(Expression::Function(Box::new(Function::new(
1732 "FLATTEN".to_string(),
1733 f.args,
1734 )))),
1735
1736 "EXPLODE" => Ok(Expression::Function(Box::new(Function::new(
1738 "FLATTEN".to_string(),
1739 f.args,
1740 )))),
1741
1742 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1744
1745 "NOW" => Ok(Expression::Function(Box::new(Function {
1747 name: "CURRENT_TIMESTAMP".to_string(),
1748 args: f.args,
1749 distinct: false,
1750 trailing_comments: Vec::new(),
1751 use_bracket_syntax: false,
1752 no_parens: f.no_parens,
1753 quoted: false,
1754 span: None,
1755 inferred_type: None,
1756 }))),
1757
1758 "GETDATE" => Ok(Expression::Function(Box::new(Function {
1760 name: "CURRENT_TIMESTAMP".to_string(),
1761 args: f.args,
1762 distinct: false,
1763 trailing_comments: Vec::new(),
1764 use_bracket_syntax: false,
1765 no_parens: f.no_parens,
1766 quoted: false,
1767 span: None,
1768 inferred_type: None,
1769 }))),
1770
1771 "CURRENT_TIMESTAMP" if f.args.is_empty() => {
1775 Ok(Expression::Function(Box::new(Function {
1776 name: "CURRENT_TIMESTAMP".to_string(),
1777 args: Vec::new(),
1778 distinct: false,
1779 trailing_comments: Vec::new(),
1780 use_bracket_syntax: false,
1781 no_parens: false, quoted: false,
1783 span: None,
1784 inferred_type: None,
1785 })))
1786 }
1787
1788 "TO_DATE" => {
1792 if f.args.len() == 1 {
1793 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
1794 {
1795 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
1797 return Ok(Expression::Cast(Box::new(Cast {
1798 this: f.args.into_iter().next().unwrap(),
1799 to: crate::expressions::DataType::Date,
1800 double_colon_syntax: false,
1801 trailing_comments: Vec::new(),
1802 format: None,
1803 default: None,
1804 inferred_type: None,
1805 })));
1806 }
1807 }
1808 }
1809 let mut args = f.args;
1811 if args.len() >= 2 {
1812 args[1] = Self::normalize_format_arg(args[1].clone());
1813 }
1814 Ok(Expression::Function(Box::new(Function::new(
1815 "TO_DATE".to_string(),
1816 args,
1817 ))))
1818 }
1819
1820 "TO_TIME" => {
1822 if f.args.len() == 1 {
1823 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
1824 {
1825 return Ok(Expression::Cast(Box::new(Cast {
1826 this: f.args.into_iter().next().unwrap(),
1827 to: crate::expressions::DataType::Time {
1828 precision: None,
1829 timezone: false,
1830 },
1831 double_colon_syntax: false,
1832 trailing_comments: Vec::new(),
1833 format: None,
1834 default: None,
1835 inferred_type: None,
1836 })));
1837 }
1838 }
1839 let mut args = f.args;
1841 if args.len() >= 2 {
1842 args[1] = Self::normalize_format_arg(args[1].clone());
1843 }
1844 Ok(Expression::Function(Box::new(Function::new(
1845 "TO_TIME".to_string(),
1846 args,
1847 ))))
1848 }
1849
1850 "TO_TIMESTAMP" => {
1857 let args = f.args;
1858 if args.len() == 1 {
1859 let arg = &args[0];
1860 match arg {
1861 Expression::Literal(Literal::String(s)) if Self::looks_like_datetime(s) => {
1862 return Ok(Expression::Cast(Box::new(Cast {
1864 this: args.into_iter().next().unwrap(),
1865 to: DataType::Timestamp {
1866 precision: None,
1867 timezone: false,
1868 },
1869 double_colon_syntax: false,
1870 trailing_comments: vec![],
1871 format: None,
1872 default: None,
1873 inferred_type: None,
1874 })));
1875 }
1876 Expression::Literal(Literal::String(s)) if Self::looks_like_epoch(s) => {
1877 return Ok(Expression::UnixToTime(Box::new(
1879 crate::expressions::UnixToTime {
1880 this: Box::new(args.into_iter().next().unwrap()),
1881 scale: None,
1882 zone: None,
1883 hours: None,
1884 minutes: None,
1885 format: None,
1886 target_type: None,
1887 },
1888 )));
1889 }
1890 Expression::Literal(Literal::Number(_)) | Expression::Neg(_) => {
1891 return Ok(Expression::UnixToTime(Box::new(
1893 crate::expressions::UnixToTime {
1894 this: Box::new(args.into_iter().next().unwrap()),
1895 scale: None,
1896 zone: None,
1897 hours: None,
1898 minutes: None,
1899 format: None,
1900 target_type: None,
1901 },
1902 )));
1903 }
1904 _ => {
1905 return Ok(Expression::Function(Box::new(Function::new(
1907 "TO_TIMESTAMP".to_string(),
1908 args,
1909 ))));
1910 }
1911 }
1912 } else if args.len() == 2 {
1913 let second_arg = &args[1];
1914 let is_int_scale = match second_arg {
1916 Expression::Literal(Literal::Number(n)) => n.parse::<i64>().is_ok(),
1917 _ => false,
1918 };
1919
1920 if is_int_scale {
1921 let mut args_iter = args.into_iter();
1923 let value = args_iter.next().unwrap();
1924 let scale_expr = args_iter.next().unwrap();
1925 let scale = if let Expression::Literal(Literal::Number(n)) = &scale_expr {
1926 n.parse::<i64>().ok()
1927 } else {
1928 None
1929 };
1930 return Ok(Expression::UnixToTime(Box::new(
1931 crate::expressions::UnixToTime {
1932 this: Box::new(value),
1933 scale,
1934 zone: None,
1935 hours: None,
1936 minutes: None,
1937 format: None,
1938 target_type: None,
1939 },
1940 )));
1941 } else {
1942 let mut args_iter = args.into_iter();
1944 let value = args_iter.next().unwrap();
1945 let format_expr = args_iter.next().unwrap();
1946 let format_str = match &format_expr {
1947 Expression::Literal(Literal::String(s)) => s.clone(),
1948 _ => {
1949 return Ok(Expression::Function(Box::new(Function::new(
1951 "TO_TIMESTAMP".to_string(),
1952 vec![value, format_expr],
1953 ))));
1954 }
1955 };
1956 let normalized_format = Self::normalize_snowflake_format(&format_str);
1958 return Ok(Expression::StrToTime(Box::new(
1959 crate::expressions::StrToTime {
1960 this: Box::new(value),
1961 format: normalized_format,
1962 zone: None,
1963 safe: None,
1964 target_type: None,
1965 },
1966 )));
1967 }
1968 }
1969 Ok(Expression::Function(Box::new(Function::new(
1971 "TO_TIMESTAMP".to_string(),
1972 args,
1973 ))))
1974 }
1975
1976 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
1978
1979 "ROUND"
1982 if f.args
1983 .iter()
1984 .any(|a| matches!(a, Expression::NamedArgument(_))) =>
1985 {
1986 let mut expr_val = None;
1987 let mut scale_val = None;
1988 let mut rounding_mode_val = None;
1989 for arg in &f.args {
1990 if let Expression::NamedArgument(na) = arg {
1991 match na.name.name.to_uppercase().as_str() {
1992 "EXPR" => expr_val = Some(na.value.clone()),
1993 "SCALE" => scale_val = Some(na.value.clone()),
1994 "ROUNDING_MODE" => rounding_mode_val = Some(na.value.clone()),
1995 _ => {}
1996 }
1997 }
1998 }
1999 if let Some(expr) = expr_val {
2000 let mut args = vec![expr];
2001 if let Some(scale) = scale_val {
2002 args.push(scale);
2003 }
2004 if let Some(mode) = rounding_mode_val {
2005 args.push(mode);
2006 }
2007 Ok(Expression::Function(Box::new(Function::new(
2008 "ROUND".to_string(),
2009 args,
2010 ))))
2011 } else {
2012 Ok(Expression::Function(Box::new(f)))
2013 }
2014 }
2015
2016 "DATE_FORMAT" => {
2019 let mut args = f.args;
2020 if !args.is_empty() {
2022 if matches!(&args[0], Expression::Literal(Literal::String(_))) {
2023 args[0] = Expression::Cast(Box::new(crate::expressions::Cast {
2024 this: args[0].clone(),
2025 to: DataType::Timestamp {
2026 precision: None,
2027 timezone: false,
2028 },
2029 trailing_comments: Vec::new(),
2030 double_colon_syntax: false,
2031 format: None,
2032 default: None,
2033 inferred_type: None,
2034 }));
2035 }
2036 }
2037 if args.len() >= 2 {
2039 if let Expression::Literal(Literal::String(ref fmt)) = args[1] {
2040 let sf_fmt = strftime_to_snowflake_format(fmt);
2041 args[1] = Expression::Literal(Literal::String(sf_fmt));
2042 }
2043 }
2044 Ok(Expression::Function(Box::new(Function::new(
2045 "TO_CHAR".to_string(),
2046 args,
2047 ))))
2048 }
2049
2050 "ARRAY" => Ok(Expression::Function(Box::new(Function::new(
2052 "ARRAY_CONSTRUCT".to_string(),
2053 f.args,
2054 )))),
2055
2056 "STRUCT" => {
2059 let mut oc_args = Vec::new();
2060 for arg in f.args {
2061 match arg {
2062 Expression::Alias(a) => {
2063 oc_args.push(Expression::Literal(crate::expressions::Literal::String(
2065 a.alias.name.clone(),
2066 )));
2067 oc_args.push(a.this);
2068 }
2069 other => {
2070 oc_args.push(other);
2072 }
2073 }
2074 }
2075 Ok(Expression::Function(Box::new(Function::new(
2076 "OBJECT_CONSTRUCT".to_string(),
2077 oc_args,
2078 ))))
2079 }
2080
2081 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2083 "GET_PATH".to_string(),
2084 f.args,
2085 )))),
2086
2087 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
2089 "JSON_EXTRACT_PATH_TEXT".to_string(),
2090 f.args,
2091 )))),
2092
2093 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
2095 f.args.into_iter().next().unwrap(),
2096 )))),
2097
2098 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
2100 this: f.args.into_iter().next().unwrap(),
2101 decimals: None,
2102 to: None,
2103 }))),
2104
2105 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
2107
2108 "SPLIT" => Ok(Expression::Function(Box::new(f))),
2110
2111 "ARRAY_AGG" => Ok(Expression::Function(Box::new(f))),
2113
2114 "JSON_PARSE" | "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
2116 "PARSE_JSON".to_string(),
2117 f.args,
2118 )))),
2119
2120 "RAND" => {
2122 let seed = f.args.first().cloned().map(Box::new);
2123 Ok(Expression::Rand(Box::new(crate::expressions::Rand {
2124 seed,
2125 lower: None,
2126 upper: None,
2127 })))
2128 }
2129
2130 "SHA" => Ok(Expression::Function(Box::new(Function::new(
2132 "SHA1".to_string(),
2133 f.args,
2134 )))),
2135
2136 "APPROX_DISTINCT" => Ok(Expression::Function(Box::new(Function::new(
2138 "APPROX_COUNT_DISTINCT".to_string(),
2139 f.args,
2140 )))),
2141
2142 "GEN_RANDOM_UUID" | "UUID" => {
2144 Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2145 this: None,
2146 name: None,
2147 is_string: None,
2148 })))
2149 }
2150
2151 "NEWID" => Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2153 this: None,
2154 name: None,
2155 is_string: None,
2156 }))),
2157
2158 "UUID_STRING" => {
2160 if f.args.is_empty() {
2161 Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2162 this: None,
2163 name: None,
2164 is_string: None,
2165 })))
2166 } else {
2167 Ok(Expression::Function(Box::new(Function::new(
2168 "UUID_STRING".to_string(),
2169 f.args,
2170 ))))
2171 }
2172 }
2173
2174 "IF" if f.args.len() >= 2 => {
2176 let mut args = f.args;
2177 let condition = args.remove(0);
2178 let true_val = args.remove(0);
2179 let false_val = if !args.is_empty() {
2180 Some(args.remove(0))
2181 } else {
2182 None
2183 };
2184 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2185 condition,
2186 true_value: true_val,
2187 false_value: Some(
2188 false_val.unwrap_or(Expression::Null(crate::expressions::Null)),
2189 ),
2190 original_name: Some("IFF".to_string()),
2191 })))
2192 }
2193
2194 "SQUARE" if f.args.len() == 1 => {
2196 let x = f.args.into_iter().next().unwrap();
2197 Ok(Expression::Power(Box::new(
2198 crate::expressions::BinaryFunc {
2199 original_name: None,
2200 this: x,
2201 expression: Expression::number(2),
2202 inferred_type: None,
2203 },
2204 )))
2205 }
2206
2207 "POW" if f.args.len() == 2 => {
2209 let mut args = f.args.into_iter();
2210 let x = args.next().unwrap();
2211 let y = args.next().unwrap();
2212 Ok(Expression::Power(Box::new(
2213 crate::expressions::BinaryFunc {
2214 original_name: None,
2215 this: x,
2216 expression: y,
2217 inferred_type: None,
2218 },
2219 )))
2220 }
2221
2222 "MOD" if f.args.len() == 2 => {
2224 let mut args = f.args.into_iter();
2225 let x = args.next().unwrap();
2226 let y = args.next().unwrap();
2227 Ok(Expression::Mod(Box::new(crate::expressions::BinaryOp {
2228 left: x,
2229 right: y,
2230 left_comments: Vec::new(),
2231 operator_comments: Vec::new(),
2232 trailing_comments: Vec::new(),
2233 inferred_type: None,
2234 })))
2235 }
2236
2237 "APPROXIMATE_JACCARD_INDEX" => Ok(Expression::Function(Box::new(Function::new(
2239 "APPROXIMATE_SIMILARITY".to_string(),
2240 f.args,
2241 )))),
2242
2243 "ARRAY_CONSTRUCT" => Ok(Expression::ArrayFunc(Box::new(
2245 crate::expressions::ArrayConstructor {
2246 expressions: f.args,
2247 bracket_notation: true,
2248 use_list_keyword: false,
2249 },
2250 ))),
2251
2252 "APPROX_TOP_K" if f.args.len() == 1 => {
2254 let mut args = f.args;
2255 args.push(Expression::number(1));
2256 Ok(Expression::Function(Box::new(Function::new(
2257 "APPROX_TOP_K".to_string(),
2258 args,
2259 ))))
2260 }
2261
2262 "TO_DECIMAL" | "TO_NUMERIC" => Ok(Expression::Function(Box::new(Function::new(
2264 "TO_NUMBER".to_string(),
2265 f.args,
2266 )))),
2267
2268 "TRY_TO_DECIMAL" | "TRY_TO_NUMERIC" => Ok(Expression::Function(Box::new(
2270 Function::new("TRY_TO_NUMBER".to_string(), f.args),
2271 ))),
2272
2273 "STDDEV_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2275 "STDDEV".to_string(),
2276 f.args,
2277 )))),
2278
2279 "STRTOK" if f.args.len() >= 1 => {
2281 let mut args = f.args;
2282 if args.len() == 1 {
2284 args.push(Expression::string(" ".to_string()));
2285 }
2286 if args.len() == 2 {
2288 args.push(Expression::number(1));
2289 }
2290 Ok(Expression::Function(Box::new(Function::new(
2291 "SPLIT_PART".to_string(),
2292 args,
2293 ))))
2294 }
2295
2296 "WEEKOFYEAR" => Ok(Expression::Function(Box::new(Function::new(
2298 "WEEK".to_string(),
2299 f.args,
2300 )))),
2301
2302 "LIKE" if f.args.len() >= 2 => {
2304 let mut args = f.args.into_iter();
2305 let left = args.next().unwrap();
2306 let right = args.next().unwrap();
2307 let escape = args.next();
2308 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
2309 left,
2310 right,
2311 escape,
2312 quantifier: None,
2313 inferred_type: None,
2314 })))
2315 }
2316
2317 "ILIKE" if f.args.len() >= 2 => {
2319 let mut args = f.args.into_iter();
2320 let left = args.next().unwrap();
2321 let right = args.next().unwrap();
2322 let escape = args.next();
2323 Ok(Expression::ILike(Box::new(crate::expressions::LikeOp {
2324 left,
2325 right,
2326 escape,
2327 quantifier: None,
2328 inferred_type: None,
2329 })))
2330 }
2331
2332 "RLIKE" if f.args.len() >= 2 => {
2334 let mut args = f.args.into_iter();
2335 let left = args.next().unwrap();
2336 let pattern = args.next().unwrap();
2337 let flags = args.next();
2338 Ok(Expression::RegexpLike(Box::new(
2339 crate::expressions::RegexpFunc {
2340 this: left,
2341 pattern,
2342 flags,
2343 },
2344 )))
2345 }
2346
2347 "IFF" if f.args.len() >= 2 => {
2349 let mut args = f.args;
2350 let condition = args.remove(0);
2351 let true_value = args.remove(0);
2352 let false_value = if !args.is_empty() {
2353 Some(args.remove(0))
2354 } else {
2355 None
2356 };
2357 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2358 condition,
2359 true_value,
2360 false_value,
2361 original_name: Some("IFF".to_string()),
2362 })))
2363 }
2364
2365 "TIMESTAMP_NTZ_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMPNTZFROMPARTS" => {
2367 Ok(Expression::Function(Box::new(Function::new(
2368 "TIMESTAMP_FROM_PARTS".to_string(),
2369 f.args,
2370 ))))
2371 }
2372
2373 "TIMESTAMPLTZFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2375 "TIMESTAMP_LTZ_FROM_PARTS".to_string(),
2376 f.args,
2377 )))),
2378
2379 "TIMESTAMPTZFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2381 "TIMESTAMP_TZ_FROM_PARTS".to_string(),
2382 f.args,
2383 )))),
2384
2385 "DATEADD" if f.args.len() >= 1 => {
2387 let mut args = f.args;
2388 args[0] = self.transform_date_part_arg(args[0].clone());
2389 Ok(Expression::Function(Box::new(Function::new(
2390 "DATEADD".to_string(),
2391 args,
2392 ))))
2393 }
2394
2395 "DATEDIFF" if f.args.len() >= 1 => {
2398 let mut args = f.args;
2399 args[0] = self.transform_date_part_arg(args[0].clone());
2400 for i in 1..args.len() {
2403 if let Expression::Function(ref func) = args[i] {
2404 if func.name == "_POLYGLOT_TO_DATE" {
2405 let inner_args = func.args.clone();
2406 args[i] = Expression::Function(Box::new(Function::new(
2407 "TO_DATE".to_string(),
2408 inner_args,
2409 )));
2410 }
2411 }
2412 }
2413 Ok(Expression::Function(Box::new(Function::new(
2414 "DATEDIFF".to_string(),
2415 args,
2416 ))))
2417 }
2418
2419 "TIMEDIFF" => Ok(Expression::Function(Box::new(Function::new(
2421 "DATEDIFF".to_string(),
2422 f.args,
2423 )))),
2424
2425 "TIMESTAMPDIFF" => Ok(Expression::Function(Box::new(Function::new(
2427 "DATEDIFF".to_string(),
2428 f.args,
2429 )))),
2430
2431 "TIMESTAMPADD" => Ok(Expression::Function(Box::new(Function::new(
2433 "DATEADD".to_string(),
2434 f.args,
2435 )))),
2436
2437 "TIMEADD" => Ok(Expression::Function(Box::new(f))),
2439
2440 "DATEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2442 "DATE_FROM_PARTS".to_string(),
2443 f.args,
2444 )))),
2445
2446 "TIMEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2448 "TIME_FROM_PARTS".to_string(),
2449 f.args,
2450 )))),
2451
2452 "DAYOFWEEK" => Ok(Expression::Function(Box::new(f))),
2454
2455 "DAYOFMONTH" => Ok(Expression::Function(Box::new(f))),
2457
2458 "DAYOFYEAR" => Ok(Expression::Function(Box::new(f))),
2460
2461 "MONTHNAME" if f.args.len() == 1 => {
2464 let arg = f.args.into_iter().next().unwrap();
2465 Ok(Expression::Monthname(Box::new(
2466 crate::expressions::Monthname {
2467 this: Box::new(arg),
2468 abbreviated: Some(Box::new(Expression::Literal(Literal::String(
2469 "true".to_string(),
2470 )))),
2471 },
2472 )))
2473 }
2474
2475 "DAYNAME" if f.args.len() == 1 => {
2478 let arg = f.args.into_iter().next().unwrap();
2479 Ok(Expression::Dayname(Box::new(crate::expressions::Dayname {
2480 this: Box::new(arg),
2481 abbreviated: Some(Box::new(Expression::Literal(Literal::String(
2482 "true".to_string(),
2483 )))),
2484 })))
2485 }
2486
2487 "BOOLAND_AGG" | "BOOL_AND" | "LOGICAL_AND" if !f.args.is_empty() => {
2489 let arg = f.args.into_iter().next().unwrap();
2490 Ok(Expression::LogicalAnd(Box::new(AggFunc {
2491 this: arg,
2492 distinct: false,
2493 filter: None,
2494 order_by: Vec::new(),
2495 name: Some("BOOLAND_AGG".to_string()),
2496 ignore_nulls: None,
2497 having_max: None,
2498 limit: None,
2499 inferred_type: None,
2500 })))
2501 }
2502
2503 "BOOLOR_AGG" | "BOOL_OR" | "LOGICAL_OR" if !f.args.is_empty() => {
2505 let arg = f.args.into_iter().next().unwrap();
2506 Ok(Expression::LogicalOr(Box::new(AggFunc {
2507 this: arg,
2508 distinct: false,
2509 filter: None,
2510 order_by: Vec::new(),
2511 name: Some("BOOLOR_AGG".to_string()),
2512 ignore_nulls: None,
2513 having_max: None,
2514 limit: None,
2515 inferred_type: None,
2516 })))
2517 }
2518
2519 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
2521 let arg = f.args.into_iter().next().unwrap();
2522 Ok(Expression::Skewness(Box::new(AggFunc {
2523 this: arg,
2524 distinct: false,
2525 filter: None,
2526 order_by: Vec::new(),
2527 name: Some("SKEW".to_string()),
2528 ignore_nulls: None,
2529 having_max: None,
2530 limit: None,
2531 inferred_type: None,
2532 })))
2533 }
2534
2535 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2537 "VARIANCE".to_string(),
2538 f.args,
2539 )))),
2540
2541 "VAR_POP" => Ok(Expression::Function(Box::new(Function::new(
2543 "VARIANCE_POP".to_string(),
2544 f.args,
2545 )))),
2546
2547 "DATE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2549 "TO_DATE".to_string(),
2550 f.args,
2551 )))),
2552 "DATE" if f.args.len() >= 2 => {
2556 let mut args = f.args;
2557 args[1] = Self::normalize_format_arg(args[1].clone());
2558 Ok(Expression::Function(Box::new(Function::new(
2559 "TO_DATE".to_string(),
2560 args,
2561 ))))
2562 }
2563 "_POLYGLOT_DATE" if f.args.len() >= 2 => {
2566 let mut args = f.args;
2567 args[1] = Self::normalize_format_arg(args[1].clone());
2568 Ok(Expression::Function(Box::new(Function::new(
2569 "DATE".to_string(),
2570 args,
2571 ))))
2572 }
2573
2574 "DESCRIBE" => Ok(Expression::Function(Box::new(f))),
2576
2577 "MD5_HEX" => Ok(Expression::Function(Box::new(Function::new(
2579 "MD5".to_string(),
2580 f.args,
2581 )))),
2582
2583 "SHA1_HEX" => Ok(Expression::Function(Box::new(Function::new(
2585 "SHA1".to_string(),
2586 f.args,
2587 )))),
2588
2589 "SHA2_HEX" => Ok(Expression::Function(Box::new(Function::new(
2591 "SHA2".to_string(),
2592 f.args,
2593 )))),
2594
2595 "LEVENSHTEIN" => Ok(Expression::Function(Box::new(Function::new(
2597 "EDITDISTANCE".to_string(),
2598 f.args,
2599 )))),
2600
2601 "BIT_NOT" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2603 "BITNOT".to_string(),
2604 f.args,
2605 )))),
2606
2607 "BIT_AND" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2609 "BITAND".to_string(),
2610 f.args,
2611 )))),
2612
2613 "BIT_OR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2615 "BITOR".to_string(),
2616 f.args,
2617 )))),
2618
2619 "BIT_XOR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2621 "BITXOR".to_string(),
2622 f.args,
2623 )))),
2624
2625 "BIT_SHIFTLEFT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
2627 Function::new("BITSHIFTLEFT".to_string(), f.args),
2628 ))),
2629
2630 "BIT_SHIFTRIGHT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
2632 Function::new("BITSHIFTRIGHT".to_string(), f.args),
2633 ))),
2634
2635 "SYSTIMESTAMP" => Ok(Expression::Function(Box::new(Function {
2637 name: "CURRENT_TIMESTAMP".to_string(),
2638 args: f.args,
2639 distinct: false,
2640 trailing_comments: Vec::new(),
2641 use_bracket_syntax: false,
2642 no_parens: f.no_parens,
2643 quoted: false,
2644 span: None,
2645 inferred_type: None,
2646 }))),
2647
2648 "LOCALTIMESTAMP" => Ok(Expression::Function(Box::new(Function {
2650 name: "CURRENT_TIMESTAMP".to_string(),
2651 args: f.args,
2652 distinct: false,
2653 trailing_comments: Vec::new(),
2654 use_bracket_syntax: false,
2655 no_parens: f.no_parens,
2656 quoted: false,
2657 span: None,
2658 inferred_type: None,
2659 }))),
2660
2661 "SPACE" if f.args.len() == 1 => {
2663 let arg = f.args.into_iter().next().unwrap();
2664 Ok(Expression::Function(Box::new(Function::new(
2665 "REPEAT".to_string(),
2666 vec![Expression::Literal(Literal::String(" ".to_string())), arg],
2667 ))))
2668 }
2669
2670 "CEILING" => Ok(Expression::Function(Box::new(Function::new(
2672 "CEIL".to_string(),
2673 f.args,
2674 )))),
2675
2676 "LOG" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2678 "LN".to_string(),
2679 f.args,
2680 )))),
2681
2682 "REGEXP_SUBSTR_ALL" => Ok(Expression::Function(Box::new(Function::new(
2684 "REGEXP_EXTRACT_ALL".to_string(),
2685 f.args,
2686 )))),
2687
2688 "GET_PATH" if f.args.len() >= 2 => {
2692 let mut args = f.args;
2693 if let Expression::Literal(crate::expressions::Literal::String(path)) = &args[1] {
2695 let transformed = Self::transform_json_path(path);
2696 args[1] = Expression::Literal(crate::expressions::Literal::String(transformed));
2697 }
2698 Ok(Expression::Function(Box::new(Function::new(
2699 "GET_PATH".to_string(),
2700 args,
2701 ))))
2702 }
2703 "GET_PATH" => Ok(Expression::Function(Box::new(f))),
2704
2705 "FLATTEN" => Ok(Expression::Function(Box::new(f))),
2707
2708 "DATE_TRUNC" if f.args.len() >= 1 => {
2711 let mut args = f.args;
2712 let unit_name = match &args[0] {
2714 Expression::Identifier(id) => Some(id.name.as_str()),
2715 Expression::Column(col) if col.table.is_none() => Some(col.name.name.as_str()),
2716 _ => None,
2717 };
2718 if let Some(name) = unit_name {
2719 let canonical = Self::map_date_part(name).unwrap_or(name);
2720 args[0] = Expression::Literal(crate::expressions::Literal::String(
2721 canonical.to_uppercase(),
2722 ));
2723 }
2724 Ok(Expression::Function(Box::new(Function::new(
2725 "DATE_TRUNC".to_string(),
2726 args,
2727 ))))
2728 }
2729
2730 "DATE_PART" if f.args.len() >= 1 => {
2736 let mut args = f.args;
2737 let from_typed_literal = args.len() >= 2
2738 && matches!(
2739 &args[1],
2740 Expression::Literal(crate::expressions::Literal::Timestamp(_))
2741 | Expression::Literal(crate::expressions::Literal::Date(_))
2742 | Expression::Literal(crate::expressions::Literal::Time(_))
2743 | Expression::Literal(crate::expressions::Literal::Datetime(_))
2744 );
2745 if from_typed_literal {
2746 args[0] = self.transform_date_part_arg(args[0].clone());
2747 } else {
2748 args[0] = self.transform_date_part_arg_identifiers_only(args[0].clone());
2751 }
2752 Ok(Expression::Function(Box::new(Function::new(
2753 "DATE_PART".to_string(),
2754 args,
2755 ))))
2756 }
2757
2758 "OBJECT_CONSTRUCT" => Ok(Expression::Function(Box::new(f))),
2760
2761 "OBJECT_CONSTRUCT_KEEP_NULL" => Ok(Expression::Function(Box::new(f))),
2763
2764 "DESC" => Ok(Expression::Function(Box::new(Function::new(
2766 "DESCRIBE".to_string(),
2767 f.args,
2768 )))),
2769
2770 "RLIKE" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2772 "REGEXP_LIKE".to_string(),
2773 f.args,
2774 )))),
2775
2776 "TRANSFORM" => {
2781 let transformed_args: Vec<Expression> = f
2782 .args
2783 .into_iter()
2784 .map(|arg| {
2785 if let Expression::Lambda(lambda) = arg {
2786 self.transform_typed_lambda(*lambda)
2787 } else {
2788 arg
2789 }
2790 })
2791 .collect();
2792 Ok(Expression::Function(Box::new(Function::new(
2793 "TRANSFORM".to_string(),
2794 transformed_args,
2795 ))))
2796 }
2797
2798 "SEARCH" if f.args.len() >= 2 => {
2800 let mut args = f.args.into_iter();
2801 let this = Box::new(args.next().unwrap());
2802 let expression = Box::new(args.next().unwrap());
2803
2804 let mut analyzer: Option<Box<Expression>> = None;
2805 let mut search_mode: Option<Box<Expression>> = None;
2806
2807 for arg in args {
2809 if let Expression::NamedArgument(na) = &arg {
2810 let name_upper = na.name.name.to_uppercase();
2811 match name_upper.as_str() {
2812 "ANALYZER" => analyzer = Some(Box::new(arg)),
2813 "SEARCH_MODE" => search_mode = Some(Box::new(arg)),
2814 _ => {}
2815 }
2816 }
2817 }
2818
2819 Ok(Expression::Search(Box::new(crate::expressions::Search {
2820 this,
2821 expression,
2822 json_scope: None,
2823 analyzer,
2824 analyzer_options: None,
2825 search_mode,
2826 })))
2827 }
2828
2829 "CONVERT" if f.args.len() == 2 => {
2832 let value = f.args.get(0).cloned().unwrap();
2833 let type_arg = f.args.get(1).cloned().unwrap();
2834
2835 if let Expression::Column(col) = &type_arg {
2837 let type_name = col.name.name.to_uppercase();
2838 let data_type = match type_name.as_str() {
2839 "SQL_DOUBLE" => Some(DataType::Double {
2840 precision: None,
2841 scale: None,
2842 }),
2843 "SQL_VARCHAR" => Some(DataType::VarChar {
2844 length: None,
2845 parenthesized_length: false,
2846 }),
2847 "SQL_INTEGER" | "SQL_INT" => Some(DataType::Int {
2848 length: None,
2849 integer_spelling: false,
2850 }),
2851 "SQL_BIGINT" => Some(DataType::BigInt { length: None }),
2852 "SQL_SMALLINT" => Some(DataType::SmallInt { length: None }),
2853 "SQL_FLOAT" => Some(DataType::Float {
2854 precision: None,
2855 scale: None,
2856 real_spelling: false,
2857 }),
2858 "SQL_REAL" => Some(DataType::Float {
2859 precision: None,
2860 scale: None,
2861 real_spelling: true,
2862 }),
2863 "SQL_DECIMAL" => Some(DataType::Decimal {
2864 precision: None,
2865 scale: None,
2866 }),
2867 "SQL_DATE" => Some(DataType::Date),
2868 "SQL_TIME" => Some(DataType::Time {
2869 precision: None,
2870 timezone: false,
2871 }),
2872 "SQL_TIMESTAMP" => Some(DataType::Timestamp {
2873 precision: None,
2874 timezone: false,
2875 }),
2876 _ => None,
2877 };
2878
2879 if let Some(dt) = data_type {
2880 return Ok(Expression::Cast(Box::new(Cast {
2881 this: value,
2882 to: dt,
2883 double_colon_syntax: false,
2884 trailing_comments: vec![],
2885 format: None,
2886 default: None,
2887 inferred_type: None,
2888 })));
2889 }
2890 }
2891 Ok(Expression::Function(Box::new(f)))
2893 }
2894
2895 "TO_TIMESTAMP_TZ" => {
2898 if f.args.len() == 1 {
2899 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2900 {
2901 return Ok(Expression::Cast(Box::new(Cast {
2902 this: f.args.into_iter().next().unwrap(),
2903 to: DataType::Custom {
2904 name: "TIMESTAMPTZ".to_string(),
2905 },
2906 double_colon_syntax: false,
2907 trailing_comments: vec![],
2908 format: None,
2909 default: None,
2910 inferred_type: None,
2911 })));
2912 }
2913 }
2914 Ok(Expression::Function(Box::new(f)))
2915 }
2916
2917 "TO_TIMESTAMP_NTZ" => {
2919 if f.args.len() == 1 {
2920 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2921 {
2922 return Ok(Expression::Cast(Box::new(Cast {
2923 this: f.args.into_iter().next().unwrap(),
2924 to: DataType::Custom {
2925 name: "TIMESTAMPNTZ".to_string(),
2926 },
2927 double_colon_syntax: false,
2928 trailing_comments: vec![],
2929 format: None,
2930 default: None,
2931 inferred_type: None,
2932 })));
2933 }
2934 }
2935 Ok(Expression::Function(Box::new(f)))
2936 }
2937
2938 "TO_TIMESTAMP_LTZ" => {
2940 if f.args.len() == 1 {
2941 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2942 {
2943 return Ok(Expression::Cast(Box::new(Cast {
2944 this: f.args.into_iter().next().unwrap(),
2945 to: DataType::Custom {
2946 name: "TIMESTAMPLTZ".to_string(),
2947 },
2948 double_colon_syntax: false,
2949 trailing_comments: vec![],
2950 format: None,
2951 default: None,
2952 inferred_type: None,
2953 })));
2954 }
2955 }
2956 Ok(Expression::Function(Box::new(f)))
2957 }
2958
2959 "UNIFORM" => Ok(Expression::Function(Box::new(f))),
2961
2962 "REPLACE" if f.args.len() == 2 => {
2964 let mut args = f.args;
2965 args.push(Expression::Literal(crate::expressions::Literal::String(
2966 String::new(),
2967 )));
2968 Ok(Expression::Function(Box::new(Function::new(
2969 "REPLACE".to_string(),
2970 args,
2971 ))))
2972 }
2973
2974 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
2976 "ANY_VALUE".to_string(),
2977 f.args,
2978 )))),
2979
2980 "SAFE_DIVIDE" if f.args.len() == 2 => {
2982 let mut args = f.args;
2983 let x = args.remove(0);
2984 let y = args.remove(0);
2985 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2986 condition: Expression::Neq(Box::new(BinaryOp {
2987 left: y.clone(),
2988 right: Expression::number(0),
2989 left_comments: Vec::new(),
2990 operator_comments: Vec::new(),
2991 trailing_comments: Vec::new(),
2992 inferred_type: None,
2993 })),
2994 true_value: Expression::Div(Box::new(BinaryOp {
2995 left: x,
2996 right: y,
2997 left_comments: Vec::new(),
2998 operator_comments: Vec::new(),
2999 trailing_comments: Vec::new(),
3000 inferred_type: None,
3001 })),
3002 false_value: Some(Expression::Null(crate::expressions::Null)),
3003 original_name: Some("IFF".to_string()),
3004 })))
3005 }
3006
3007 "TIMESTAMP" if f.args.len() == 1 => {
3009 let arg = f.args.into_iter().next().unwrap();
3010 Ok(Expression::Cast(Box::new(Cast {
3011 this: arg,
3012 to: DataType::Custom {
3013 name: "TIMESTAMPTZ".to_string(),
3014 },
3015 trailing_comments: Vec::new(),
3016 double_colon_syntax: false,
3017 format: None,
3018 default: None,
3019 inferred_type: None,
3020 })))
3021 }
3022
3023 "TIMESTAMP" if f.args.len() == 2 => {
3025 let mut args = f.args;
3026 let value = args.remove(0);
3027 let tz = args.remove(0);
3028 Ok(Expression::Function(Box::new(Function::new(
3029 "CONVERT_TIMEZONE".to_string(),
3030 vec![
3031 tz,
3032 Expression::Cast(Box::new(Cast {
3033 this: value,
3034 to: DataType::Timestamp {
3035 precision: None,
3036 timezone: false,
3037 },
3038 trailing_comments: Vec::new(),
3039 double_colon_syntax: false,
3040 format: None,
3041 default: None,
3042 inferred_type: None,
3043 })),
3044 ],
3045 ))))
3046 }
3047
3048 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3050 "TIME_FROM_PARTS".to_string(),
3051 f.args,
3052 )))),
3053
3054 "DIV0" if f.args.len() == 2 => {
3056 let mut args = f.args;
3057 let x = args.remove(0);
3058 let y = args.remove(0);
3059 let x_expr = Self::maybe_paren(x.clone());
3061 let y_expr = Self::maybe_paren(y.clone());
3062 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3063 condition: Expression::And(Box::new(BinaryOp::new(
3064 Expression::Eq(Box::new(BinaryOp::new(
3065 y_expr.clone(),
3066 Expression::number(0),
3067 ))),
3068 Expression::Not(Box::new(crate::expressions::UnaryOp {
3069 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3070 this: x_expr.clone(),
3071 not: false,
3072 postfix_form: false,
3073 })),
3074 inferred_type: None,
3075 })),
3076 ))),
3077 true_value: Expression::number(0),
3078 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3079 original_name: Some("IFF".to_string()),
3080 })))
3081 }
3082
3083 "DIV0NULL" if f.args.len() == 2 => {
3085 let mut args = f.args;
3086 let x = args.remove(0);
3087 let y = args.remove(0);
3088 let x_expr = Self::maybe_paren(x.clone());
3089 let y_expr = Self::maybe_paren(y.clone());
3090 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3091 condition: Expression::Or(Box::new(BinaryOp::new(
3092 Expression::Eq(Box::new(BinaryOp::new(
3093 y_expr.clone(),
3094 Expression::number(0),
3095 ))),
3096 Expression::IsNull(Box::new(crate::expressions::IsNull {
3097 this: y_expr.clone(),
3098 not: false,
3099 postfix_form: false,
3100 })),
3101 ))),
3102 true_value: Expression::number(0),
3103 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3104 original_name: Some("IFF".to_string()),
3105 })))
3106 }
3107
3108 "ZEROIFNULL" if f.args.len() == 1 => {
3110 let x = f.args.into_iter().next().unwrap();
3111 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3112 condition: Expression::IsNull(Box::new(crate::expressions::IsNull {
3113 this: x.clone(),
3114 not: false,
3115 postfix_form: false,
3116 })),
3117 true_value: Expression::number(0),
3118 false_value: Some(x),
3119 original_name: Some("IFF".to_string()),
3120 })))
3121 }
3122
3123 "NULLIFZERO" if f.args.len() == 1 => {
3125 let x = f.args.into_iter().next().unwrap();
3126 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3127 condition: Expression::Eq(Box::new(BinaryOp::new(
3128 x.clone(),
3129 Expression::number(0),
3130 ))),
3131 true_value: Expression::Null(crate::expressions::Null),
3132 false_value: Some(x),
3133 original_name: Some("IFF".to_string()),
3134 })))
3135 }
3136
3137 "TRY_TO_TIME" => {
3139 if f.args.len() == 1 {
3140 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
3141 {
3142 return Ok(Expression::TryCast(Box::new(Cast {
3143 this: f.args.into_iter().next().unwrap(),
3144 to: crate::expressions::DataType::Time {
3145 precision: None,
3146 timezone: false,
3147 },
3148 double_colon_syntax: false,
3149 trailing_comments: Vec::new(),
3150 format: None,
3151 default: None,
3152 inferred_type: None,
3153 })));
3154 }
3155 }
3156 let mut args = f.args;
3158 if args.len() >= 2 {
3159 args[1] = Self::normalize_format_arg(args[1].clone());
3160 }
3161 Ok(Expression::Function(Box::new(Function::new(
3162 "TRY_TO_TIME".to_string(),
3163 args,
3164 ))))
3165 }
3166
3167 "TRY_TO_TIMESTAMP" => {
3170 if f.args.len() == 1 {
3171 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
3172 {
3173 if !Self::looks_like_epoch(s) {
3174 return Ok(Expression::TryCast(Box::new(Cast {
3175 this: f.args.into_iter().next().unwrap(),
3176 to: DataType::Timestamp {
3177 precision: None,
3178 timezone: false,
3179 },
3180 double_colon_syntax: false,
3181 trailing_comments: Vec::new(),
3182 format: None,
3183 default: None,
3184 inferred_type: None,
3185 })));
3186 }
3187 }
3188 }
3189 let mut args = f.args;
3191 if args.len() >= 2 {
3192 args[1] = Self::normalize_format_arg(args[1].clone());
3193 }
3194 Ok(Expression::Function(Box::new(Function::new(
3195 "TRY_TO_TIMESTAMP".to_string(),
3196 args,
3197 ))))
3198 }
3199
3200 "TRY_TO_DATE" => {
3202 if f.args.len() == 1 {
3203 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
3204 {
3205 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
3207 return Ok(Expression::TryCast(Box::new(Cast {
3208 this: f.args.into_iter().next().unwrap(),
3209 to: crate::expressions::DataType::Date,
3210 double_colon_syntax: false,
3211 trailing_comments: Vec::new(),
3212 format: None,
3213 default: None,
3214 inferred_type: None,
3215 })));
3216 }
3217 }
3218 }
3219 let mut args = f.args;
3221 if args.len() >= 2 {
3222 args[1] = Self::normalize_format_arg(args[1].clone());
3223 }
3224 Ok(Expression::Function(Box::new(Function::new(
3225 "TRY_TO_DATE".to_string(),
3226 args,
3227 ))))
3228 }
3229
3230 "TRY_TO_DOUBLE" => Ok(Expression::Function(Box::new(f))),
3232
3233 "REGEXP_REPLACE" if f.args.len() == 2 => {
3235 let mut args = f.args;
3236 args.push(Expression::Literal(crate::expressions::Literal::String(
3237 String::new(),
3238 )));
3239 Ok(Expression::Function(Box::new(Function::new(
3240 "REGEXP_REPLACE".to_string(),
3241 args,
3242 ))))
3243 }
3244
3245 "LAST_DAY" if f.args.len() == 2 => {
3247 let mut args = f.args;
3248 let date = args.remove(0);
3249 let unit = args.remove(0);
3250 let unit_str = match &unit {
3251 Expression::Column(c) => c.name.name.to_uppercase(),
3252 Expression::Identifier(i) => i.name.to_uppercase(),
3253 _ => String::new(),
3254 };
3255 if unit_str == "MONTH" {
3256 Ok(Expression::Function(Box::new(Function::new(
3257 "LAST_DAY".to_string(),
3258 vec![date],
3259 ))))
3260 } else {
3261 Ok(Expression::Function(Box::new(Function::new(
3262 "LAST_DAY".to_string(),
3263 vec![date, unit],
3264 ))))
3265 }
3266 }
3267
3268 "EXTRACT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
3270 "DATE_PART".to_string(),
3271 f.args,
3272 )))),
3273
3274 "ENDS_WITH" | "ENDSWITH" if f.args.len() == 2 => {
3276 let mut args = f.args;
3277 let this = args.remove(0);
3278 let expr = args.remove(0);
3279 Ok(Expression::EndsWith(Box::new(
3280 crate::expressions::BinaryFunc {
3281 original_name: None,
3282 this,
3283 expression: expr,
3284 inferred_type: None,
3285 },
3286 )))
3287 }
3288
3289 _ => Ok(Expression::Function(Box::new(f))),
3291 }
3292 }
3293
3294 fn looks_like_datetime(s: &str) -> bool {
3296 s.contains('-') || s.contains(':') || s.contains(' ') || s.contains('/')
3299 }
3300
3301 fn looks_like_epoch(s: &str) -> bool {
3303 !s.is_empty() && s.chars().all(|c| c.is_ascii_digit() || c == '.')
3304 }
3305
3306 fn maybe_paren(expr: Expression) -> Expression {
3308 match &expr {
3309 Expression::Sub(_) | Expression::Add(_) | Expression::Mul(_) | Expression::Div(_) => {
3310 Expression::Paren(Box::new(crate::expressions::Paren {
3311 this: expr,
3312 trailing_comments: Vec::new(),
3313 }))
3314 }
3315 _ => expr,
3316 }
3317 }
3318
3319 fn normalize_snowflake_format(format: &str) -> String {
3323 let mut result = String::new();
3324 let chars: Vec<char> = format.chars().collect();
3325 let mut i = 0;
3326 while i < chars.len() {
3327 if chars[i] == '"' {
3329 i += 1;
3330 while i < chars.len() && chars[i] != '"' {
3331 result.push(chars[i]);
3332 i += 1;
3333 }
3334 if i < chars.len() {
3335 i += 1; }
3337 continue;
3338 }
3339
3340 let remaining = &format[i..];
3341 let remaining_upper = remaining.to_uppercase();
3342
3343 if remaining_upper.starts_with("YYYY") {
3345 result.push_str("yyyy");
3346 i += 4;
3347 } else if remaining_upper.starts_with("YY") {
3348 result.push_str("yy");
3349 i += 2;
3350 } else if remaining_upper.starts_with("MMMM") {
3351 result.push_str("mmmm");
3352 i += 4;
3353 } else if remaining_upper.starts_with("MON") {
3354 result.push_str("mon");
3355 i += 3;
3356 } else if remaining_upper.starts_with("MM") {
3357 result.push_str("mm");
3358 i += 2;
3359 } else if remaining_upper.starts_with("DD") {
3360 result.push_str("DD");
3361 i += 2;
3362 } else if remaining_upper.starts_with("DY") {
3363 result.push_str("dy");
3364 i += 2;
3365 } else if remaining_upper.starts_with("HH24") {
3366 result.push_str("hh24");
3367 i += 4;
3368 } else if remaining_upper.starts_with("HH12") {
3369 result.push_str("hh12");
3370 i += 4;
3371 } else if remaining_upper.starts_with("HH") {
3372 result.push_str("hh");
3373 i += 2;
3374 } else if remaining_upper.starts_with("MISS") {
3375 result.push_str("miss");
3377 i += 4;
3378 } else if remaining_upper.starts_with("MI") {
3379 result.push_str("mi");
3380 i += 2;
3381 } else if remaining_upper.starts_with("SS") {
3382 result.push_str("ss");
3383 i += 2;
3384 } else if remaining_upper.starts_with("FF") {
3385 let ff_len = 2;
3387 let digit = if i + ff_len < chars.len() && chars[i + ff_len].is_ascii_digit() {
3388 let d = chars[i + ff_len];
3389 Some(d)
3390 } else {
3391 None
3392 };
3393 if let Some(d) = digit {
3394 result.push_str("ff");
3395 result.push(d);
3396 i += 3;
3397 } else {
3398 result.push_str("ff9");
3400 i += 2;
3401 }
3402 } else if remaining_upper.starts_with("AM") || remaining_upper.starts_with("PM") {
3403 result.push_str("pm");
3404 i += 2;
3405 } else if remaining_upper.starts_with("TZH") {
3406 result.push_str("tzh");
3407 i += 3;
3408 } else if remaining_upper.starts_with("TZM") {
3409 result.push_str("tzm");
3410 i += 3;
3411 } else {
3412 result.push(chars[i]);
3414 i += 1;
3415 }
3416 }
3417 result
3418 }
3419
3420 fn normalize_format_arg(expr: Expression) -> Expression {
3422 if let Expression::Literal(crate::expressions::Literal::String(s)) = &expr {
3423 let normalized = Self::normalize_snowflake_format(s);
3424 Expression::Literal(crate::expressions::Literal::String(normalized))
3425 } else {
3426 expr
3427 }
3428 }
3429
3430 fn transform_typed_lambda(&self, lambda: crate::expressions::LambdaExpr) -> Expression {
3433 use crate::expressions::{DataType, LambdaExpr};
3434 use std::collections::HashMap;
3435
3436 let mut param_types: HashMap<String, DataType> = HashMap::new();
3438 for (i, param) in lambda.parameters.iter().enumerate() {
3439 if let Some(Some(dt)) = lambda.parameter_types.get(i) {
3440 param_types.insert(param.name.to_uppercase(), dt.clone());
3441 }
3442 }
3443
3444 if param_types.is_empty() {
3446 return Expression::Lambda(Box::new(lambda));
3447 }
3448
3449 let transformed_body = self.replace_lambda_params_with_cast(lambda.body, ¶m_types);
3451
3452 Expression::Lambda(Box::new(LambdaExpr {
3454 parameters: lambda.parameters,
3455 body: transformed_body,
3456 colon: lambda.colon,
3457 parameter_types: Vec::new(), }))
3459 }
3460
3461 fn replace_lambda_params_with_cast(
3463 &self,
3464 expr: Expression,
3465 param_types: &std::collections::HashMap<String, crate::expressions::DataType>,
3466 ) -> Expression {
3467 use crate::expressions::{BinaryOp, Cast, Paren};
3468
3469 match expr {
3470 Expression::Column(col) if col.table.is_none() => {
3472 let name_upper = col.name.name.to_uppercase();
3473 if let Some(dt) = param_types.get(&name_upper) {
3474 Expression::Cast(Box::new(Cast {
3476 this: Expression::Column(col),
3477 to: dt.clone(),
3478 double_colon_syntax: false,
3479 trailing_comments: Vec::new(),
3480 format: None,
3481 default: None,
3482 inferred_type: None,
3483 }))
3484 } else {
3485 Expression::Column(col)
3486 }
3487 }
3488
3489 Expression::Identifier(id) => {
3491 let name_upper = id.name.to_uppercase();
3492 if let Some(dt) = param_types.get(&name_upper) {
3493 Expression::Cast(Box::new(Cast {
3495 this: Expression::Identifier(id),
3496 to: dt.clone(),
3497 double_colon_syntax: false,
3498 trailing_comments: Vec::new(),
3499 format: None,
3500 default: None,
3501 inferred_type: None,
3502 }))
3503 } else {
3504 Expression::Identifier(id)
3505 }
3506 }
3507
3508 Expression::Add(op) => Expression::Add(Box::new(BinaryOp::new(
3510 self.replace_lambda_params_with_cast(op.left, param_types),
3511 self.replace_lambda_params_with_cast(op.right, param_types),
3512 ))),
3513 Expression::Sub(op) => Expression::Sub(Box::new(BinaryOp::new(
3514 self.replace_lambda_params_with_cast(op.left, param_types),
3515 self.replace_lambda_params_with_cast(op.right, param_types),
3516 ))),
3517 Expression::Mul(op) => Expression::Mul(Box::new(BinaryOp::new(
3518 self.replace_lambda_params_with_cast(op.left, param_types),
3519 self.replace_lambda_params_with_cast(op.right, param_types),
3520 ))),
3521 Expression::Div(op) => Expression::Div(Box::new(BinaryOp::new(
3522 self.replace_lambda_params_with_cast(op.left, param_types),
3523 self.replace_lambda_params_with_cast(op.right, param_types),
3524 ))),
3525 Expression::Mod(op) => Expression::Mod(Box::new(BinaryOp::new(
3526 self.replace_lambda_params_with_cast(op.left, param_types),
3527 self.replace_lambda_params_with_cast(op.right, param_types),
3528 ))),
3529
3530 Expression::Paren(p) => Expression::Paren(Box::new(Paren {
3532 this: self.replace_lambda_params_with_cast(p.this, param_types),
3533 trailing_comments: p.trailing_comments,
3534 })),
3535
3536 Expression::Function(mut f) => {
3538 f.args = f
3539 .args
3540 .into_iter()
3541 .map(|arg| self.replace_lambda_params_with_cast(arg, param_types))
3542 .collect();
3543 Expression::Function(f)
3544 }
3545
3546 Expression::Eq(op) => Expression::Eq(Box::new(BinaryOp::new(
3548 self.replace_lambda_params_with_cast(op.left, param_types),
3549 self.replace_lambda_params_with_cast(op.right, param_types),
3550 ))),
3551 Expression::Neq(op) => Expression::Neq(Box::new(BinaryOp::new(
3552 self.replace_lambda_params_with_cast(op.left, param_types),
3553 self.replace_lambda_params_with_cast(op.right, param_types),
3554 ))),
3555 Expression::Lt(op) => Expression::Lt(Box::new(BinaryOp::new(
3556 self.replace_lambda_params_with_cast(op.left, param_types),
3557 self.replace_lambda_params_with_cast(op.right, param_types),
3558 ))),
3559 Expression::Lte(op) => Expression::Lte(Box::new(BinaryOp::new(
3560 self.replace_lambda_params_with_cast(op.left, param_types),
3561 self.replace_lambda_params_with_cast(op.right, param_types),
3562 ))),
3563 Expression::Gt(op) => Expression::Gt(Box::new(BinaryOp::new(
3564 self.replace_lambda_params_with_cast(op.left, param_types),
3565 self.replace_lambda_params_with_cast(op.right, param_types),
3566 ))),
3567 Expression::Gte(op) => Expression::Gte(Box::new(BinaryOp::new(
3568 self.replace_lambda_params_with_cast(op.left, param_types),
3569 self.replace_lambda_params_with_cast(op.right, param_types),
3570 ))),
3571
3572 Expression::And(op) => Expression::And(Box::new(BinaryOp::new(
3574 self.replace_lambda_params_with_cast(op.left, param_types),
3575 self.replace_lambda_params_with_cast(op.right, param_types),
3576 ))),
3577 Expression::Or(op) => Expression::Or(Box::new(BinaryOp::new(
3578 self.replace_lambda_params_with_cast(op.left, param_types),
3579 self.replace_lambda_params_with_cast(op.right, param_types),
3580 ))),
3581
3582 other => other,
3584 }
3585 }
3586
3587 fn transform_aggregate_function(
3588 &self,
3589 f: Box<crate::expressions::AggregateFunction>,
3590 ) -> Result<Expression> {
3591 let name_upper = f.name.to_uppercase();
3592 match name_upper.as_str() {
3593 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3595 Function::new("LISTAGG".to_string(), f.args),
3596 ))),
3597
3598 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3600 Function::new("LISTAGG".to_string(), f.args),
3601 ))),
3602
3603 "APPROX_DISTINCT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3605 Function::new("APPROX_COUNT_DISTINCT".to_string(), f.args),
3606 ))),
3607
3608 "BIT_AND" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3610 "BITAND_AGG".to_string(),
3611 f.args,
3612 )))),
3613
3614 "BIT_OR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3616 "BITOR_AGG".to_string(),
3617 f.args,
3618 )))),
3619
3620 "BIT_XOR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3622 "BITXOR_AGG".to_string(),
3623 f.args,
3624 )))),
3625
3626 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" if !f.args.is_empty() => {
3628 let arg = f.args.into_iter().next().unwrap();
3629 Ok(Expression::LogicalAnd(Box::new(AggFunc {
3630 this: arg,
3631 distinct: f.distinct,
3632 filter: f.filter,
3633 order_by: Vec::new(),
3634 name: Some("BOOLAND_AGG".to_string()),
3635 ignore_nulls: None,
3636 having_max: None,
3637 limit: None,
3638 inferred_type: None,
3639 })))
3640 }
3641
3642 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if !f.args.is_empty() => {
3644 let arg = f.args.into_iter().next().unwrap();
3645 Ok(Expression::LogicalOr(Box::new(AggFunc {
3646 this: arg,
3647 distinct: f.distinct,
3648 filter: f.filter,
3649 order_by: Vec::new(),
3650 name: Some("BOOLOR_AGG".to_string()),
3651 ignore_nulls: None,
3652 having_max: None,
3653 limit: None,
3654 inferred_type: None,
3655 })))
3656 }
3657
3658 "APPROX_TOP_K" if f.args.len() == 1 => {
3660 let mut args = f.args;
3661 args.push(Expression::number(1));
3662 Ok(Expression::AggregateFunction(Box::new(
3663 crate::expressions::AggregateFunction {
3664 name: "APPROX_TOP_K".to_string(),
3665 args,
3666 distinct: f.distinct,
3667 filter: f.filter,
3668 order_by: Vec::new(),
3669 limit: None,
3670 ignore_nulls: None,
3671 inferred_type: None,
3672 },
3673 )))
3674 }
3675
3676 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
3678 let arg = f.args.into_iter().next().unwrap();
3679 Ok(Expression::Skewness(Box::new(AggFunc {
3680 this: arg,
3681 distinct: f.distinct,
3682 filter: f.filter,
3683 order_by: Vec::new(),
3684 name: Some("SKEW".to_string()),
3685 ignore_nulls: None,
3686 having_max: None,
3687 limit: None,
3688 inferred_type: None,
3689 })))
3690 }
3691
3692 _ => Ok(Expression::AggregateFunction(f)),
3694 }
3695 }
3696}
3697
3698fn strftime_to_snowflake_format(fmt: &str) -> String {
3700 let mut result = String::new();
3701 let chars: Vec<char> = fmt.chars().collect();
3702 let mut i = 0;
3703 while i < chars.len() {
3704 if chars[i] == '%' && i + 1 < chars.len() {
3705 match chars[i + 1] {
3706 'Y' => {
3707 result.push_str("yyyy");
3708 i += 2;
3709 }
3710 'y' => {
3711 result.push_str("yy");
3712 i += 2;
3713 }
3714 'm' => {
3715 result.push_str("mm");
3716 i += 2;
3717 }
3718 'd' => {
3719 result.push_str("DD");
3720 i += 2;
3721 }
3722 'H' => {
3723 result.push_str("hh24");
3724 i += 2;
3725 }
3726 'M' => {
3727 result.push_str("mmmm");
3728 i += 2;
3729 } 'i' => {
3731 result.push_str("mi");
3732 i += 2;
3733 }
3734 'S' | 's' => {
3735 result.push_str("ss");
3736 i += 2;
3737 }
3738 'f' => {
3739 result.push_str("ff");
3740 i += 2;
3741 }
3742 'w' => {
3743 result.push_str("dy");
3744 i += 2;
3745 } 'a' => {
3747 result.push_str("DY");
3748 i += 2;
3749 } 'b' => {
3751 result.push_str("mon");
3752 i += 2;
3753 } 'T' => {
3755 result.push_str("hh24:mi:ss");
3756 i += 2;
3757 } _ => {
3759 result.push(chars[i]);
3760 result.push(chars[i + 1]);
3761 i += 2;
3762 }
3763 }
3764 } else {
3765 result.push(chars[i]);
3766 i += 1;
3767 }
3768 }
3769 result
3770}
3771
3772#[cfg(test)]
3773mod tests {
3774 use super::*;
3775 use crate::dialects::Dialect;
3776
3777 fn transpile_to_snowflake(sql: &str) -> String {
3778 let dialect = Dialect::get(DialectType::Generic);
3779 let result = dialect
3780 .transpile_to(sql, DialectType::Snowflake)
3781 .expect("Transpile failed");
3782 result[0].clone()
3783 }
3784
3785 #[test]
3786 fn test_ifnull_to_coalesce() {
3787 let result = transpile_to_snowflake("SELECT IFNULL(a, b)");
3788 assert!(
3789 result.contains("COALESCE"),
3790 "Expected COALESCE, got: {}",
3791 result
3792 );
3793 }
3794
3795 #[test]
3796 fn test_basic_select() {
3797 let result = transpile_to_snowflake("SELECT a, b FROM users WHERE id = 1");
3798 assert!(result.contains("SELECT"));
3799 assert!(result.contains("FROM users"));
3800 }
3801
3802 #[test]
3803 fn test_group_concat_to_listagg() {
3804 let result = transpile_to_snowflake("SELECT GROUP_CONCAT(name)");
3805 assert!(
3806 result.contains("LISTAGG"),
3807 "Expected LISTAGG, got: {}",
3808 result
3809 );
3810 }
3811
3812 #[test]
3813 fn test_string_agg_to_listagg() {
3814 let result = transpile_to_snowflake("SELECT STRING_AGG(name)");
3815 assert!(
3816 result.contains("LISTAGG"),
3817 "Expected LISTAGG, got: {}",
3818 result
3819 );
3820 }
3821
3822 #[test]
3823 fn test_array_to_array_construct() {
3824 let result = transpile_to_snowflake("SELECT ARRAY(1, 2, 3)");
3825 assert!(
3826 result.contains("ARRAY_CONSTRUCT"),
3827 "Expected ARRAY_CONSTRUCT, got: {}",
3828 result
3829 );
3830 }
3831
3832 #[test]
3833 fn test_double_quote_identifiers() {
3834 let dialect = SnowflakeDialect;
3836 let config = dialect.generator_config();
3837 assert_eq!(config.identifier_quote, '"');
3838 }
3839}