1use super::{DialectImpl, DialectType};
13use crate::error::Result;
14use crate::expressions::{AggFunc, BinaryOp, Cast, CeilFunc, DataType, Expression, Function, IntervalUnit, ListAggFunc, Literal, UnaryFunc, VarArgFunc};
15use crate::generator::GeneratorConfig;
16use crate::tokens::TokenizerConfig;
17
18fn interval_unit_to_str(unit: &IntervalUnit) -> String {
20 match unit {
21 IntervalUnit::Year => "YEAR".to_string(),
22 IntervalUnit::Quarter => "QUARTER".to_string(),
23 IntervalUnit::Month => "MONTH".to_string(),
24 IntervalUnit::Week => "WEEK".to_string(),
25 IntervalUnit::Day => "DAY".to_string(),
26 IntervalUnit::Hour => "HOUR".to_string(),
27 IntervalUnit::Minute => "MINUTE".to_string(),
28 IntervalUnit::Second => "SECOND".to_string(),
29 IntervalUnit::Millisecond => "MILLISECOND".to_string(),
30 IntervalUnit::Microsecond => "MICROSECOND".to_string(),
31 }
32}
33
34pub struct SnowflakeDialect;
36
37impl DialectImpl for SnowflakeDialect {
38 fn dialect_type(&self) -> DialectType {
39 DialectType::Snowflake
40 }
41
42 fn tokenizer_config(&self) -> TokenizerConfig {
43 let mut config = TokenizerConfig::default();
44 config.identifiers.insert('"', '"');
46 config.quotes.insert("$$".to_string(), "$$".to_string());
48 config.nested_comments = false;
50 config
51 }
52
53 fn generator_config(&self) -> GeneratorConfig {
54 use crate::generator::IdentifierQuoteStyle;
55 GeneratorConfig {
56 identifier_quote: '"',
57 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
58 dialect: Some(DialectType::Snowflake),
59 parameter_token: "$",
61 matched_by_source: false,
62 single_string_interval: true,
63 join_hints: false,
64 table_hints: false,
65 query_hints: false,
66 aggregate_filter_supported: false,
67 supports_table_copy: false,
68 collate_is_func: true,
69 limit_only_literals: true,
70 json_key_value_pair_sep: ",",
71 insert_overwrite: " OVERWRITE INTO",
72 struct_delimiter: ("(", ")"),
73 copy_params_are_wrapped: false,
74 copy_params_eq_required: true,
75 star_except: "EXCLUDE",
76 supports_exploding_projections: false,
77 array_concat_is_var_len: false,
78 supports_convert_timezone: true,
79 except_intersect_support_all_clause: false,
80 supports_median: true,
81 array_size_name: "ARRAY_SIZE",
82 supports_decode_case: true,
83 is_bool_allowed: false,
84 try_supported: true,
86 nvl2_supported: true,
88 unnest_with_ordinality: false,
90 ..Default::default()
91 }
92 }
93
94 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
95 match expr {
96 Expression::DataType(dt) => self.transform_data_type(dt),
98
99 Expression::In(in_expr) if in_expr.not && in_expr.query.is_some() => {
103 let subquery = in_expr.query.unwrap();
105 Ok(Expression::All(Box::new(crate::expressions::QuantifiedExpr {
106 this: in_expr.this,
107 subquery,
108 op: Some(crate::expressions::QuantifiedOp::Neq),
109 })))
110 }
111
112 Expression::In(in_expr) if in_expr.not => {
114 let in_without_not = crate::expressions::In {
116 this: in_expr.this,
117 expressions: in_expr.expressions,
118 query: in_expr.query,
119 not: false,
120 global: in_expr.global,
121 unnest: in_expr.unnest,
122 };
123 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
124 this: Expression::In(Box::new(in_without_not)),
125 })))
126 }
127
128 Expression::Interval(interval) => {
131 self.transform_interval(*interval)
132 }
133
134 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
137 expressions: vec![f.this, f.expression],
138 }))),
139
140 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
142 expressions: vec![f.this, f.expression],
143 }))),
144
145 Expression::Coalesce(mut f) => {
147 f.original_name = None;
148 Ok(Expression::Coalesce(f))
149 }
150
151 Expression::GroupConcat(f) => Ok(Expression::ListAgg(Box::new(ListAggFunc {
153 this: f.this,
154 separator: f.separator,
155 on_overflow: None,
156 order_by: f.order_by,
157 distinct: f.distinct,
158 filter: f.filter,
159 }))),
160
161 Expression::Cast(c) => {
165 use crate::expressions::DataType;
166 let transformed_this = self.transform_expr(c.this)?;
168 match &c.to {
169 DataType::Geography { .. } => {
170 Ok(Expression::Function(Box::new(Function::new(
171 "TO_GEOGRAPHY".to_string(),
172 vec![transformed_this],
173 ))))
174 }
175 DataType::Geometry { .. } => {
176 Ok(Expression::Function(Box::new(Function::new(
177 "TO_GEOMETRY".to_string(),
178 vec![transformed_this],
179 ))))
180 }
181 _ => {
182 let transformed_dt = match self.transform_data_type(c.to.clone())? {
184 Expression::DataType(dt) => dt,
185 _ => c.to.clone(),
186 };
187 Ok(Expression::Cast(Box::new(Cast {
188 this: transformed_this,
189 to: transformed_dt,
190 double_colon_syntax: false, trailing_comments: c.trailing_comments,
192 format: c.format,
193 default: c.default,
194 })))
195 }
196 }
197 }
198
199 Expression::TryCast(c) => {
202 let transformed_this = self.transform_expr(c.this)?;
203 Ok(Expression::TryCast(Box::new(Cast {
204 this: transformed_this,
205 to: c.to,
206 double_colon_syntax: false, trailing_comments: c.trailing_comments,
208 format: c.format,
209 default: c.default,
210 })))
211 }
212
213 Expression::SafeCast(c) => {
216 let to = match c.to {
217 DataType::Timestamp { .. } => DataType::Custom { name: "TIMESTAMPTZ".to_string() },
218 DataType::Custom { name } if name.eq_ignore_ascii_case("TIMESTAMP") => {
219 DataType::Custom { name: "TIMESTAMPTZ".to_string() }
220 }
221 other => other,
222 };
223 let transformed_this = self.transform_expr(c.this)?;
224 Ok(Expression::Cast(Box::new(Cast {
225 this: transformed_this,
226 to,
227 double_colon_syntax: c.double_colon_syntax,
228 trailing_comments: c.trailing_comments,
229 format: c.format,
230 default: c.default,
231 })))
232 }
233
234 Expression::Literal(Literal::Timestamp(s)) => {
237 Ok(Expression::Cast(Box::new(Cast {
238 this: Expression::Literal(Literal::String(s)),
239 to: DataType::Timestamp { precision: None, timezone: false },
240 double_colon_syntax: false,
241 trailing_comments: Vec::new(),
242 format: None,
243 default: None,
244 })))
245 }
246
247 Expression::Literal(Literal::Date(s)) => {
249 Ok(Expression::Cast(Box::new(Cast {
250 this: Expression::Literal(Literal::String(s)),
251 to: DataType::Date,
252 double_colon_syntax: false,
253 trailing_comments: Vec::new(),
254 format: None,
255 default: None,
256 })))
257 }
258
259 Expression::Literal(Literal::Time(s)) => {
261 Ok(Expression::Cast(Box::new(Cast {
262 this: Expression::Literal(Literal::String(s)),
263 to: DataType::Time { precision: None, timezone: false },
264 double_colon_syntax: false,
265 trailing_comments: Vec::new(),
266 format: None,
267 default: None,
268 })))
269 }
270
271 Expression::Literal(Literal::Datetime(s)) => {
273 Ok(Expression::Cast(Box::new(Cast {
274 this: Expression::Literal(Literal::String(s)),
275 to: DataType::Custom { name: "DATETIME".to_string() },
276 double_colon_syntax: false,
277 trailing_comments: Vec::new(),
278 format: None,
279 default: None,
280 })))
281 }
282
283 Expression::ILike(op) => Ok(Expression::ILike(op)),
286
287 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
290 "FLATTEN".to_string(),
291 vec![f.this],
292 )))),
293
294 Expression::ExplodeOuter(f) => Ok(Expression::Function(Box::new(Function::new(
296 "FLATTEN".to_string(),
297 vec![f.this],
298 )))),
299
300 Expression::Unnest(f) => {
302 let input_arg = Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
304 name: crate::expressions::Identifier::new("INPUT"),
305 value: f.this,
306 separator: crate::expressions::NamedArgSeparator::DArrow,
307 }));
308
309 let flatten = Expression::Function(Box::new(Function::new(
311 "FLATTEN".to_string(),
312 vec![input_arg],
313 )));
314
315 let table_func = Expression::TableFromRows(Box::new(crate::expressions::TableFromRows {
317 this: Box::new(flatten),
318 alias: None,
319 joins: vec![],
320 pivots: None,
321 sample: None,
322 }));
323
324 Ok(Expression::Alias(Box::new(crate::expressions::Alias {
326 this: table_func,
327 alias: crate::expressions::Identifier::new("_t0"),
328 column_aliases: vec![
329 crate::expressions::Identifier::new("seq"),
330 crate::expressions::Identifier::new("key"),
331 crate::expressions::Identifier::new("path"),
332 crate::expressions::Identifier::new("index"),
333 crate::expressions::Identifier::new("value"),
334 crate::expressions::Identifier::new("this"),
335 ],
336 pre_alias_comments: vec![],
337 trailing_comments: vec![],
338 })))
339 }
340
341 Expression::ArrayFunc(arr) => {
345 if arr.bracket_notation {
346 Ok(Expression::ArrayFunc(arr))
348 } else {
349 Ok(Expression::Function(Box::new(Function::new(
351 "ARRAY_CONSTRUCT".to_string(),
352 arr.expressions,
353 ))))
354 }
355 }
356
357 Expression::ArrayConcat(f) => Ok(Expression::Function(Box::new(Function::new(
359 "ARRAY_CAT".to_string(),
360 f.expressions,
361 )))),
362
363 Expression::ArrayConcatAgg(f) => Ok(Expression::Function(Box::new(Function::new(
365 "ARRAY_FLATTEN".to_string(),
366 vec![f.this],
367 )))),
368
369 Expression::ArrayContains(f) => Ok(Expression::Function(Box::new(Function::new(
371 "ARRAY_CONTAINS".to_string(),
372 vec![f.this, f.expression],
373 )))),
374
375 Expression::ArrayIntersect(f) => Ok(Expression::Function(Box::new(Function::new(
377 "ARRAY_INTERSECTION".to_string(),
378 vec![f.this, f.expression],
379 )))),
380
381 Expression::ArraySort(f) => Ok(Expression::Function(Box::new(Function::new(
383 "ARRAY_SORT".to_string(),
384 vec![f.this],
385 )))),
386
387 Expression::StringToArray(f) => {
389 let mut args = vec![*f.this];
390 if let Some(expr) = f.expression {
391 args.push(*expr);
392 }
393 Ok(Expression::Function(Box::new(Function::new(
394 "STRTOK_TO_ARRAY".to_string(),
395 args,
396 ))))
397 }
398
399 Expression::BitwiseOr(f) => Ok(Expression::Function(Box::new(Function::new(
402 "BITOR".to_string(),
403 vec![f.left, f.right],
404 )))),
405
406 Expression::BitwiseXor(f) => Ok(Expression::Function(Box::new(Function::new(
408 "BITXOR".to_string(),
409 vec![f.left, f.right],
410 )))),
411
412 Expression::BitwiseAnd(f) => Ok(Expression::Function(Box::new(Function::new(
414 "BITAND".to_string(),
415 vec![f.left, f.right],
416 )))),
417
418 Expression::BitwiseNot(f) => Ok(Expression::Function(Box::new(Function::new(
420 "BITNOT".to_string(),
421 vec![f.this],
422 )))),
423
424 Expression::BitwiseLeftShift(f) => Ok(Expression::Function(Box::new(Function::new(
426 "BITSHIFTLEFT".to_string(),
427 vec![f.left, f.right],
428 )))),
429
430 Expression::BitwiseRightShift(f) => Ok(Expression::Function(Box::new(Function::new(
432 "BITSHIFTRIGHT".to_string(),
433 vec![f.left, f.right],
434 )))),
435
436 Expression::BitwiseAndAgg(f) => Ok(Expression::Function(Box::new(Function::new(
438 "BITAND_AGG".to_string(),
439 vec![f.this],
440 )))),
441
442 Expression::BitwiseOrAgg(f) => Ok(Expression::Function(Box::new(Function::new(
444 "BITOR_AGG".to_string(),
445 vec![f.this],
446 )))),
447
448 Expression::BitwiseXorAgg(f) => Ok(Expression::Function(Box::new(Function::new(
450 "BITXOR_AGG".to_string(),
451 vec![f.this],
452 )))),
453
454 Expression::LogicalAnd(f) => Ok(Expression::Function(Box::new(Function::new(
457 "BOOLAND_AGG".to_string(),
458 vec![f.this],
459 )))),
460
461 Expression::LogicalOr(f) => Ok(Expression::Function(Box::new(Function::new(
463 "BOOLOR_AGG".to_string(),
464 vec![f.this],
465 )))),
466
467 Expression::Booland(f) => Ok(Expression::Function(Box::new(Function::new(
469 "BOOLAND".to_string(),
470 vec![*f.this, *f.expression],
471 )))),
472
473 Expression::Boolor(f) => Ok(Expression::Function(Box::new(Function::new(
475 "BOOLOR".to_string(),
476 vec![*f.this, *f.expression],
477 )))),
478
479 Expression::Xor(f) => {
481 let mut args = Vec::new();
482 if let Some(this) = f.this {
483 args.push(*this);
484 }
485 if let Some(expr) = f.expression {
486 args.push(*expr);
487 }
488 Ok(Expression::Function(Box::new(Function::new(
489 "BOOLXOR".to_string(),
490 args,
491 ))))
492 }
493
494 Expression::DayOfMonth(f) => Ok(Expression::Function(Box::new(Function::new(
497 "DAYOFMONTH".to_string(),
498 vec![f.this],
499 )))),
500
501 Expression::DayOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
503 "DAYOFWEEK".to_string(),
504 vec![f.this],
505 )))),
506
507 Expression::DayOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
509 "DAYOFWEEKISO".to_string(),
510 vec![f.this],
511 )))),
512
513 Expression::DayOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
515 "DAYOFYEAR".to_string(),
516 vec![f.this],
517 )))),
518
519 Expression::WeekOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
521 "WEEK".to_string(),
522 vec![f.this],
523 )))),
524
525 Expression::YearOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
527 "YEAROFWEEK".to_string(),
528 vec![f.this],
529 )))),
530
531 Expression::YearOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
533 "YEAROFWEEKISO".to_string(),
534 vec![f.this],
535 )))),
536
537 Expression::ByteLength(f) => Ok(Expression::Function(Box::new(Function::new(
539 "OCTET_LENGTH".to_string(),
540 vec![f.this],
541 )))),
542
543 Expression::TimestampDiff(f) => {
545 let mut args = vec![];
546 if let Some(ref unit_str) = f.unit {
548 args.push(Expression::Identifier(crate::expressions::Identifier::new(unit_str.clone())));
549 args.push(*f.this);
550 args.push(*f.expression);
551 } else {
552 args.push(*f.this);
553 args.push(*f.expression);
554 }
555 Ok(Expression::Function(Box::new(Function::new(
556 "TIMESTAMPDIFF".to_string(),
557 args,
558 ))))
559 }
560
561 Expression::TimestampAdd(f) => {
563 let mut args = vec![];
564 if let Some(ref unit_str) = f.unit {
565 args.push(Expression::Identifier(crate::expressions::Identifier::new(unit_str.clone())));
566 args.push(*f.this);
567 args.push(*f.expression);
568 } else {
569 args.push(*f.this);
570 args.push(*f.expression);
571 }
572 Ok(Expression::Function(Box::new(Function::new(
573 "TIMESTAMPADD".to_string(),
574 args,
575 ))))
576 }
577
578 Expression::ToArray(f) => Ok(Expression::Function(Box::new(Function::new(
580 "TO_ARRAY".to_string(),
581 vec![f.this],
582 )))),
583
584 Expression::DateAdd(f) => {
586 let unit_str = interval_unit_to_str(&f.unit);
587 let unit = Expression::Identifier(crate::expressions::Identifier {
588 name: unit_str,
589 quoted: false,
590 trailing_comments: Vec::new(),
591 });
592 Ok(Expression::Function(Box::new(Function::new(
593 "DATEADD".to_string(),
594 vec![unit, f.interval, f.this],
595 ))))
596 }
597
598 Expression::DateSub(f) => {
600 let unit_str = interval_unit_to_str(&f.unit);
601 let unit = Expression::Identifier(crate::expressions::Identifier {
602 name: unit_str,
603 quoted: false,
604 trailing_comments: Vec::new(),
605 });
606 let neg_expr = Expression::Mul(Box::new(crate::expressions::BinaryOp::new(
608 f.interval,
609 Expression::Neg(Box::new(crate::expressions::UnaryOp { this: Expression::number(1) })),
610 )));
611 Ok(Expression::Function(Box::new(Function::new(
612 "DATEADD".to_string(),
613 vec![unit, neg_expr, f.this],
614 ))))
615 }
616
617 Expression::DateDiff(f) => {
619 let unit_str = interval_unit_to_str(&f.unit.unwrap_or(crate::expressions::IntervalUnit::Day));
620 let unit = Expression::Identifier(crate::expressions::Identifier {
621 name: unit_str,
622 quoted: false,
623 trailing_comments: Vec::new(),
624 });
625 Ok(Expression::Function(Box::new(Function::new(
626 "DATEDIFF".to_string(),
627 vec![unit, f.expression, f.this],
628 ))))
629 }
630
631 Expression::StringAgg(f) => {
634 let mut args = vec![f.this.clone()];
635 if let Some(separator) = &f.separator {
636 args.push(separator.clone());
637 }
638 Ok(Expression::Function(Box::new(Function::new(
639 "LISTAGG".to_string(),
640 args,
641 ))))
642 }
643
644 Expression::StartsWith(f) => Ok(Expression::Function(Box::new(Function::new(
646 "STARTSWITH".to_string(),
647 vec![f.this, f.expression],
648 )))),
649
650 Expression::EndsWith(f) => Ok(Expression::EndsWith(f)),
652
653 Expression::Stuff(f) => {
655 let mut args = vec![*f.this];
656 if let Some(start) = f.start {
657 args.push(*start);
658 }
659 if let Some(length) = f.length {
660 args.push(Expression::number(length));
661 }
662 args.push(*f.expression);
663 Ok(Expression::Function(Box::new(Function::new(
664 "INSERT".to_string(),
665 args,
666 ))))
667 }
668
669 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
672 "SHA1".to_string(),
673 vec![f.this],
674 )))),
675
676 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
678 "SHA1_BINARY".to_string(),
679 vec![f.this],
680 )))),
681
682 Expression::SHA2Digest(f) => Ok(Expression::Function(Box::new(Function::new(
684 "SHA2_BINARY".to_string(),
685 vec![*f.this],
686 )))),
687
688 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
690 "MD5_BINARY".to_string(),
691 vec![*f.this],
692 )))),
693
694 Expression::MD5NumberLower64(f) => Ok(Expression::Function(Box::new(Function::new(
696 "MD5_NUMBER_LOWER64".to_string(),
697 vec![f.this],
698 )))),
699
700 Expression::MD5NumberUpper64(f) => Ok(Expression::Function(Box::new(Function::new(
702 "MD5_NUMBER_UPPER64".to_string(),
703 vec![f.this],
704 )))),
705
706 Expression::CosineDistance(f) => Ok(Expression::Function(Box::new(Function::new(
709 "VECTOR_COSINE_SIMILARITY".to_string(),
710 vec![*f.this, *f.expression],
711 )))),
712
713 Expression::DotProduct(f) => Ok(Expression::Function(Box::new(Function::new(
715 "VECTOR_INNER_PRODUCT".to_string(),
716 vec![*f.this, *f.expression],
717 )))),
718
719 Expression::EuclideanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
721 "VECTOR_L2_DISTANCE".to_string(),
722 vec![*f.this, *f.expression],
723 )))),
724
725 Expression::ManhattanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
727 "VECTOR_L1_DISTANCE".to_string(),
728 vec![*f.this, *f.expression],
729 )))),
730
731 Expression::JSONFormat(f) => {
734 let mut args = Vec::new();
735 if let Some(this) = f.this {
736 args.push(*this);
737 }
738 Ok(Expression::Function(Box::new(Function::new(
739 "TO_JSON".to_string(),
740 args,
741 ))))
742 }
743
744 Expression::JSONKeys(f) => Ok(Expression::Function(Box::new(Function::new(
746 "OBJECT_KEYS".to_string(),
747 vec![*f.this],
748 )))),
749
750 Expression::GetExtract(f) => Ok(Expression::Function(Box::new(Function::new(
752 "GET".to_string(),
753 vec![*f.this, *f.expression],
754 )))),
755
756 Expression::StarMap(f) => Ok(Expression::Function(Box::new(Function::new(
758 "OBJECT_CONSTRUCT".to_string(),
759 vec![f.this, f.expression],
760 )))),
761
762 Expression::LowerHex(f) => Ok(Expression::Function(Box::new(Function::new(
764 "TO_CHAR".to_string(),
765 vec![f.this],
766 )))),
767
768 Expression::Skewness(f) => Ok(Expression::Function(Box::new(Function::new(
770 "SKEW".to_string(),
771 vec![f.this],
772 )))),
773
774 Expression::StPoint(f) => Ok(Expression::Function(Box::new(Function::new(
776 "ST_MAKEPOINT".to_string(),
777 vec![*f.this, *f.expression],
778 )))),
779
780 Expression::FromTimeZone(f) => Ok(Expression::Function(Box::new(Function::new(
782 "CONVERT_TIMEZONE".to_string(),
783 vec![*f.this],
784 )))),
785
786 Expression::Unhex(f) => Ok(Expression::Function(Box::new(Function::new(
789 "HEX_DECODE_BINARY".to_string(),
790 vec![*f.this],
791 )))),
792
793 Expression::UnixToTime(f) => {
795 let mut args = vec![*f.this];
796 if let Some(scale) = f.scale {
797 args.push(Expression::number(scale));
798 }
799 Ok(Expression::Function(Box::new(Function::new(
800 "TO_TIMESTAMP".to_string(),
801 args,
802 ))))
803 }
804
805 Expression::IfFunc(f) => {
808 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
809 condition: f.condition,
810 true_value: f.true_value,
811 false_value: Some(f.false_value.unwrap_or(Expression::Null(crate::expressions::Null))),
812 original_name: Some("IFF".to_string()),
813 })))
814 }
815
816 Expression::ApproxDistinct(f) => Ok(Expression::Function(Box::new(Function::new(
819 "APPROX_COUNT_DISTINCT".to_string(),
820 vec![f.this],
821 )))),
822
823 Expression::ArgMax(f) => Ok(Expression::Function(Box::new(Function::new(
825 "MAX_BY".to_string(),
826 vec![*f.this, *f.expression],
827 )))),
828
829 Expression::ArgMin(f) => Ok(Expression::Function(Box::new(Function::new(
831 "MIN_BY".to_string(),
832 vec![*f.this, *f.expression],
833 )))),
834
835 Expression::Random(_) => Ok(Expression::Random(crate::expressions::Random)),
838
839 Expression::Rand(r) => Ok(Expression::Rand(r)),
841
842 Expression::Uuid(u) => Ok(Expression::Uuid(u)),
845
846 Expression::Map(f) => Ok(Expression::Function(Box::new(Function::new(
849 "OBJECT_CONSTRUCT".to_string(),
850 f.keys
851 .into_iter()
852 .zip(f.values.into_iter())
853 .flat_map(|(k, v)| vec![k, v])
854 .collect(),
855 )))),
856
857 Expression::MapFunc(f) => Ok(Expression::Function(Box::new(Function::new(
859 "OBJECT_CONSTRUCT".to_string(),
860 f.keys
861 .into_iter()
862 .zip(f.values.into_iter())
863 .flat_map(|(k, v)| vec![k, v])
864 .collect(),
865 )))),
866
867 Expression::VarMap(f) => Ok(Expression::Function(Box::new(Function::new(
869 "OBJECT_CONSTRUCT".to_string(),
870 f.keys
871 .into_iter()
872 .zip(f.values.into_iter())
873 .flat_map(|(k, v)| vec![k, v])
874 .collect(),
875 )))),
876
877 Expression::JsonObject(f) => Ok(Expression::Function(Box::new(Function::new(
880 "OBJECT_CONSTRUCT_KEEP_NULL".to_string(),
881 f.pairs.into_iter().flat_map(|(k, v)| vec![k, v]).collect(),
882 )))),
883
884 Expression::JsonExtractScalar(f) => Ok(Expression::Function(Box::new(Function::new(
886 "JSON_EXTRACT_PATH_TEXT".to_string(),
887 vec![f.this, f.path],
888 )))),
889
890 Expression::Struct(f) => Ok(Expression::Function(Box::new(Function::new(
893 "OBJECT_CONSTRUCT".to_string(),
894 f.fields
895 .into_iter()
896 .flat_map(|(name, expr)| {
897 let key = match name {
898 Some(n) => Expression::string(n),
899 None => Expression::Null(crate::expressions::Null),
900 };
901 vec![key, expr]
902 })
903 .collect(),
904 )))),
905
906 Expression::JSONPathRoot(_) => Ok(Expression::Literal(crate::expressions::Literal::String(
909 String::new(),
910 ))),
911
912 Expression::VarSamp(agg) => {
915 Ok(Expression::Variance(agg))
916 }
917
918 Expression::VarPop(agg) => Ok(Expression::VarPop(agg)),
921
922 Expression::Extract(f) => {
925 use crate::expressions::DateTimeField;
926 let transformed_this = self.transform_expr(f.this)?;
928 let field_name = match &f.field {
929 DateTimeField::Year => "YEAR",
930 DateTimeField::Month => "MONTH",
931 DateTimeField::Day => "DAY",
932 DateTimeField::Hour => "HOUR",
933 DateTimeField::Minute => "MINUTE",
934 DateTimeField::Second => "SECOND",
935 DateTimeField::Millisecond => "MILLISECOND",
936 DateTimeField::Microsecond => "MICROSECOND",
937 DateTimeField::Week => "WEEK",
938 DateTimeField::WeekWithModifier(m) => return Ok(Expression::Function(Box::new(Function::new(
939 "DATE_PART".to_string(),
940 vec![
941 Expression::Identifier(crate::expressions::Identifier {
942 name: format!("WEEK({})", m),
943 quoted: false,
944 trailing_comments: Vec::new(),
945 }),
946 transformed_this,
947 ],
948 )))),
949 DateTimeField::DayOfWeek => "DAYOFWEEK",
950 DateTimeField::DayOfYear => "DAYOFYEAR",
951 DateTimeField::Quarter => "QUARTER",
952 DateTimeField::Epoch => "EPOCH",
953 DateTimeField::Timezone => "TIMEZONE",
954 DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
955 DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
956 DateTimeField::Date => "DATE",
957 DateTimeField::Time => "TIME",
958 DateTimeField::Custom(s) => {
959 match s.to_uppercase().as_str() {
961 "DAYOFMONTH" => "DAY",
962 "DOW" => "DAYOFWEEK",
963 "DOY" => "DAYOFYEAR",
964 "ISODOW" => "DAYOFWEEKISO",
965 "EPOCH_SECOND" | "EPOCH_SECONDS" => "EPOCH_SECOND",
966 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => "EPOCH_MILLISECOND",
967 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => "EPOCH_MICROSECOND",
968 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => "EPOCH_NANOSECOND",
969 _ => return {
970 let field_ident = Expression::Identifier(crate::expressions::Identifier {
971 name: s.to_string(),
972 quoted: false,
973 trailing_comments: Vec::new(),
974 });
975 Ok(Expression::Function(Box::new(Function::new(
976 "DATE_PART".to_string(),
977 vec![field_ident, transformed_this],
978 ))))
979 },
980 }
981 }
982 };
983 let field_ident = Expression::Identifier(crate::expressions::Identifier {
984 name: field_name.to_string(),
985 quoted: false,
986 trailing_comments: Vec::new(),
987 });
988 Ok(Expression::Function(Box::new(Function::new(
989 "DATE_PART".to_string(),
990 vec![field_ident, transformed_this],
991 ))))
992 }
993
994 Expression::Function(f) => self.transform_function(*f),
996
997 Expression::Sum(mut agg) => {
999 agg.this = self.transform_expr(agg.this)?;
1000 Ok(Expression::Sum(agg))
1001 }
1002
1003 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
1005
1006 Expression::NamedArgument(na) => {
1008 let transformed_value = self.transform_expr(na.value)?;
1009 Ok(Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
1010 name: na.name,
1011 value: transformed_value,
1012 separator: na.separator,
1013 })))
1014 }
1015
1016 Expression::CreateTable(mut ct) => {
1018 for col in &mut ct.columns {
1019 if let Expression::DataType(new_dt) = self.transform_data_type(col.data_type.clone())? {
1020 col.data_type = new_dt;
1021 }
1022 if let Some(default_expr) = col.default.take() {
1024 col.default = Some(self.transform_expr(default_expr)?);
1025 }
1026 for constraint in &mut col.constraints {
1028 if let crate::expressions::ColumnConstraint::ComputedColumn(cc) = constraint {
1029 let transformed = self.transform_expr(*cc.expression.clone())?;
1030 cc.expression = Box::new(transformed);
1031 }
1032 }
1033 }
1034
1035 if ct.table_modifier.as_deref() == Some("EXTERNAL") && !ct.with_properties.is_empty() {
1038 for (key, value) in ct.with_properties.drain(..) {
1039 let formatted = Self::format_external_table_property(&key, &value);
1040 ct.properties.push(Expression::Raw(crate::expressions::Raw { sql: formatted }));
1041 }
1042 }
1043
1044 Ok(Expression::CreateTable(ct))
1045 }
1046
1047 Expression::AlterTable(mut at) => {
1049 for action in &mut at.actions {
1050 if let crate::expressions::AlterTableAction::AddColumn { column, .. } = action {
1051 if let Expression::DataType(new_dt) = self.transform_data_type(column.data_type.clone())? {
1052 column.data_type = new_dt;
1053 }
1054 }
1055 }
1056 Ok(Expression::AlterTable(at))
1057 }
1058
1059 Expression::Table(mut t) => {
1061 if let Some(when) = t.when.take() {
1062 let transformed_expr = self.transform_expr(*when.expression)?;
1064 t.when = Some(Box::new(crate::expressions::HistoricalData {
1065 this: when.this,
1066 kind: when.kind,
1067 expression: Box::new(transformed_expr),
1068 }));
1069 }
1070 Ok(Expression::Table(t))
1071 }
1072
1073 Expression::Subscript(s) => {
1075 let transformed_this = self.transform_expr(s.this)?;
1076 let transformed_index = self.transform_expr(s.index)?;
1077 Ok(Expression::Subscript(Box::new(crate::expressions::Subscript {
1078 this: transformed_this,
1079 index: transformed_index,
1080 })))
1081 }
1082
1083 Expression::Paren(p) => {
1085 let transformed = self.transform_expr(p.this)?;
1086 Ok(Expression::Paren(Box::new(crate::expressions::Paren {
1087 this: transformed,
1088 trailing_comments: p.trailing_comments,
1089 })))
1090 }
1091
1092 Expression::Select(mut select) => {
1096 if let Some(ref mut order) = select.order_by {
1097 for ord in &mut order.expressions {
1098 if ord.nulls_first.is_none() {
1099 ord.nulls_first = Some(ord.desc);
1100 }
1101 }
1102 }
1103 Ok(Expression::Select(select))
1104 }
1105
1106 Expression::WindowFunction(mut wf) => {
1108 for ord in &mut wf.over.order_by {
1109 if ord.nulls_first.is_none() {
1110 ord.nulls_first = Some(ord.desc);
1111 }
1112 }
1113 Ok(Expression::WindowFunction(wf))
1114 }
1115
1116 Expression::Window(mut w) => {
1118 for ord in &mut w.order_by {
1119 if ord.nulls_first.is_none() {
1120 ord.nulls_first = Some(ord.desc);
1121 }
1122 }
1123 Ok(Expression::Window(w))
1124 }
1125
1126 Expression::Lateral(mut lat) => {
1128 let is_flatten = match lat.this.as_ref() {
1130 Expression::Function(f) => f.name.to_uppercase() == "FLATTEN",
1131 _ => false,
1132 };
1133 if is_flatten && lat.column_aliases.is_empty() {
1134 lat.column_aliases = vec![
1136 "SEQ".to_string(), "KEY".to_string(), "PATH".to_string(),
1137 "INDEX".to_string(), "VALUE".to_string(), "THIS".to_string(),
1138 ];
1139 if lat.alias.is_none() {
1141 lat.alias = Some("_flattened".to_string());
1142 }
1143 }
1144 Ok(Expression::Lateral(lat))
1145 }
1146
1147 _ => Ok(expr),
1149 }
1150 }
1151}
1152
1153impl SnowflakeDialect {
1154 fn format_external_table_property(key: &str, value: &str) -> String {
1157 let lower_key = key.to_lowercase();
1158 match lower_key.as_str() {
1159 "location" => format!("LOCATION={}", value),
1160 "file_format" => {
1161 let formatted_value = Self::format_file_format_value(value);
1163 format!("FILE_FORMAT={}", formatted_value)
1164 }
1165 _ => format!("{}={}", key, value),
1166 }
1167 }
1168
1169 fn format_file_format_value(value: &str) -> String {
1173 if !value.starts_with('(') {
1174 return value.to_string();
1175 }
1176 let inner = value[1..value.len() - 1].trim();
1178 let mut result = String::from("(");
1180 let mut parts: Vec<String> = Vec::new();
1181 let tokens: Vec<&str> = inner.split_whitespace().collect();
1183 let mut i = 0;
1184 while i < tokens.len() {
1185 let token = tokens[i];
1186 if i + 2 < tokens.len() && tokens[i + 1] == "=" {
1187 let val = Self::format_property_value(tokens[i + 2]);
1189 parts.push(format!("{}={}", token, val));
1190 i += 3;
1191 } else if token.contains('=') {
1192 let eq_pos = token.find('=').unwrap();
1194 let k = &token[..eq_pos];
1195 let v = Self::format_property_value(&token[eq_pos + 1..]);
1196 parts.push(format!("{}={}", k, v));
1197 i += 1;
1198 } else {
1199 parts.push(token.to_string());
1200 i += 1;
1201 }
1202 }
1203 result.push_str(&parts.join(" "));
1204 result.push(')');
1205 result
1206 }
1207
1208 fn format_property_value(value: &str) -> String {
1210 match value.to_lowercase().as_str() {
1211 "true" => "TRUE".to_string(),
1212 "false" => "FALSE".to_string(),
1213 _ => value.to_string(),
1214 }
1215 }
1216
1217 fn transform_data_type(&self, dt: crate::expressions::DataType) -> Result<Expression> {
1219 use crate::expressions::DataType;
1220 let transformed = match dt {
1221 DataType::Text => DataType::VarChar { length: None, parenthesized_length: false },
1223 DataType::Struct { fields, .. } => {
1225 let _ = fields; DataType::Custom {
1228 name: "OBJECT".to_string(),
1229 }
1230 }
1231 DataType::Custom { name } => {
1233 let upper_name = name.to_uppercase();
1234 match upper_name.as_str() {
1235 "NVARCHAR" | "NCHAR" | "NATIONAL CHARACTER VARYING" | "NATIONAL CHAR" => {
1237 DataType::VarChar { length: None, parenthesized_length: false }
1238 }
1239 "STRING" => DataType::VarChar { length: None, parenthesized_length: false },
1241 "BIGDECIMAL" => DataType::Double { precision: None, scale: None },
1243 "NESTED" => DataType::Custom {
1245 name: "OBJECT".to_string(),
1246 },
1247 "BYTEINT" => DataType::Int { length: None, integer_spelling: false },
1249 "CHAR VARYING" | "CHARACTER VARYING" => DataType::VarChar { length: None, parenthesized_length: false },
1251 "SQL_DOUBLE" => DataType::Double { precision: None, scale: None },
1253 "SQL_VARCHAR" => DataType::VarChar { length: None, parenthesized_length: false },
1255 "TIMESTAMP_NTZ" => DataType::Custom { name: "TIMESTAMPNTZ".to_string() },
1257 "TIMESTAMP_LTZ" => DataType::Custom { name: "TIMESTAMPLTZ".to_string() },
1259 "TIMESTAMP_TZ" => DataType::Custom { name: "TIMESTAMPTZ".to_string() },
1261 "NCHAR VARYING" => DataType::VarChar { length: None, parenthesized_length: false },
1263 "NUMBER" => DataType::Decimal { precision: Some(38), scale: Some(0) },
1265 _ if name.starts_with("NUMBER(") => {
1266 let inner = &name[7..name.len()-1]; let parts: Vec<&str> = inner.split(',').map(|s| s.trim()).collect();
1270 let precision = parts.first().and_then(|p| p.parse::<u32>().ok());
1271 let scale = parts.get(1).and_then(|s| s.parse::<u32>().ok());
1272 DataType::Decimal { precision, scale }
1273 }
1274 _ => DataType::Custom { name },
1275 }
1276 }
1277 DataType::Decimal { precision: None, scale: None } => DataType::Decimal { precision: Some(38), scale: Some(0) },
1279 DataType::Float { .. } => DataType::Double { precision: None, scale: None },
1281 other => other,
1283 };
1284 Ok(Expression::DataType(transformed))
1285 }
1286
1287 fn map_date_part(abbr: &str) -> Option<&'static str> {
1289 match abbr.to_uppercase().as_str() {
1290 "Y" | "YY" | "YYY" | "YYYY" | "YR" | "YEARS" | "YRS" => Some("YEAR"),
1292 "MM" | "MON" | "MONS" | "MONTHS" => Some("MONTH"),
1294 "D" | "DD" | "DAYS" | "DAYOFMONTH" => Some("DAY"),
1296 "DAY OF WEEK" | "WEEKDAY" | "DOW" | "DW" => Some("DAYOFWEEK"),
1298 "WEEKDAY_ISO" | "DOW_ISO" | "DW_ISO" | "DAYOFWEEK_ISO" => Some("DAYOFWEEKISO"),
1299 "DAY OF YEAR" | "DOY" | "DY" => Some("DAYOFYEAR"),
1301 "W" | "WK" | "WEEKOFYEAR" | "WOY" | "WY" => Some("WEEK"),
1303 "WEEK_ISO" | "WEEKOFYEARISO" | "WEEKOFYEAR_ISO" => Some("WEEKISO"),
1304 "Q" | "QTR" | "QTRS" | "QUARTERS" => Some("QUARTER"),
1306 "H" | "HH" | "HR" | "HOURS" | "HRS" => Some("HOUR"),
1308 "MI" | "MIN" | "MINUTES" | "MINS" => Some("MINUTE"),
1310 "S" | "SEC" | "SECONDS" | "SECS" => Some("SECOND"),
1312 "MS" | "MSEC" | "MSECS" | "MSECOND" | "MSECONDS" | "MILLISEC" | "MILLISECS" | "MILLISECON" | "MILLISECONDS" => Some("MILLISECOND"),
1314 "US" | "USEC" | "USECS" | "MICROSEC" | "MICROSECS" | "USECOND" | "USECONDS" | "MICROSECONDS" => Some("MICROSECOND"),
1316 "NS" | "NSEC" | "NANOSEC" | "NSECOND" | "NSECONDS" | "NANOSECS" => Some("NANOSECOND"),
1318 "EPOCH_SECOND" | "EPOCH_SECONDS" => Some("EPOCH_SECOND"),
1320 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Some("EPOCH_MILLISECOND"),
1321 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Some("EPOCH_MICROSECOND"),
1322 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Some("EPOCH_NANOSECOND"),
1323 "TZH" => Some("TIMEZONE_HOUR"),
1325 "TZM" => Some("TIMEZONE_MINUTE"),
1326 "DEC" | "DECS" | "DECADES" => Some("DECADE"),
1328 "MIL" | "MILS" | "MILLENIA" => Some("MILLENNIUM"),
1330 "C" | "CENT" | "CENTS" | "CENTURIES" => Some("CENTURY"),
1332 _ => None,
1334 }
1335 }
1336
1337 fn transform_date_part_arg(&self, expr: Expression) -> Expression {
1339 match &expr {
1340 Expression::Literal(crate::expressions::Literal::String(s)) => {
1342 Expression::Identifier(crate::expressions::Identifier {
1343 name: s.clone(),
1344 quoted: false,
1345 trailing_comments: Vec::new(),
1346 })
1347 }
1348 Expression::Identifier(id) => {
1350 if let Some(canonical) = Self::map_date_part(&id.name) {
1351 Expression::Identifier(crate::expressions::Identifier {
1352 name: canonical.to_string(),
1353 quoted: false,
1354 trailing_comments: Vec::new(),
1355 })
1356 } else {
1357 expr
1359 }
1360 }
1361 Expression::Column(col) if col.table.is_none() => {
1363 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1364 Expression::Identifier(crate::expressions::Identifier {
1365 name: canonical.to_string(),
1366 quoted: false,
1367 trailing_comments: Vec::new(),
1368 })
1369 } else {
1370 expr
1372 }
1373 }
1374 _ => expr,
1375 }
1376 }
1377
1378 fn transform_date_part_arg_identifiers_only(&self, expr: Expression) -> Expression {
1381 match &expr {
1382 Expression::Identifier(id) => {
1383 if let Some(canonical) = Self::map_date_part(&id.name) {
1384 Expression::Identifier(crate::expressions::Identifier {
1385 name: canonical.to_string(),
1386 quoted: false,
1387 trailing_comments: Vec::new(),
1388 })
1389 } else {
1390 expr
1391 }
1392 }
1393 Expression::Column(col) if col.table.is_none() => {
1394 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1395 Expression::Identifier(crate::expressions::Identifier {
1396 name: canonical.to_string(),
1397 quoted: false,
1398 trailing_comments: Vec::new(),
1399 })
1400 } else {
1401 expr
1402 }
1403 }
1404 _ => expr,
1405 }
1406 }
1407
1408 fn transform_json_path(path: &str) -> String {
1412 fn is_safe_identifier(s: &str) -> bool {
1415 if s.is_empty() {
1416 return false;
1417 }
1418 let mut chars = s.chars();
1419 match chars.next() {
1420 Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
1421 _ => return false,
1422 }
1423 chars.all(|c| c.is_ascii_alphanumeric() || c == '_')
1424 }
1425
1426 if !path.contains('.') && !path.contains('[') && !path.contains(':') {
1429 if is_safe_identifier(path) {
1430 return path.to_string();
1431 } else {
1432 return format!("[\"{}\"]", path);
1434 }
1435 }
1436
1437 let result = path.replace(':', ".");
1440 result
1441 }
1442
1443 fn transform_interval(&self, interval: crate::expressions::Interval) -> Result<Expression> {
1445 use crate::expressions::{Interval, Literal};
1446
1447 fn expand_unit(abbr: &str) -> &'static str {
1449 match abbr.to_uppercase().as_str() {
1450 "D" => "DAY",
1451 "H" => "HOUR",
1452 "M" => "MINUTE",
1453 "MS" => "MILLISECOND",
1454 "NS" => "NANOSECOND",
1455 "Q" => "QUARTER",
1456 "S" => "SECOND",
1457 "US" => "MICROSECOND",
1458 "W" => "WEEK",
1459 "Y" => "YEAR",
1460 "WEEK" | "WEEKS" => "WEEK",
1462 "DAY" | "DAYS" => "DAY",
1463 "HOUR" | "HOURS" => "HOUR",
1464 "MINUTE" | "MINUTES" => "MINUTE",
1465 "SECOND" | "SECONDS" => "SECOND",
1466 "MONTH" | "MONTHS" => "MONTH",
1467 "YEAR" | "YEARS" => "YEAR",
1468 "QUARTER" | "QUARTERS" => "QUARTER",
1469 "MILLISECOND" | "MILLISECONDS" => "MILLISECOND",
1470 "MICROSECOND" | "MICROSECONDS" => "MICROSECOND",
1471 "NANOSECOND" | "NANOSECONDS" => "NANOSECOND",
1472 _ => "", }
1474 }
1475
1476 fn parse_interval_string(s: &str) -> Option<(&str, &str)> {
1478 let s = s.trim();
1479
1480 let mut num_end = 0;
1483 let mut chars = s.chars().peekable();
1484
1485 if chars.peek() == Some(&'-') {
1487 chars.next();
1488 num_end += 1;
1489 }
1490
1491 while let Some(&c) = chars.peek() {
1493 if c.is_ascii_digit() {
1494 chars.next();
1495 num_end += 1;
1496 } else {
1497 break;
1498 }
1499 }
1500
1501 if chars.peek() == Some(&'.') {
1503 chars.next();
1504 num_end += 1;
1505 while let Some(&c) = chars.peek() {
1506 if c.is_ascii_digit() {
1507 chars.next();
1508 num_end += 1;
1509 } else {
1510 break;
1511 }
1512 }
1513 }
1514
1515 if num_end == 0 || (num_end == 1 && s.starts_with('-')) {
1516 return None; }
1518
1519 let value = &s[..num_end];
1520 let rest = s[num_end..].trim();
1521
1522 if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_alphabetic()) {
1524 return None;
1525 }
1526
1527 Some((value, rest))
1528 }
1529
1530 if let Some(Expression::Literal(Literal::String(ref s))) = interval.this {
1532 if let Some((value, unit)) = parse_interval_string(s) {
1533 let expanded = expand_unit(unit);
1534 if !expanded.is_empty() {
1535 let new_value = format!("{} {}", value, expanded);
1537
1538 return Ok(Expression::Interval(Box::new(Interval {
1539 this: Some(Expression::Literal(Literal::String(new_value))),
1540 unit: None, })));
1542 }
1543 }
1544 }
1545
1546 Ok(Expression::Interval(Box::new(interval)))
1548 }
1549
1550 fn transform_function(&self, f: Function) -> Result<Expression> {
1551 let transformed_args: Vec<Expression> = f
1553 .args
1554 .into_iter()
1555 .map(|arg| self.transform_expr(arg))
1556 .collect::<Result<Vec<_>>>()?;
1557
1558 let f = Function {
1559 name: f.name,
1560 args: transformed_args,
1561 distinct: f.distinct,
1562 trailing_comments: f.trailing_comments,
1563 use_bracket_syntax: f.use_bracket_syntax,
1564 no_parens: f.no_parens,
1565 quoted: f.quoted,
1566 };
1567
1568 let name_upper = f.name.to_uppercase();
1569 match name_upper.as_str() {
1570 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
1572 expressions: f.args,
1573 }))),
1574
1575 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1577 original_name: None,
1578 expressions: f.args,
1579 }))),
1580
1581 "NVL2" => Ok(Expression::Function(Box::new(f))),
1583
1584 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1586 Function::new("LISTAGG".to_string(), f.args),
1587 ))),
1588
1589 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
1591 "LISTAGG".to_string(),
1592 f.args,
1593 )))),
1594
1595 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
1597 "SUBSTRING".to_string(),
1598 f.args,
1599 )))),
1600
1601 "UNNEST" => Ok(Expression::Function(Box::new(Function::new(
1603 "FLATTEN".to_string(),
1604 f.args,
1605 )))),
1606
1607 "EXPLODE" => Ok(Expression::Function(Box::new(Function::new(
1609 "FLATTEN".to_string(),
1610 f.args,
1611 )))),
1612
1613 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1615
1616 "NOW" => Ok(Expression::Function(Box::new(Function {
1618 name: "CURRENT_TIMESTAMP".to_string(),
1619 args: f.args,
1620 distinct: false,
1621 trailing_comments: Vec::new(),
1622 use_bracket_syntax: false,
1623 no_parens: f.no_parens, quoted: false,
1624 }))),
1625
1626 "GETDATE" => Ok(Expression::Function(Box::new(Function {
1628 name: "CURRENT_TIMESTAMP".to_string(),
1629 args: f.args,
1630 distinct: false,
1631 trailing_comments: Vec::new(),
1632 use_bracket_syntax: false,
1633 no_parens: f.no_parens, quoted: false,
1634 }))),
1635
1636 "CURRENT_TIMESTAMP" if f.args.is_empty() => Ok(Expression::Function(Box::new(Function {
1640 name: "CURRENT_TIMESTAMP".to_string(),
1641 args: Vec::new(),
1642 distinct: false,
1643 trailing_comments: Vec::new(),
1644 use_bracket_syntax: false,
1645 no_parens: false, quoted: false,
1647 }))),
1648
1649 "TO_DATE" => {
1653 if f.args.len() == 1 {
1654 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0] {
1655 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
1657 return Ok(Expression::Cast(Box::new(Cast {
1658 this: f.args.into_iter().next().unwrap(),
1659 to: crate::expressions::DataType::Date,
1660 double_colon_syntax: false,
1661 trailing_comments: Vec::new(),
1662 format: None,
1663 default: None,
1664 })));
1665 }
1666 }
1667 }
1668 let mut args = f.args;
1670 if args.len() >= 2 {
1671 args[1] = Self::normalize_format_arg(args[1].clone());
1672 }
1673 Ok(Expression::Function(Box::new(Function::new(
1674 "TO_DATE".to_string(),
1675 args,
1676 ))))
1677 }
1678
1679 "TO_TIME" => {
1681 if f.args.len() == 1 {
1682 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0] {
1683 return Ok(Expression::Cast(Box::new(Cast {
1684 this: f.args.into_iter().next().unwrap(),
1685 to: crate::expressions::DataType::Time { precision: None, timezone: false },
1686 double_colon_syntax: false,
1687 trailing_comments: Vec::new(),
1688 format: None,
1689 default: None,
1690 })));
1691 }
1692 }
1693 let mut args = f.args;
1695 if args.len() >= 2 {
1696 args[1] = Self::normalize_format_arg(args[1].clone());
1697 }
1698 Ok(Expression::Function(Box::new(Function::new(
1699 "TO_TIME".to_string(),
1700 args,
1701 ))))
1702 }
1703
1704 "TO_TIMESTAMP" => {
1711 let args = f.args;
1712 if args.len() == 1 {
1713 let arg = &args[0];
1714 match arg {
1715 Expression::Literal(Literal::String(s)) if Self::looks_like_datetime(s) => {
1716 return Ok(Expression::Cast(Box::new(Cast {
1718 this: args.into_iter().next().unwrap(),
1719 to: DataType::Timestamp { precision: None, timezone: false },
1720 double_colon_syntax: false,
1721 trailing_comments: vec![],
1722 format: None,
1723 default: None,
1724 })));
1725 }
1726 Expression::Literal(Literal::String(s)) if Self::looks_like_epoch(s) => {
1727 return Ok(Expression::UnixToTime(Box::new(crate::expressions::UnixToTime {
1729 this: Box::new(args.into_iter().next().unwrap()),
1730 scale: None,
1731 zone: None,
1732 hours: None,
1733 minutes: None,
1734 format: None,
1735 target_type: None,
1736 })));
1737 }
1738 Expression::Literal(Literal::Number(_)) | Expression::Neg(_) => {
1739 return Ok(Expression::UnixToTime(Box::new(crate::expressions::UnixToTime {
1741 this: Box::new(args.into_iter().next().unwrap()),
1742 scale: None,
1743 zone: None,
1744 hours: None,
1745 minutes: None,
1746 format: None,
1747 target_type: None,
1748 })));
1749 }
1750 _ => {
1751 return Ok(Expression::Function(Box::new(Function::new(
1753 "TO_TIMESTAMP".to_string(),
1754 args,
1755 ))));
1756 }
1757 }
1758 } else if args.len() == 2 {
1759 let second_arg = &args[1];
1760 let is_int_scale = match second_arg {
1762 Expression::Literal(Literal::Number(n)) => n.parse::<i64>().is_ok(),
1763 _ => false,
1764 };
1765
1766 if is_int_scale {
1767 let mut args_iter = args.into_iter();
1769 let value = args_iter.next().unwrap();
1770 let scale_expr = args_iter.next().unwrap();
1771 let scale = if let Expression::Literal(Literal::Number(n)) = &scale_expr {
1772 n.parse::<i64>().ok()
1773 } else {
1774 None
1775 };
1776 return Ok(Expression::UnixToTime(Box::new(crate::expressions::UnixToTime {
1777 this: Box::new(value),
1778 scale,
1779 zone: None,
1780 hours: None,
1781 minutes: None,
1782 format: None,
1783 target_type: None,
1784 })));
1785 } else {
1786 let mut args_iter = args.into_iter();
1788 let value = args_iter.next().unwrap();
1789 let format_expr = args_iter.next().unwrap();
1790 let format_str = match &format_expr {
1791 Expression::Literal(Literal::String(s)) => s.clone(),
1792 _ => {
1793 return Ok(Expression::Function(Box::new(Function::new(
1795 "TO_TIMESTAMP".to_string(),
1796 vec![value, format_expr],
1797 ))));
1798 }
1799 };
1800 let normalized_format = Self::normalize_snowflake_format(&format_str);
1802 return Ok(Expression::StrToTime(Box::new(crate::expressions::StrToTime {
1803 this: Box::new(value),
1804 format: normalized_format,
1805 zone: None,
1806 safe: None,
1807 target_type: None,
1808 })));
1809 }
1810 }
1811 Ok(Expression::Function(Box::new(Function::new(
1813 "TO_TIMESTAMP".to_string(),
1814 args,
1815 ))))
1816 }
1817
1818 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
1820
1821 "ROUND" if f.args.iter().any(|a| matches!(a, Expression::NamedArgument(_))) => {
1824 let mut expr_val = None;
1825 let mut scale_val = None;
1826 let mut rounding_mode_val = None;
1827 for arg in &f.args {
1828 if let Expression::NamedArgument(na) = arg {
1829 match na.name.name.to_uppercase().as_str() {
1830 "EXPR" => expr_val = Some(na.value.clone()),
1831 "SCALE" => scale_val = Some(na.value.clone()),
1832 "ROUNDING_MODE" => rounding_mode_val = Some(na.value.clone()),
1833 _ => {}
1834 }
1835 }
1836 }
1837 if let Some(expr) = expr_val {
1838 let mut args = vec![expr];
1839 if let Some(scale) = scale_val {
1840 args.push(scale);
1841 }
1842 if let Some(mode) = rounding_mode_val {
1843 args.push(mode);
1844 }
1845 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), args))))
1846 } else {
1847 Ok(Expression::Function(Box::new(f)))
1848 }
1849 }
1850
1851 "DATE_FORMAT" => {
1854 let mut args = f.args;
1855 if !args.is_empty() {
1857 if matches!(&args[0], Expression::Literal(Literal::String(_))) {
1858 args[0] = Expression::Cast(Box::new(crate::expressions::Cast {
1859 this: args[0].clone(),
1860 to: DataType::Timestamp { precision: None, timezone: false },
1861 trailing_comments: Vec::new(),
1862 double_colon_syntax: false,
1863 format: None,
1864 default: None,
1865 }));
1866 }
1867 }
1868 if args.len() >= 2 {
1870 if let Expression::Literal(Literal::String(ref fmt)) = args[1] {
1871 let sf_fmt = strftime_to_snowflake_format(fmt);
1872 args[1] = Expression::Literal(Literal::String(sf_fmt));
1873 }
1874 }
1875 Ok(Expression::Function(Box::new(Function::new(
1876 "TO_CHAR".to_string(),
1877 args,
1878 ))))
1879 }
1880
1881 "ARRAY" => Ok(Expression::Function(Box::new(Function::new(
1883 "ARRAY_CONSTRUCT".to_string(),
1884 f.args,
1885 )))),
1886
1887 "STRUCT" => {
1890 let mut oc_args = Vec::new();
1891 for arg in f.args {
1892 match arg {
1893 Expression::Alias(a) => {
1894 oc_args.push(Expression::Literal(crate::expressions::Literal::String(a.alias.name.clone())));
1896 oc_args.push(a.this);
1897 }
1898 other => {
1899 oc_args.push(other);
1901 }
1902 }
1903 }
1904 Ok(Expression::Function(Box::new(Function::new(
1905 "OBJECT_CONSTRUCT".to_string(),
1906 oc_args,
1907 ))))
1908 }
1909
1910 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
1912 "GET_PATH".to_string(),
1913 f.args,
1914 )))),
1915
1916 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
1918 "JSON_EXTRACT_PATH_TEXT".to_string(),
1919 f.args,
1920 )))),
1921
1922 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
1924 f.args.into_iter().next().unwrap(),
1925 )))),
1926
1927 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
1929 this: f.args.into_iter().next().unwrap(),
1930 decimals: None,
1931 to: None,
1932 }))),
1933
1934 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
1936
1937 "SPLIT" => Ok(Expression::Function(Box::new(f))),
1939
1940 "ARRAY_AGG" => Ok(Expression::Function(Box::new(f))),
1942
1943 "JSON_PARSE" | "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
1945 "PARSE_JSON".to_string(),
1946 f.args,
1947 )))),
1948
1949 "RAND" => {
1951 let seed = f.args.first().cloned().map(Box::new);
1952 Ok(Expression::Rand(Box::new(crate::expressions::Rand { seed, lower: None, upper: None })))
1953 }
1954
1955 "SHA" => Ok(Expression::Function(Box::new(Function::new(
1957 "SHA1".to_string(),
1958 f.args,
1959 )))),
1960
1961 "APPROX_DISTINCT" => Ok(Expression::Function(Box::new(Function::new(
1963 "APPROX_COUNT_DISTINCT".to_string(),
1964 f.args,
1965 )))),
1966
1967 "GEN_RANDOM_UUID" | "UUID" => Ok(Expression::Uuid(Box::new(crate::expressions::Uuid { this: None, name: None, is_string: None }))),
1969
1970 "NEWID" => Ok(Expression::Uuid(Box::new(crate::expressions::Uuid { this: None, name: None, is_string: None }))),
1972
1973 "UUID_STRING" => {
1975 if f.args.is_empty() {
1976 Ok(Expression::Uuid(Box::new(crate::expressions::Uuid { this: None, name: None, is_string: None })))
1977 } else {
1978 Ok(Expression::Function(Box::new(Function::new(
1979 "UUID_STRING".to_string(),
1980 f.args,
1981 ))))
1982 }
1983 }
1984
1985 "IF" if f.args.len() >= 2 => {
1987 let mut args = f.args;
1988 let condition = args.remove(0);
1989 let true_val = args.remove(0);
1990 let false_val = if !args.is_empty() { Some(args.remove(0)) } else { None };
1991 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
1992 condition,
1993 true_value: true_val,
1994 false_value: Some(false_val.unwrap_or(Expression::Null(crate::expressions::Null))),
1995 original_name: Some("IFF".to_string()),
1996 })))
1997 }
1998
1999 "SQUARE" if f.args.len() == 1 => {
2001 let x = f.args.into_iter().next().unwrap();
2002 Ok(Expression::Power(Box::new(crate::expressions::BinaryFunc { original_name: None,
2003 this: x,
2004 expression: Expression::number(2),
2005 })))
2006 }
2007
2008 "POW" if f.args.len() == 2 => {
2010 let mut args = f.args.into_iter();
2011 let x = args.next().unwrap();
2012 let y = args.next().unwrap();
2013 Ok(Expression::Power(Box::new(crate::expressions::BinaryFunc { original_name: None,
2014 this: x,
2015 expression: y,
2016 })))
2017 }
2018
2019 "MOD" if f.args.len() == 2 => {
2021 let mut args = f.args.into_iter();
2022 let x = args.next().unwrap();
2023 let y = args.next().unwrap();
2024 Ok(Expression::Mod(Box::new(crate::expressions::BinaryOp {
2025 left: x,
2026 right: y,
2027 left_comments: Vec::new(),
2028 operator_comments: Vec::new(),
2029 trailing_comments: Vec::new(),
2030 })))
2031 }
2032
2033 "APPROXIMATE_JACCARD_INDEX" => Ok(Expression::Function(Box::new(Function::new(
2035 "APPROXIMATE_SIMILARITY".to_string(),
2036 f.args,
2037 )))),
2038
2039 "ARRAY_CONSTRUCT" => Ok(Expression::ArrayFunc(Box::new(crate::expressions::ArrayConstructor {
2041 expressions: f.args,
2042 bracket_notation: true,
2043 use_list_keyword: false,
2044 }))),
2045
2046 "APPROX_TOP_K" if f.args.len() == 1 => {
2048 let mut args = f.args;
2049 args.push(Expression::number(1));
2050 Ok(Expression::Function(Box::new(Function::new(
2051 "APPROX_TOP_K".to_string(),
2052 args,
2053 ))))
2054 }
2055
2056 "TO_DECIMAL" | "TO_NUMERIC" => Ok(Expression::Function(Box::new(Function::new(
2058 "TO_NUMBER".to_string(),
2059 f.args,
2060 )))),
2061
2062 "TRY_TO_DECIMAL" | "TRY_TO_NUMERIC" => Ok(Expression::Function(Box::new(Function::new(
2064 "TRY_TO_NUMBER".to_string(),
2065 f.args,
2066 )))),
2067
2068 "STDDEV_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2070 "STDDEV".to_string(),
2071 f.args,
2072 )))),
2073
2074 "STRTOK" if f.args.len() >= 1 => {
2076 let mut args = f.args;
2077 if args.len() == 1 {
2079 args.push(Expression::string(" ".to_string()));
2080 }
2081 if args.len() == 2 {
2083 args.push(Expression::number(1));
2084 }
2085 Ok(Expression::Function(Box::new(Function::new(
2086 "SPLIT_PART".to_string(),
2087 args,
2088 ))))
2089 }
2090
2091 "WEEKOFYEAR" => Ok(Expression::Function(Box::new(Function::new(
2093 "WEEK".to_string(),
2094 f.args,
2095 )))),
2096
2097 "LIKE" if f.args.len() >= 2 => {
2099 let mut args = f.args.into_iter();
2100 let left = args.next().unwrap();
2101 let right = args.next().unwrap();
2102 let escape = args.next();
2103 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
2104 left,
2105 right,
2106 escape,
2107 quantifier: None,
2108 })))
2109 }
2110
2111 "ILIKE" if f.args.len() >= 2 => {
2113 let mut args = f.args.into_iter();
2114 let left = args.next().unwrap();
2115 let right = args.next().unwrap();
2116 let escape = args.next();
2117 Ok(Expression::ILike(Box::new(crate::expressions::LikeOp {
2118 left,
2119 right,
2120 escape,
2121 quantifier: None,
2122 })))
2123 }
2124
2125 "RLIKE" if f.args.len() >= 2 => {
2127 let mut args = f.args.into_iter();
2128 let left = args.next().unwrap();
2129 let pattern = args.next().unwrap();
2130 let flags = args.next();
2131 Ok(Expression::RegexpLike(Box::new(crate::expressions::RegexpFunc {
2132 this: left,
2133 pattern,
2134 flags,
2135 })))
2136 }
2137
2138 "IFF" if f.args.len() >= 2 => {
2140 let mut args = f.args;
2141 let condition = args.remove(0);
2142 let true_value = args.remove(0);
2143 let false_value = if !args.is_empty() { Some(args.remove(0)) } else { None };
2144 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2145 condition,
2146 true_value,
2147 false_value,
2148 original_name: Some("IFF".to_string()),
2149 })))
2150 }
2151
2152 "TIMESTAMP_NTZ_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMPNTZFROMPARTS" => {
2154 Ok(Expression::Function(Box::new(Function::new(
2155 "TIMESTAMP_FROM_PARTS".to_string(),
2156 f.args,
2157 ))))
2158 }
2159
2160 "TIMESTAMPLTZFROMPARTS" => {
2162 Ok(Expression::Function(Box::new(Function::new(
2163 "TIMESTAMP_LTZ_FROM_PARTS".to_string(),
2164 f.args,
2165 ))))
2166 }
2167
2168 "TIMESTAMPTZFROMPARTS" => {
2170 Ok(Expression::Function(Box::new(Function::new(
2171 "TIMESTAMP_TZ_FROM_PARTS".to_string(),
2172 f.args,
2173 ))))
2174 }
2175
2176 "DATEADD" if f.args.len() >= 1 => {
2178 let mut args = f.args;
2179 args[0] = self.transform_date_part_arg(args[0].clone());
2180 Ok(Expression::Function(Box::new(Function::new(
2181 "DATEADD".to_string(),
2182 args,
2183 ))))
2184 }
2185
2186 "DATEDIFF" if f.args.len() >= 1 => {
2189 let mut args = f.args;
2190 args[0] = self.transform_date_part_arg(args[0].clone());
2191 for i in 1..args.len() {
2194 if let Expression::Function(ref func) = args[i] {
2195 if func.name == "_POLYGLOT_TO_DATE" {
2196 let inner_args = func.args.clone();
2197 args[i] = Expression::Function(Box::new(Function::new(
2198 "TO_DATE".to_string(),
2199 inner_args,
2200 )));
2201 }
2202 }
2203 }
2204 Ok(Expression::Function(Box::new(Function::new(
2205 "DATEDIFF".to_string(),
2206 args,
2207 ))))
2208 }
2209
2210 "TIMEDIFF" => Ok(Expression::Function(Box::new(Function::new(
2212 "DATEDIFF".to_string(),
2213 f.args,
2214 )))),
2215
2216 "TIMESTAMPDIFF" => Ok(Expression::Function(Box::new(Function::new(
2218 "DATEDIFF".to_string(),
2219 f.args,
2220 )))),
2221
2222 "TIMESTAMPADD" => Ok(Expression::Function(Box::new(Function::new(
2224 "DATEADD".to_string(),
2225 f.args,
2226 )))),
2227
2228 "TIMEADD" => Ok(Expression::Function(Box::new(f))),
2230
2231 "DATEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2233 "DATE_FROM_PARTS".to_string(),
2234 f.args,
2235 )))),
2236
2237 "TIMEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2239 "TIME_FROM_PARTS".to_string(),
2240 f.args,
2241 )))),
2242
2243 "DAYOFWEEK" => Ok(Expression::Function(Box::new(f))),
2245
2246 "DAYOFMONTH" => Ok(Expression::Function(Box::new(f))),
2248
2249 "DAYOFYEAR" => Ok(Expression::Function(Box::new(f))),
2251
2252 "MONTHNAME" if f.args.len() == 1 => {
2255 let arg = f.args.into_iter().next().unwrap();
2256 Ok(Expression::Monthname(Box::new(crate::expressions::Monthname {
2257 this: Box::new(arg),
2258 abbreviated: Some(Box::new(Expression::Literal(Literal::String("true".to_string())))),
2259 })))
2260 }
2261
2262 "DAYNAME" if f.args.len() == 1 => {
2265 let arg = f.args.into_iter().next().unwrap();
2266 Ok(Expression::Dayname(Box::new(crate::expressions::Dayname {
2267 this: Box::new(arg),
2268 abbreviated: Some(Box::new(Expression::Literal(Literal::String("true".to_string())))),
2269 })))
2270 }
2271
2272 "BOOLAND_AGG" | "BOOL_AND" | "LOGICAL_AND" if !f.args.is_empty() => {
2274 let arg = f.args.into_iter().next().unwrap();
2275 Ok(Expression::LogicalAnd(Box::new(AggFunc {
2276 this: arg,
2277 distinct: false,
2278 filter: None,
2279 order_by: Vec::new(),
2280 name: Some("BOOLAND_AGG".to_string()),
2281 ignore_nulls: None,
2282 having_max: None,
2283 limit: None,
2284 })))
2285 }
2286
2287 "BOOLOR_AGG" | "BOOL_OR" | "LOGICAL_OR" if !f.args.is_empty() => {
2289 let arg = f.args.into_iter().next().unwrap();
2290 Ok(Expression::LogicalOr(Box::new(AggFunc {
2291 this: arg,
2292 distinct: false,
2293 filter: None,
2294 order_by: Vec::new(),
2295 name: Some("BOOLOR_AGG".to_string()),
2296 ignore_nulls: None,
2297 having_max: None,
2298 limit: None,
2299 })))
2300 }
2301
2302 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
2304 let arg = f.args.into_iter().next().unwrap();
2305 Ok(Expression::Skewness(Box::new(AggFunc {
2306 this: arg,
2307 distinct: false,
2308 filter: None,
2309 order_by: Vec::new(),
2310 name: Some("SKEW".to_string()),
2311 ignore_nulls: None,
2312 having_max: None,
2313 limit: None,
2314 })))
2315 }
2316
2317 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2319 "VARIANCE".to_string(),
2320 f.args,
2321 )))),
2322
2323 "VAR_POP" => Ok(Expression::Function(Box::new(Function::new(
2325 "VARIANCE_POP".to_string(),
2326 f.args,
2327 )))),
2328
2329 "DATE" if f.args.len() == 1 => {
2331 Ok(Expression::Function(Box::new(Function::new(
2332 "TO_DATE".to_string(),
2333 f.args,
2334 ))))
2335 }
2336 "DATE" if f.args.len() >= 2 => {
2340 let mut args = f.args;
2341 args[1] = Self::normalize_format_arg(args[1].clone());
2342 Ok(Expression::Function(Box::new(Function::new(
2343 "TO_DATE".to_string(),
2344 args,
2345 ))))
2346 }
2347 "_POLYGLOT_DATE" if f.args.len() >= 2 => {
2350 let mut args = f.args;
2351 args[1] = Self::normalize_format_arg(args[1].clone());
2352 Ok(Expression::Function(Box::new(Function::new(
2353 "DATE".to_string(),
2354 args,
2355 ))))
2356 }
2357
2358 "DESCRIBE" => Ok(Expression::Function(Box::new(f))),
2360
2361 "MD5_HEX" => Ok(Expression::Function(Box::new(Function::new(
2363 "MD5".to_string(),
2364 f.args,
2365 )))),
2366
2367 "SHA1_HEX" => Ok(Expression::Function(Box::new(Function::new(
2369 "SHA1".to_string(),
2370 f.args,
2371 )))),
2372
2373 "SHA2_HEX" => Ok(Expression::Function(Box::new(Function::new(
2375 "SHA2".to_string(),
2376 f.args,
2377 )))),
2378
2379 "LEVENSHTEIN" => Ok(Expression::Function(Box::new(Function::new(
2381 "EDITDISTANCE".to_string(),
2382 f.args,
2383 )))),
2384
2385 "BIT_NOT" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2387 "BITNOT".to_string(),
2388 f.args,
2389 )))),
2390
2391 "BIT_AND" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2393 "BITAND".to_string(),
2394 f.args,
2395 )))),
2396
2397 "BIT_OR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2399 "BITOR".to_string(),
2400 f.args,
2401 )))),
2402
2403 "BIT_XOR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2405 "BITXOR".to_string(),
2406 f.args,
2407 )))),
2408
2409 "BIT_SHIFTLEFT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2411 "BITSHIFTLEFT".to_string(),
2412 f.args,
2413 )))),
2414
2415 "BIT_SHIFTRIGHT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2417 "BITSHIFTRIGHT".to_string(),
2418 f.args,
2419 )))),
2420
2421 "SYSTIMESTAMP" => Ok(Expression::Function(Box::new(Function {
2423 name: "CURRENT_TIMESTAMP".to_string(),
2424 args: f.args,
2425 distinct: false,
2426 trailing_comments: Vec::new(),
2427 use_bracket_syntax: false,
2428 no_parens: f.no_parens, quoted: false,
2429 }))),
2430
2431 "LOCALTIMESTAMP" => {
2433 Ok(Expression::Function(Box::new(Function {
2434 name: "CURRENT_TIMESTAMP".to_string(),
2435 args: f.args,
2436 distinct: false,
2437 trailing_comments: Vec::new(),
2438 use_bracket_syntax: false,
2439 no_parens: f.no_parens, quoted: false,
2440 })))
2441 }
2442
2443 "CEILING" => Ok(Expression::Function(Box::new(Function::new(
2445 "CEIL".to_string(),
2446 f.args,
2447 )))),
2448
2449 "LOG" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2451 "LN".to_string(),
2452 f.args,
2453 )))),
2454
2455 "REGEXP_SUBSTR_ALL" => Ok(Expression::Function(Box::new(Function::new(
2457 "REGEXP_EXTRACT_ALL".to_string(),
2458 f.args,
2459 )))),
2460
2461 "GET_PATH" if f.args.len() >= 2 => {
2465 let mut args = f.args;
2466 if let Expression::Literal(crate::expressions::Literal::String(path)) = &args[1] {
2468 let transformed = Self::transform_json_path(path);
2469 args[1] = Expression::Literal(crate::expressions::Literal::String(transformed));
2470 }
2471 Ok(Expression::Function(Box::new(Function::new(
2472 "GET_PATH".to_string(),
2473 args,
2474 ))))
2475 }
2476 "GET_PATH" => Ok(Expression::Function(Box::new(f))),
2477
2478 "FLATTEN" => Ok(Expression::Function(Box::new(f))),
2480
2481 "DATE_TRUNC" if f.args.len() >= 1 => {
2484 let mut args = f.args;
2485 let unit_name = match &args[0] {
2487 Expression::Identifier(id) => Some(id.name.as_str()),
2488 Expression::Column(col) if col.table.is_none() => Some(col.name.name.as_str()),
2489 _ => None,
2490 };
2491 if let Some(name) = unit_name {
2492 let canonical = Self::map_date_part(name).unwrap_or(name);
2493 args[0] = Expression::Literal(crate::expressions::Literal::String(canonical.to_uppercase()));
2494 }
2495 Ok(Expression::Function(Box::new(Function::new(
2496 "DATE_TRUNC".to_string(),
2497 args,
2498 ))))
2499 }
2500
2501 "DATE_PART" if f.args.len() >= 1 => {
2507 let mut args = f.args;
2508 let from_typed_literal = args.len() >= 2 && matches!(&args[1],
2509 Expression::Literal(crate::expressions::Literal::Timestamp(_))
2510 | Expression::Literal(crate::expressions::Literal::Date(_))
2511 | Expression::Literal(crate::expressions::Literal::Time(_))
2512 | Expression::Literal(crate::expressions::Literal::Datetime(_))
2513 );
2514 if from_typed_literal {
2515 args[0] = self.transform_date_part_arg(args[0].clone());
2516 } else {
2517 args[0] = self.transform_date_part_arg_identifiers_only(args[0].clone());
2520 }
2521 Ok(Expression::Function(Box::new(Function::new(
2522 "DATE_PART".to_string(),
2523 args,
2524 ))))
2525 }
2526
2527 "OBJECT_CONSTRUCT" => Ok(Expression::Function(Box::new(f))),
2529
2530 "OBJECT_CONSTRUCT_KEEP_NULL" => Ok(Expression::Function(Box::new(f))),
2532
2533 "DESC" => Ok(Expression::Function(Box::new(Function::new(
2535 "DESCRIBE".to_string(),
2536 f.args,
2537 )))),
2538
2539 "RLIKE" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2541 "REGEXP_LIKE".to_string(),
2542 f.args,
2543 )))),
2544
2545 "TRANSFORM" => {
2550 let transformed_args: Vec<Expression> = f.args.into_iter().map(|arg| {
2551 if let Expression::Lambda(lambda) = arg {
2552 self.transform_typed_lambda(*lambda)
2553 } else {
2554 arg
2555 }
2556 }).collect();
2557 Ok(Expression::Function(Box::new(Function::new(
2558 "TRANSFORM".to_string(),
2559 transformed_args,
2560 ))))
2561 }
2562
2563 "SEARCH" if f.args.len() >= 2 => {
2565 let mut args = f.args.into_iter();
2566 let this = Box::new(args.next().unwrap());
2567 let expression = Box::new(args.next().unwrap());
2568
2569 let mut analyzer: Option<Box<Expression>> = None;
2570 let mut search_mode: Option<Box<Expression>> = None;
2571
2572 for arg in args {
2574 if let Expression::NamedArgument(na) = &arg {
2575 let name_upper = na.name.name.to_uppercase();
2576 match name_upper.as_str() {
2577 "ANALYZER" => analyzer = Some(Box::new(arg)),
2578 "SEARCH_MODE" => search_mode = Some(Box::new(arg)),
2579 _ => {}
2580 }
2581 }
2582 }
2583
2584 Ok(Expression::Search(Box::new(crate::expressions::Search {
2585 this,
2586 expression,
2587 json_scope: None,
2588 analyzer,
2589 analyzer_options: None,
2590 search_mode,
2591 })))
2592 }
2593
2594 "CONVERT" if f.args.len() == 2 => {
2597 let value = f.args.get(0).cloned().unwrap();
2598 let type_arg = f.args.get(1).cloned().unwrap();
2599
2600 if let Expression::Column(col) = &type_arg {
2602 let type_name = col.name.name.to_uppercase();
2603 let data_type = match type_name.as_str() {
2604 "SQL_DOUBLE" => Some(DataType::Double { precision: None, scale: None }),
2605 "SQL_VARCHAR" => Some(DataType::VarChar { length: None, parenthesized_length: false }),
2606 "SQL_INTEGER" | "SQL_INT" => Some(DataType::Int { length: None, integer_spelling: false }),
2607 "SQL_BIGINT" => Some(DataType::BigInt { length: None }),
2608 "SQL_SMALLINT" => Some(DataType::SmallInt { length: None }),
2609 "SQL_FLOAT" => Some(DataType::Float { precision: None, scale: None, real_spelling: false }),
2610 "SQL_REAL" => Some(DataType::Float { precision: None, scale: None, real_spelling: true }),
2611 "SQL_DECIMAL" => Some(DataType::Decimal { precision: None, scale: None }),
2612 "SQL_DATE" => Some(DataType::Date),
2613 "SQL_TIME" => Some(DataType::Time { precision: None, timezone: false }),
2614 "SQL_TIMESTAMP" => Some(DataType::Timestamp { precision: None, timezone: false }),
2615 _ => None,
2616 };
2617
2618 if let Some(dt) = data_type {
2619 return Ok(Expression::Cast(Box::new(Cast {
2620 this: value,
2621 to: dt,
2622 double_colon_syntax: false,
2623 trailing_comments: vec![],
2624 format: None,
2625 default: None,
2626 })));
2627 }
2628 }
2629 Ok(Expression::Function(Box::new(f)))
2631 }
2632
2633 "TO_TIMESTAMP_TZ" => {
2636 if f.args.len() == 1 {
2637 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0] {
2638 return Ok(Expression::Cast(Box::new(Cast {
2639 this: f.args.into_iter().next().unwrap(),
2640 to: DataType::Custom { name: "TIMESTAMPTZ".to_string() },
2641 double_colon_syntax: false,
2642 trailing_comments: vec![],
2643 format: None,
2644 default: None,
2645 })));
2646 }
2647 }
2648 Ok(Expression::Function(Box::new(f)))
2649 }
2650
2651 "TO_TIMESTAMP_NTZ" => {
2653 if f.args.len() == 1 {
2654 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0] {
2655 return Ok(Expression::Cast(Box::new(Cast {
2656 this: f.args.into_iter().next().unwrap(),
2657 to: DataType::Custom { name: "TIMESTAMPNTZ".to_string() },
2658 double_colon_syntax: false,
2659 trailing_comments: vec![],
2660 format: None,
2661 default: None,
2662 })));
2663 }
2664 }
2665 Ok(Expression::Function(Box::new(f)))
2666 }
2667
2668 "TO_TIMESTAMP_LTZ" => {
2670 if f.args.len() == 1 {
2671 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0] {
2672 return Ok(Expression::Cast(Box::new(Cast {
2673 this: f.args.into_iter().next().unwrap(),
2674 to: DataType::Custom { name: "TIMESTAMPLTZ".to_string() },
2675 double_colon_syntax: false,
2676 trailing_comments: vec![],
2677 format: None,
2678 default: None,
2679 })));
2680 }
2681 }
2682 Ok(Expression::Function(Box::new(f)))
2683 }
2684
2685 "UNIFORM" => Ok(Expression::Function(Box::new(f))),
2687
2688 "REPLACE" if f.args.len() == 2 => {
2690 let mut args = f.args;
2691 args.push(Expression::Literal(crate::expressions::Literal::String(String::new())));
2692 Ok(Expression::Function(Box::new(Function::new(
2693 "REPLACE".to_string(),
2694 args,
2695 ))))
2696 }
2697
2698 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
2700 "ANY_VALUE".to_string(),
2701 f.args,
2702 )))),
2703
2704 "SAFE_DIVIDE" if f.args.len() == 2 => {
2706 let mut args = f.args;
2707 let x = args.remove(0);
2708 let y = args.remove(0);
2709 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2710 condition: Expression::Neq(Box::new(BinaryOp {
2711 left: y.clone(),
2712 right: Expression::number(0),
2713 left_comments: Vec::new(),
2714 operator_comments: Vec::new(),
2715 trailing_comments: Vec::new(),
2716 })),
2717 true_value: Expression::Div(Box::new(BinaryOp {
2718 left: x,
2719 right: y,
2720 left_comments: Vec::new(),
2721 operator_comments: Vec::new(),
2722 trailing_comments: Vec::new(),
2723 })),
2724 false_value: Some(Expression::Null(crate::expressions::Null)),
2725 original_name: Some("IFF".to_string()),
2726 })))
2727 }
2728
2729 "TIMESTAMP" if f.args.len() == 1 => {
2731 let arg = f.args.into_iter().next().unwrap();
2732 Ok(Expression::Cast(Box::new(Cast {
2733 this: arg,
2734 to: DataType::Custom { name: "TIMESTAMPTZ".to_string() },
2735 trailing_comments: Vec::new(),
2736 double_colon_syntax: false,
2737 format: None,
2738 default: None,
2739 })))
2740 }
2741
2742 "TIMESTAMP" if f.args.len() == 2 => {
2744 let mut args = f.args;
2745 let value = args.remove(0);
2746 let tz = args.remove(0);
2747 Ok(Expression::Function(Box::new(Function::new(
2748 "CONVERT_TIMEZONE".to_string(),
2749 vec![
2750 tz,
2751 Expression::Cast(Box::new(Cast {
2752 this: value,
2753 to: DataType::Timestamp { precision: None, timezone: false },
2754 trailing_comments: Vec::new(),
2755 double_colon_syntax: false,
2756 format: None,
2757 default: None,
2758 })),
2759 ],
2760 ))))
2761 }
2762
2763 "TIME" if f.args.len() == 3 => {
2765 Ok(Expression::Function(Box::new(Function::new(
2766 "TIME_FROM_PARTS".to_string(),
2767 f.args,
2768 ))))
2769 }
2770
2771 "DIV0" if f.args.len() == 2 => {
2773 let mut args = f.args;
2774 let x = args.remove(0);
2775 let y = args.remove(0);
2776 let x_expr = Self::maybe_paren(x.clone());
2778 let y_expr = Self::maybe_paren(y.clone());
2779 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2780 condition: Expression::And(Box::new(BinaryOp::new(
2781 Expression::Eq(Box::new(BinaryOp::new(
2782 y_expr.clone(),
2783 Expression::number(0),
2784 ))),
2785 Expression::Not(Box::new(crate::expressions::UnaryOp {
2786 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
2787 this: x_expr.clone(),
2788 not: false,
2789 postfix_form: false,
2790 })),
2791 })),
2792 ))),
2793 true_value: Expression::number(0),
2794 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
2795 original_name: Some("IFF".to_string()),
2796 })))
2797 }
2798
2799 "DIV0NULL" if f.args.len() == 2 => {
2801 let mut args = f.args;
2802 let x = args.remove(0);
2803 let y = args.remove(0);
2804 let x_expr = Self::maybe_paren(x.clone());
2805 let y_expr = Self::maybe_paren(y.clone());
2806 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2807 condition: Expression::Or(Box::new(BinaryOp::new(
2808 Expression::Eq(Box::new(BinaryOp::new(
2809 y_expr.clone(),
2810 Expression::number(0),
2811 ))),
2812 Expression::IsNull(Box::new(crate::expressions::IsNull {
2813 this: y_expr.clone(),
2814 not: false,
2815 postfix_form: false,
2816 })),
2817 ))),
2818 true_value: Expression::number(0),
2819 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
2820 original_name: Some("IFF".to_string()),
2821 })))
2822 }
2823
2824 "ZEROIFNULL" if f.args.len() == 1 => {
2826 let x = f.args.into_iter().next().unwrap();
2827 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2828 condition: Expression::IsNull(Box::new(crate::expressions::IsNull {
2829 this: x.clone(),
2830 not: false,
2831 postfix_form: false,
2832 })),
2833 true_value: Expression::number(0),
2834 false_value: Some(x),
2835 original_name: Some("IFF".to_string()),
2836 })))
2837 }
2838
2839 "NULLIFZERO" if f.args.len() == 1 => {
2841 let x = f.args.into_iter().next().unwrap();
2842 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2843 condition: Expression::Eq(Box::new(BinaryOp::new(
2844 x.clone(),
2845 Expression::number(0),
2846 ))),
2847 true_value: Expression::Null(crate::expressions::Null),
2848 false_value: Some(x),
2849 original_name: Some("IFF".to_string()),
2850 })))
2851 }
2852
2853 "TRY_TO_TIME" => {
2855 if f.args.len() == 1 {
2856 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0] {
2857 return Ok(Expression::TryCast(Box::new(Cast {
2858 this: f.args.into_iter().next().unwrap(),
2859 to: crate::expressions::DataType::Time { precision: None, timezone: false },
2860 double_colon_syntax: false,
2861 trailing_comments: Vec::new(),
2862 format: None,
2863 default: None,
2864 })));
2865 }
2866 }
2867 let mut args = f.args;
2869 if args.len() >= 2 {
2870 args[1] = Self::normalize_format_arg(args[1].clone());
2871 }
2872 Ok(Expression::Function(Box::new(Function::new(
2873 "TRY_TO_TIME".to_string(),
2874 args,
2875 ))))
2876 }
2877
2878 "TRY_TO_TIMESTAMP" => {
2881 if f.args.len() == 1 {
2882 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0] {
2883 if !Self::looks_like_epoch(s) {
2884 return Ok(Expression::TryCast(Box::new(Cast {
2885 this: f.args.into_iter().next().unwrap(),
2886 to: DataType::Timestamp { precision: None, timezone: false },
2887 double_colon_syntax: false,
2888 trailing_comments: Vec::new(),
2889 format: None,
2890 default: None,
2891 })));
2892 }
2893 }
2894 }
2895 let mut args = f.args;
2897 if args.len() >= 2 {
2898 args[1] = Self::normalize_format_arg(args[1].clone());
2899 }
2900 Ok(Expression::Function(Box::new(Function::new(
2901 "TRY_TO_TIMESTAMP".to_string(),
2902 args,
2903 ))))
2904 }
2905
2906 "TRY_TO_DATE" => {
2908 if f.args.len() == 1 {
2909 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0] {
2910 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
2912 return Ok(Expression::TryCast(Box::new(Cast {
2913 this: f.args.into_iter().next().unwrap(),
2914 to: crate::expressions::DataType::Date,
2915 double_colon_syntax: false,
2916 trailing_comments: Vec::new(),
2917 format: None,
2918 default: None,
2919 })));
2920 }
2921 }
2922 }
2923 let mut args = f.args;
2925 if args.len() >= 2 {
2926 args[1] = Self::normalize_format_arg(args[1].clone());
2927 }
2928 Ok(Expression::Function(Box::new(Function::new(
2929 "TRY_TO_DATE".to_string(),
2930 args,
2931 ))))
2932 }
2933
2934 "TRY_TO_DOUBLE" => Ok(Expression::Function(Box::new(f))),
2936
2937 "REGEXP_REPLACE" if f.args.len() == 2 => {
2939 let mut args = f.args;
2940 args.push(Expression::Literal(crate::expressions::Literal::String(String::new())));
2941 Ok(Expression::Function(Box::new(Function::new(
2942 "REGEXP_REPLACE".to_string(),
2943 args,
2944 ))))
2945 }
2946
2947 "LAST_DAY" if f.args.len() == 2 => {
2949 let mut args = f.args;
2950 let date = args.remove(0);
2951 let unit = args.remove(0);
2952 let unit_str = match &unit {
2953 Expression::Column(c) => c.name.name.to_uppercase(),
2954 Expression::Identifier(i) => i.name.to_uppercase(),
2955 _ => String::new(),
2956 };
2957 if unit_str == "MONTH" {
2958 Ok(Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![date]))))
2959 } else {
2960 Ok(Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![date, unit]))))
2961 }
2962 }
2963
2964 "EXTRACT" if f.args.len() == 2 => {
2966 Ok(Expression::Function(Box::new(Function::new(
2967 "DATE_PART".to_string(),
2968 f.args,
2969 ))))
2970 }
2971
2972 "ENDS_WITH" | "ENDSWITH" if f.args.len() == 2 => {
2974 let mut args = f.args;
2975 let this = args.remove(0);
2976 let expr = args.remove(0);
2977 Ok(Expression::EndsWith(Box::new(crate::expressions::BinaryFunc {
2978 original_name: None,
2979 this,
2980 expression: expr,
2981 })))
2982 }
2983
2984 _ => Ok(Expression::Function(Box::new(f))),
2986 }
2987 }
2988
2989 fn looks_like_datetime(s: &str) -> bool {
2991 s.contains('-') || s.contains(':') || s.contains(' ') || s.contains('/')
2994 }
2995
2996 fn looks_like_epoch(s: &str) -> bool {
2998 !s.is_empty() && s.chars().all(|c| c.is_ascii_digit() || c == '.')
2999 }
3000
3001 fn maybe_paren(expr: Expression) -> Expression {
3003 match &expr {
3004 Expression::Sub(_) | Expression::Add(_) | Expression::Mul(_) | Expression::Div(_) => {
3005 Expression::Paren(Box::new(crate::expressions::Paren {
3006 this: expr,
3007 trailing_comments: Vec::new(),
3008 }))
3009 }
3010 _ => expr,
3011 }
3012 }
3013
3014 fn normalize_snowflake_format(format: &str) -> String {
3018 let mut result = String::new();
3019 let chars: Vec<char> = format.chars().collect();
3020 let mut i = 0;
3021 while i < chars.len() {
3022 if chars[i] == '"' {
3024 i += 1;
3025 while i < chars.len() && chars[i] != '"' {
3026 result.push(chars[i]);
3027 i += 1;
3028 }
3029 if i < chars.len() {
3030 i += 1; }
3032 continue;
3033 }
3034
3035 let remaining = &format[i..];
3036 let remaining_upper = remaining.to_uppercase();
3037
3038 if remaining_upper.starts_with("YYYY") {
3040 result.push_str("yyyy");
3041 i += 4;
3042 } else if remaining_upper.starts_with("YY") {
3043 result.push_str("yy");
3044 i += 2;
3045 } else if remaining_upper.starts_with("MMMM") {
3046 result.push_str("mmmm");
3047 i += 4;
3048 } else if remaining_upper.starts_with("MON") {
3049 result.push_str("mon");
3050 i += 3;
3051 } else if remaining_upper.starts_with("MM") {
3052 result.push_str("mm");
3053 i += 2;
3054 } else if remaining_upper.starts_with("DD") {
3055 result.push_str("DD");
3056 i += 2;
3057 } else if remaining_upper.starts_with("DY") {
3058 result.push_str("dy");
3059 i += 2;
3060 } else if remaining_upper.starts_with("HH24") {
3061 result.push_str("hh24");
3062 i += 4;
3063 } else if remaining_upper.starts_with("HH12") {
3064 result.push_str("hh12");
3065 i += 4;
3066 } else if remaining_upper.starts_with("HH") {
3067 result.push_str("hh");
3068 i += 2;
3069 } else if remaining_upper.starts_with("MISS") {
3070 result.push_str("miss");
3072 i += 4;
3073 } else if remaining_upper.starts_with("MI") {
3074 result.push_str("mi");
3075 i += 2;
3076 } else if remaining_upper.starts_with("SS") {
3077 result.push_str("ss");
3078 i += 2;
3079 } else if remaining_upper.starts_with("FF") {
3080 let ff_len = 2;
3082 let digit = if i + ff_len < chars.len() && chars[i + ff_len].is_ascii_digit() {
3083 let d = chars[i + ff_len];
3084 Some(d)
3085 } else {
3086 None
3087 };
3088 if let Some(d) = digit {
3089 result.push_str("ff");
3090 result.push(d);
3091 i += 3;
3092 } else {
3093 result.push_str("ff9");
3095 i += 2;
3096 }
3097 } else if remaining_upper.starts_with("AM") || remaining_upper.starts_with("PM") {
3098 result.push_str("pm");
3099 i += 2;
3100 } else if remaining_upper.starts_with("TZH") {
3101 result.push_str("tzh");
3102 i += 3;
3103 } else if remaining_upper.starts_with("TZM") {
3104 result.push_str("tzm");
3105 i += 3;
3106 } else {
3107 result.push(chars[i]);
3109 i += 1;
3110 }
3111 }
3112 result
3113 }
3114
3115 fn normalize_format_arg(expr: Expression) -> Expression {
3117 if let Expression::Literal(crate::expressions::Literal::String(s)) = &expr {
3118 let normalized = Self::normalize_snowflake_format(s);
3119 Expression::Literal(crate::expressions::Literal::String(normalized))
3120 } else {
3121 expr
3122 }
3123 }
3124
3125 fn transform_typed_lambda(&self, lambda: crate::expressions::LambdaExpr) -> Expression {
3128 use crate::expressions::{LambdaExpr, DataType};
3129 use std::collections::HashMap;
3130
3131 let mut param_types: HashMap<String, DataType> = HashMap::new();
3133 for (i, param) in lambda.parameters.iter().enumerate() {
3134 if let Some(Some(dt)) = lambda.parameter_types.get(i) {
3135 param_types.insert(param.name.to_uppercase(), dt.clone());
3136 }
3137 }
3138
3139 if param_types.is_empty() {
3141 return Expression::Lambda(Box::new(lambda));
3142 }
3143
3144 let transformed_body = self.replace_lambda_params_with_cast(lambda.body, ¶m_types);
3146
3147 Expression::Lambda(Box::new(LambdaExpr {
3149 parameters: lambda.parameters,
3150 body: transformed_body,
3151 colon: lambda.colon,
3152 parameter_types: Vec::new(), }))
3154 }
3155
3156 fn replace_lambda_params_with_cast(
3158 &self,
3159 expr: Expression,
3160 param_types: &std::collections::HashMap<String, crate::expressions::DataType>,
3161 ) -> Expression {
3162 use crate::expressions::{Cast, BinaryOp, Paren};
3163
3164 match expr {
3165 Expression::Column(col) if col.table.is_none() => {
3167 let name_upper = col.name.name.to_uppercase();
3168 if let Some(dt) = param_types.get(&name_upper) {
3169 Expression::Cast(Box::new(Cast {
3171 this: Expression::Column(col),
3172 to: dt.clone(),
3173 double_colon_syntax: false,
3174 trailing_comments: Vec::new(),
3175 format: None,
3176 default: None,
3177 }))
3178 } else {
3179 Expression::Column(col)
3180 }
3181 }
3182
3183 Expression::Identifier(id) => {
3185 let name_upper = id.name.to_uppercase();
3186 if let Some(dt) = param_types.get(&name_upper) {
3187 Expression::Cast(Box::new(Cast {
3189 this: Expression::Identifier(id),
3190 to: dt.clone(),
3191 double_colon_syntax: false,
3192 trailing_comments: Vec::new(),
3193 format: None,
3194 default: None,
3195 }))
3196 } else {
3197 Expression::Identifier(id)
3198 }
3199 }
3200
3201 Expression::Add(op) => Expression::Add(Box::new(BinaryOp::new(
3203 self.replace_lambda_params_with_cast(op.left, param_types),
3204 self.replace_lambda_params_with_cast(op.right, param_types),
3205 ))),
3206 Expression::Sub(op) => Expression::Sub(Box::new(BinaryOp::new(
3207 self.replace_lambda_params_with_cast(op.left, param_types),
3208 self.replace_lambda_params_with_cast(op.right, param_types),
3209 ))),
3210 Expression::Mul(op) => Expression::Mul(Box::new(BinaryOp::new(
3211 self.replace_lambda_params_with_cast(op.left, param_types),
3212 self.replace_lambda_params_with_cast(op.right, param_types),
3213 ))),
3214 Expression::Div(op) => Expression::Div(Box::new(BinaryOp::new(
3215 self.replace_lambda_params_with_cast(op.left, param_types),
3216 self.replace_lambda_params_with_cast(op.right, param_types),
3217 ))),
3218 Expression::Mod(op) => Expression::Mod(Box::new(BinaryOp::new(
3219 self.replace_lambda_params_with_cast(op.left, param_types),
3220 self.replace_lambda_params_with_cast(op.right, param_types),
3221 ))),
3222
3223 Expression::Paren(p) => Expression::Paren(Box::new(Paren {
3225 this: self.replace_lambda_params_with_cast(p.this, param_types),
3226 trailing_comments: p.trailing_comments,
3227 })),
3228
3229 Expression::Function(mut f) => {
3231 f.args = f.args.into_iter()
3232 .map(|arg| self.replace_lambda_params_with_cast(arg, param_types))
3233 .collect();
3234 Expression::Function(f)
3235 }
3236
3237 Expression::Eq(op) => Expression::Eq(Box::new(BinaryOp::new(
3239 self.replace_lambda_params_with_cast(op.left, param_types),
3240 self.replace_lambda_params_with_cast(op.right, param_types),
3241 ))),
3242 Expression::Neq(op) => Expression::Neq(Box::new(BinaryOp::new(
3243 self.replace_lambda_params_with_cast(op.left, param_types),
3244 self.replace_lambda_params_with_cast(op.right, param_types),
3245 ))),
3246 Expression::Lt(op) => Expression::Lt(Box::new(BinaryOp::new(
3247 self.replace_lambda_params_with_cast(op.left, param_types),
3248 self.replace_lambda_params_with_cast(op.right, param_types),
3249 ))),
3250 Expression::Lte(op) => Expression::Lte(Box::new(BinaryOp::new(
3251 self.replace_lambda_params_with_cast(op.left, param_types),
3252 self.replace_lambda_params_with_cast(op.right, param_types),
3253 ))),
3254 Expression::Gt(op) => Expression::Gt(Box::new(BinaryOp::new(
3255 self.replace_lambda_params_with_cast(op.left, param_types),
3256 self.replace_lambda_params_with_cast(op.right, param_types),
3257 ))),
3258 Expression::Gte(op) => Expression::Gte(Box::new(BinaryOp::new(
3259 self.replace_lambda_params_with_cast(op.left, param_types),
3260 self.replace_lambda_params_with_cast(op.right, param_types),
3261 ))),
3262
3263 Expression::And(op) => Expression::And(Box::new(BinaryOp::new(
3265 self.replace_lambda_params_with_cast(op.left, param_types),
3266 self.replace_lambda_params_with_cast(op.right, param_types),
3267 ))),
3268 Expression::Or(op) => Expression::Or(Box::new(BinaryOp::new(
3269 self.replace_lambda_params_with_cast(op.left, param_types),
3270 self.replace_lambda_params_with_cast(op.right, param_types),
3271 ))),
3272
3273 other => other,
3275 }
3276 }
3277
3278 fn transform_aggregate_function(
3279 &self,
3280 f: Box<crate::expressions::AggregateFunction>,
3281 ) -> Result<Expression> {
3282 let name_upper = f.name.to_uppercase();
3283 match name_upper.as_str() {
3284 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3286 Function::new("LISTAGG".to_string(), f.args),
3287 ))),
3288
3289 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3291 "LISTAGG".to_string(),
3292 f.args,
3293 )))),
3294
3295 "APPROX_DISTINCT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3297 Function::new("APPROX_COUNT_DISTINCT".to_string(), f.args),
3298 ))),
3299
3300 "BIT_AND" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3302 "BITAND_AGG".to_string(),
3303 f.args,
3304 )))),
3305
3306 "BIT_OR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3308 "BITOR_AGG".to_string(),
3309 f.args,
3310 )))),
3311
3312 "BIT_XOR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3314 "BITXOR_AGG".to_string(),
3315 f.args,
3316 )))),
3317
3318 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" if !f.args.is_empty() => {
3320 let arg = f.args.into_iter().next().unwrap();
3321 Ok(Expression::LogicalAnd(Box::new(AggFunc {
3322 this: arg,
3323 distinct: f.distinct,
3324 filter: f.filter,
3325 order_by: Vec::new(),
3326 name: Some("BOOLAND_AGG".to_string()),
3327 ignore_nulls: None,
3328 having_max: None,
3329 limit: None,
3330 })))
3331 }
3332
3333 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if !f.args.is_empty() => {
3335 let arg = f.args.into_iter().next().unwrap();
3336 Ok(Expression::LogicalOr(Box::new(AggFunc {
3337 this: arg,
3338 distinct: f.distinct,
3339 filter: f.filter,
3340 order_by: Vec::new(),
3341 name: Some("BOOLOR_AGG".to_string()),
3342 ignore_nulls: None,
3343 having_max: None,
3344 limit: None,
3345 })))
3346 }
3347
3348 "APPROX_TOP_K" if f.args.len() == 1 => {
3350 let mut args = f.args;
3351 args.push(Expression::number(1));
3352 Ok(Expression::AggregateFunction(Box::new(
3353 crate::expressions::AggregateFunction {
3354 name: "APPROX_TOP_K".to_string(),
3355 args,
3356 distinct: f.distinct,
3357 filter: f.filter,
3358 order_by: Vec::new(),
3359 limit: None,
3360 ignore_nulls: None,
3361 },
3362 )))
3363 }
3364
3365 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
3367 let arg = f.args.into_iter().next().unwrap();
3368 Ok(Expression::Skewness(Box::new(AggFunc {
3369 this: arg,
3370 distinct: f.distinct,
3371 filter: f.filter,
3372 order_by: Vec::new(),
3373 name: Some("SKEW".to_string()),
3374 ignore_nulls: None,
3375 having_max: None,
3376 limit: None,
3377 })))
3378 }
3379
3380 _ => Ok(Expression::AggregateFunction(f)),
3382 }
3383 }
3384}
3385
3386fn strftime_to_snowflake_format(fmt: &str) -> String {
3388 let mut result = String::new();
3389 let chars: Vec<char> = fmt.chars().collect();
3390 let mut i = 0;
3391 while i < chars.len() {
3392 if chars[i] == '%' && i + 1 < chars.len() {
3393 match chars[i + 1] {
3394 'Y' => { result.push_str("yyyy"); i += 2; }
3395 'y' => { result.push_str("yy"); i += 2; }
3396 'm' => { result.push_str("mm"); i += 2; }
3397 'd' => { result.push_str("DD"); i += 2; }
3398 'H' => { result.push_str("hh24"); i += 2; }
3399 'M' => { result.push_str("mmmm"); i += 2; } 'i' => { result.push_str("mi"); i += 2; }
3401 'S' | 's' => { result.push_str("ss"); i += 2; }
3402 'f' => { result.push_str("ff"); i += 2; }
3403 'w' => { result.push_str("dy"); i += 2; } 'a' => { result.push_str("DY"); i += 2; } 'b' => { result.push_str("mon"); i += 2; } 'T' => { result.push_str("hh24:mi:ss"); i += 2; } _ => { result.push(chars[i]); result.push(chars[i + 1]); i += 2; }
3408 }
3409 } else {
3410 result.push(chars[i]);
3411 i += 1;
3412 }
3413 }
3414 result
3415}
3416
3417#[cfg(test)]
3418mod tests {
3419 use super::*;
3420 use crate::dialects::Dialect;
3421
3422 fn transpile_to_snowflake(sql: &str) -> String {
3423 let dialect = Dialect::get(DialectType::Generic);
3424 let result = dialect
3425 .transpile_to(sql, DialectType::Snowflake)
3426 .expect("Transpile failed");
3427 result[0].clone()
3428 }
3429
3430 #[test]
3431 fn test_ifnull_to_coalesce() {
3432 let result = transpile_to_snowflake("SELECT IFNULL(a, b)");
3433 assert!(
3434 result.contains("COALESCE"),
3435 "Expected COALESCE, got: {}",
3436 result
3437 );
3438 }
3439
3440 #[test]
3441 fn test_basic_select() {
3442 let result = transpile_to_snowflake("SELECT a, b FROM users WHERE id = 1");
3443 assert!(result.contains("SELECT"));
3444 assert!(result.contains("FROM users"));
3445 }
3446
3447 #[test]
3448 fn test_group_concat_to_listagg() {
3449 let result = transpile_to_snowflake("SELECT GROUP_CONCAT(name)");
3450 assert!(
3451 result.contains("LISTAGG"),
3452 "Expected LISTAGG, got: {}",
3453 result
3454 );
3455 }
3456
3457 #[test]
3458 fn test_string_agg_to_listagg() {
3459 let result = transpile_to_snowflake("SELECT STRING_AGG(name)");
3460 assert!(
3461 result.contains("LISTAGG"),
3462 "Expected LISTAGG, got: {}",
3463 result
3464 );
3465 }
3466
3467 #[test]
3468 fn test_array_to_array_construct() {
3469 let result = transpile_to_snowflake("SELECT ARRAY(1, 2, 3)");
3470 assert!(
3471 result.contains("ARRAY_CONSTRUCT"),
3472 "Expected ARRAY_CONSTRUCT, got: {}",
3473 result
3474 );
3475 }
3476
3477 #[test]
3478 fn test_double_quote_identifiers() {
3479 let dialect = SnowflakeDialect;
3481 let config = dialect.generator_config();
3482 assert_eq!(config.identifier_quote, '"');
3483 }
3484}