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 array_bracket_only: true,
100 ..Default::default()
101 }
102 }
103
104 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
105 match expr {
106 Expression::DataType(dt) => self.transform_data_type(dt),
108
109 Expression::In(in_expr) if in_expr.not && in_expr.query.is_some() => {
113 let inner = in_expr.query.unwrap();
115 let subquery = Expression::Subquery(Box::new(crate::expressions::Subquery {
117 this: inner,
118 alias: None,
119 column_aliases: Vec::new(),
120 order_by: None,
121 limit: None,
122 offset: None,
123 distribute_by: None,
124 sort_by: None,
125 cluster_by: None,
126 lateral: false,
127 modifiers_inside: false,
128 trailing_comments: Vec::new(),
129 inferred_type: None,
130 }));
131 Ok(Expression::All(Box::new(
132 crate::expressions::QuantifiedExpr {
133 this: in_expr.this,
134 subquery,
135 op: Some(crate::expressions::QuantifiedOp::Neq),
136 },
137 )))
138 }
139
140 Expression::In(in_expr) if in_expr.not => {
142 let in_without_not = crate::expressions::In {
144 this: in_expr.this,
145 expressions: in_expr.expressions,
146 query: in_expr.query,
147 not: false,
148 global: in_expr.global,
149 unnest: in_expr.unnest,
150 is_field: in_expr.is_field,
151 };
152 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
153 this: Expression::In(Box::new(in_without_not)),
154 inferred_type: None,
155 })))
156 }
157
158 Expression::Interval(interval) => self.transform_interval(*interval),
161
162 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
165 original_name: None,
166 expressions: vec![f.this, f.expression],
167 inferred_type: None,
168 }))),
169
170 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
172 original_name: None,
173 expressions: vec![f.this, f.expression],
174 inferred_type: None,
175 }))),
176
177 Expression::Coalesce(mut f) => {
179 f.original_name = None;
180 Ok(Expression::Coalesce(f))
181 }
182
183 Expression::GroupConcat(f) => Ok(Expression::ListAgg(Box::new(ListAggFunc {
185 this: f.this,
186 separator: f.separator,
187 on_overflow: None,
188 order_by: f.order_by,
189 distinct: f.distinct,
190 filter: f.filter,
191 inferred_type: None,
192 }))),
193
194 Expression::Cast(c) => {
198 use crate::expressions::DataType;
199 let transformed_this = self.transform_expr(c.this)?;
201 match &c.to {
202 DataType::Geography { .. } => Ok(Expression::Function(Box::new(
203 Function::new("TO_GEOGRAPHY".to_string(), vec![transformed_this]),
204 ))),
205 DataType::Geometry { .. } => Ok(Expression::Function(Box::new(Function::new(
206 "TO_GEOMETRY".to_string(),
207 vec![transformed_this],
208 )))),
209 _ => {
210 let transformed_dt = match self.transform_data_type(c.to.clone())? {
212 Expression::DataType(dt) => dt,
213 _ => c.to.clone(),
214 };
215 Ok(Expression::Cast(Box::new(Cast {
216 this: transformed_this,
217 to: transformed_dt,
218 double_colon_syntax: false, trailing_comments: c.trailing_comments,
220 format: c.format,
221 default: c.default,
222 inferred_type: None,
223 })))
224 }
225 }
226 }
227
228 Expression::TryCast(c) => {
231 let transformed_this = self.transform_expr(c.this)?;
232 Ok(Expression::TryCast(Box::new(Cast {
233 this: transformed_this,
234 to: c.to,
235 double_colon_syntax: false, trailing_comments: c.trailing_comments,
237 format: c.format,
238 default: c.default,
239 inferred_type: None,
240 })))
241 }
242
243 Expression::SafeCast(c) => {
246 let to = match c.to {
247 DataType::Timestamp { .. } => DataType::Custom {
248 name: "TIMESTAMPTZ".to_string(),
249 },
250 DataType::Custom { name } if name.eq_ignore_ascii_case("TIMESTAMP") => {
251 DataType::Custom {
252 name: "TIMESTAMPTZ".to_string(),
253 }
254 }
255 other => other,
256 };
257 let transformed_this = self.transform_expr(c.this)?;
258 Ok(Expression::Cast(Box::new(Cast {
259 this: transformed_this,
260 to,
261 double_colon_syntax: c.double_colon_syntax,
262 trailing_comments: c.trailing_comments,
263 format: c.format,
264 default: c.default,
265 inferred_type: None,
266 })))
267 }
268
269 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Timestamp(_)) => { let Literal::Timestamp(s) = lit.as_ref() else { unreachable!() }; Ok(Expression::Cast(Box::new(Cast {
272 this: Expression::Literal(Box::new(Literal::String(s.clone()))),
273 to: DataType::Timestamp {
274 precision: None,
275 timezone: false,
276 },
277 double_colon_syntax: false,
278 trailing_comments: Vec::new(),
279 format: None,
280 default: None,
281 inferred_type: None,
282 }))) },
283
284 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => { let Literal::Date(s) = lit.as_ref() else { unreachable!() }; Ok(Expression::Cast(Box::new(Cast {
286 this: Expression::Literal(Box::new(Literal::String(s.clone()))),
287 to: DataType::Date,
288 double_colon_syntax: false,
289 trailing_comments: Vec::new(),
290 format: None,
291 default: None,
292 inferred_type: None,
293 }))) },
294
295 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Time(_)) => { let Literal::Time(s) = lit.as_ref() else { unreachable!() }; Ok(Expression::Cast(Box::new(Cast {
297 this: Expression::Literal(Box::new(Literal::String(s.clone()))),
298 to: DataType::Time {
299 precision: None,
300 timezone: false,
301 },
302 double_colon_syntax: false,
303 trailing_comments: Vec::new(),
304 format: None,
305 default: None,
306 inferred_type: None,
307 }))) },
308
309 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Datetime(_)) => { let Literal::Datetime(s) = lit.as_ref() else { unreachable!() }; Ok(Expression::Cast(Box::new(Cast {
311 this: Expression::Literal(Box::new(Literal::String(s.clone()))),
312 to: DataType::Custom {
313 name: "DATETIME".to_string(),
314 },
315 double_colon_syntax: false,
316 trailing_comments: Vec::new(),
317 format: None,
318 default: None,
319 inferred_type: None,
320 }))) },
321
322 Expression::ILike(op) => Ok(Expression::ILike(op)),
325
326 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
329 "FLATTEN".to_string(),
330 vec![f.this],
331 )))),
332
333 Expression::ExplodeOuter(f) => Ok(Expression::Function(Box::new(Function::new(
335 "FLATTEN".to_string(),
336 vec![f.this],
337 )))),
338
339 Expression::Unnest(f) => {
341 let input_arg =
343 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
344 name: crate::expressions::Identifier::new("INPUT"),
345 value: f.this,
346 separator: crate::expressions::NamedArgSeparator::DArrow,
347 }));
348
349 let flatten = Expression::Function(Box::new(Function::new(
351 "FLATTEN".to_string(),
352 vec![input_arg],
353 )));
354
355 let table_func =
357 Expression::TableFromRows(Box::new(crate::expressions::TableFromRows {
358 this: Box::new(flatten),
359 alias: None,
360 joins: vec![],
361 pivots: None,
362 sample: None,
363 }));
364
365 Ok(Expression::Alias(Box::new(crate::expressions::Alias {
367 this: table_func,
368 alias: crate::expressions::Identifier::new("_t0"),
369 column_aliases: vec![
370 crate::expressions::Identifier::new("seq"),
371 crate::expressions::Identifier::new("key"),
372 crate::expressions::Identifier::new("path"),
373 crate::expressions::Identifier::new("index"),
374 crate::expressions::Identifier::new("value"),
375 crate::expressions::Identifier::new("this"),
376 ],
377 pre_alias_comments: vec![],
378 trailing_comments: vec![],
379 inferred_type: None,
380 })))
381 }
382
383 Expression::ArrayFunc(arr) => {
387 if arr.bracket_notation {
388 Ok(Expression::ArrayFunc(arr))
390 } else {
391 Ok(Expression::Function(Box::new(Function::new(
393 "ARRAY_CONSTRUCT".to_string(),
394 arr.expressions,
395 ))))
396 }
397 }
398
399 Expression::ArrayConcat(f) => Ok(Expression::Function(Box::new(Function::new(
401 "ARRAY_CAT".to_string(),
402 f.expressions,
403 )))),
404
405 Expression::ArrayConcatAgg(f) => Ok(Expression::Function(Box::new(Function::new(
407 "ARRAY_FLATTEN".to_string(),
408 vec![f.this],
409 )))),
410
411 Expression::ArrayContains(f) => Ok(Expression::Function(Box::new(Function::new(
413 "ARRAY_CONTAINS".to_string(),
414 vec![f.this, f.expression],
415 )))),
416
417 Expression::ArrayIntersect(f) => Ok(Expression::Function(Box::new(Function::new(
419 "ARRAY_INTERSECTION".to_string(),
420 f.expressions,
421 )))),
422
423 Expression::ArraySort(f) => Ok(Expression::Function(Box::new(Function::new(
425 "ARRAY_SORT".to_string(),
426 vec![f.this],
427 )))),
428
429 Expression::StringToArray(f) => {
431 let mut args = vec![*f.this];
432 if let Some(expr) = f.expression {
433 args.push(*expr);
434 }
435 Ok(Expression::Function(Box::new(Function::new(
436 "STRTOK_TO_ARRAY".to_string(),
437 args,
438 ))))
439 }
440
441 Expression::BitwiseOr(f) => Ok(Expression::Function(Box::new(Function::new(
444 "BITOR".to_string(),
445 vec![f.left, f.right],
446 )))),
447
448 Expression::BitwiseXor(f) => Ok(Expression::Function(Box::new(Function::new(
450 "BITXOR".to_string(),
451 vec![f.left, f.right],
452 )))),
453
454 Expression::BitwiseAnd(f) => Ok(Expression::Function(Box::new(Function::new(
456 "BITAND".to_string(),
457 vec![f.left, f.right],
458 )))),
459
460 Expression::BitwiseNot(f) => Ok(Expression::Function(Box::new(Function::new(
462 "BITNOT".to_string(),
463 vec![f.this],
464 )))),
465
466 Expression::BitwiseLeftShift(f) => Ok(Expression::Function(Box::new(Function::new(
468 "BITSHIFTLEFT".to_string(),
469 vec![f.left, f.right],
470 )))),
471
472 Expression::BitwiseRightShift(f) => Ok(Expression::Function(Box::new(Function::new(
474 "BITSHIFTRIGHT".to_string(),
475 vec![f.left, f.right],
476 )))),
477
478 Expression::BitwiseAndAgg(f) => Ok(Expression::Function(Box::new(Function::new(
480 "BITAND_AGG".to_string(),
481 vec![f.this],
482 )))),
483
484 Expression::BitwiseOrAgg(f) => Ok(Expression::Function(Box::new(Function::new(
486 "BITOR_AGG".to_string(),
487 vec![f.this],
488 )))),
489
490 Expression::BitwiseXorAgg(f) => Ok(Expression::Function(Box::new(Function::new(
492 "BITXOR_AGG".to_string(),
493 vec![f.this],
494 )))),
495
496 Expression::LogicalAnd(f) => Ok(Expression::Function(Box::new(Function::new(
499 "BOOLAND_AGG".to_string(),
500 vec![f.this],
501 )))),
502
503 Expression::LogicalOr(f) => Ok(Expression::Function(Box::new(Function::new(
505 "BOOLOR_AGG".to_string(),
506 vec![f.this],
507 )))),
508
509 Expression::Booland(f) => Ok(Expression::Function(Box::new(Function::new(
511 "BOOLAND".to_string(),
512 vec![*f.this, *f.expression],
513 )))),
514
515 Expression::Boolor(f) => Ok(Expression::Function(Box::new(Function::new(
517 "BOOLOR".to_string(),
518 vec![*f.this, *f.expression],
519 )))),
520
521 Expression::Xor(f) => {
523 let mut args = Vec::new();
524 if let Some(this) = f.this {
525 args.push(*this);
526 }
527 if let Some(expr) = f.expression {
528 args.push(*expr);
529 }
530 Ok(Expression::Function(Box::new(Function::new(
531 "BOOLXOR".to_string(),
532 args,
533 ))))
534 }
535
536 Expression::DayOfMonth(f) => Ok(Expression::Function(Box::new(Function::new(
539 "DAYOFMONTH".to_string(),
540 vec![f.this],
541 )))),
542
543 Expression::DayOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
545 "DAYOFWEEK".to_string(),
546 vec![f.this],
547 )))),
548
549 Expression::DayOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
551 "DAYOFWEEKISO".to_string(),
552 vec![f.this],
553 )))),
554
555 Expression::DayOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
557 "DAYOFYEAR".to_string(),
558 vec![f.this],
559 )))),
560
561 Expression::WeekOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
563 "WEEK".to_string(),
564 vec![f.this],
565 )))),
566
567 Expression::YearOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
569 "YEAROFWEEK".to_string(),
570 vec![f.this],
571 )))),
572
573 Expression::YearOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
575 "YEAROFWEEKISO".to_string(),
576 vec![f.this],
577 )))),
578
579 Expression::ByteLength(f) => Ok(Expression::Function(Box::new(Function::new(
581 "OCTET_LENGTH".to_string(),
582 vec![f.this],
583 )))),
584
585 Expression::TimestampDiff(f) => {
587 let mut args = vec![];
588 if let Some(ref unit_str) = f.unit {
590 args.push(Expression::Identifier(crate::expressions::Identifier::new(
591 unit_str.clone(),
592 )));
593 args.push(*f.this);
594 args.push(*f.expression);
595 } else {
596 args.push(*f.this);
597 args.push(*f.expression);
598 }
599 Ok(Expression::Function(Box::new(Function::new(
600 "TIMESTAMPDIFF".to_string(),
601 args,
602 ))))
603 }
604
605 Expression::TimestampAdd(f) => {
607 let mut args = vec![];
608 if let Some(ref unit_str) = f.unit {
609 args.push(Expression::Identifier(crate::expressions::Identifier::new(
610 unit_str.clone(),
611 )));
612 args.push(*f.this);
613 args.push(*f.expression);
614 } else {
615 args.push(*f.this);
616 args.push(*f.expression);
617 }
618 Ok(Expression::Function(Box::new(Function::new(
619 "TIMESTAMPADD".to_string(),
620 args,
621 ))))
622 }
623
624 Expression::ToArray(f) => Ok(Expression::Function(Box::new(Function::new(
626 "TO_ARRAY".to_string(),
627 vec![f.this],
628 )))),
629
630 Expression::DateAdd(f) => {
632 let unit_str = interval_unit_to_str(&f.unit);
633 let unit = Expression::Identifier(crate::expressions::Identifier {
634 name: unit_str,
635 quoted: false,
636 trailing_comments: Vec::new(),
637 span: None,
638 });
639 Ok(Expression::Function(Box::new(Function::new(
640 "DATEADD".to_string(),
641 vec![unit, f.interval, f.this],
642 ))))
643 }
644
645 Expression::DateSub(f) => {
647 let unit_str = interval_unit_to_str(&f.unit);
648 let unit = Expression::Identifier(crate::expressions::Identifier {
649 name: unit_str,
650 quoted: false,
651 trailing_comments: Vec::new(),
652 span: None,
653 });
654 let neg_expr = Expression::Mul(Box::new(crate::expressions::BinaryOp::new(
656 f.interval,
657 Expression::Neg(Box::new(crate::expressions::UnaryOp {
658 this: Expression::number(1),
659 inferred_type: None,
660 })),
661 )));
662 Ok(Expression::Function(Box::new(Function::new(
663 "DATEADD".to_string(),
664 vec![unit, neg_expr, f.this],
665 ))))
666 }
667
668 Expression::DateDiff(f) => {
670 let unit_str =
671 interval_unit_to_str(&f.unit.unwrap_or(crate::expressions::IntervalUnit::Day));
672 let unit = Expression::Identifier(crate::expressions::Identifier {
673 name: unit_str,
674 quoted: false,
675 trailing_comments: Vec::new(),
676 span: None,
677 });
678 Ok(Expression::Function(Box::new(Function::new(
679 "DATEDIFF".to_string(),
680 vec![unit, f.expression, f.this],
681 ))))
682 }
683
684 Expression::StringAgg(f) => {
687 let mut args = vec![f.this.clone()];
688 if let Some(separator) = &f.separator {
689 args.push(separator.clone());
690 }
691 Ok(Expression::Function(Box::new(Function::new(
692 "LISTAGG".to_string(),
693 args,
694 ))))
695 }
696
697 Expression::StartsWith(f) => Ok(Expression::Function(Box::new(Function::new(
699 "STARTSWITH".to_string(),
700 vec![f.this, f.expression],
701 )))),
702
703 Expression::EndsWith(f) => Ok(Expression::EndsWith(f)),
705
706 Expression::Stuff(f) => {
708 let mut args = vec![*f.this];
709 if let Some(start) = f.start {
710 args.push(*start);
711 }
712 if let Some(length) = f.length {
713 args.push(Expression::number(length));
714 }
715 args.push(*f.expression);
716 Ok(Expression::Function(Box::new(Function::new(
717 "INSERT".to_string(),
718 args,
719 ))))
720 }
721
722 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
725 "SHA1".to_string(),
726 vec![f.this],
727 )))),
728
729 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
731 "SHA1_BINARY".to_string(),
732 vec![f.this],
733 )))),
734
735 Expression::SHA2Digest(f) => Ok(Expression::Function(Box::new(Function::new(
737 "SHA2_BINARY".to_string(),
738 vec![*f.this],
739 )))),
740
741 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
743 "MD5_BINARY".to_string(),
744 vec![*f.this],
745 )))),
746
747 Expression::MD5NumberLower64(f) => Ok(Expression::Function(Box::new(Function::new(
749 "MD5_NUMBER_LOWER64".to_string(),
750 vec![f.this],
751 )))),
752
753 Expression::MD5NumberUpper64(f) => Ok(Expression::Function(Box::new(Function::new(
755 "MD5_NUMBER_UPPER64".to_string(),
756 vec![f.this],
757 )))),
758
759 Expression::CosineDistance(f) => Ok(Expression::Function(Box::new(Function::new(
762 "VECTOR_COSINE_SIMILARITY".to_string(),
763 vec![*f.this, *f.expression],
764 )))),
765
766 Expression::DotProduct(f) => Ok(Expression::Function(Box::new(Function::new(
768 "VECTOR_INNER_PRODUCT".to_string(),
769 vec![*f.this, *f.expression],
770 )))),
771
772 Expression::EuclideanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
774 "VECTOR_L2_DISTANCE".to_string(),
775 vec![*f.this, *f.expression],
776 )))),
777
778 Expression::ManhattanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
780 "VECTOR_L1_DISTANCE".to_string(),
781 vec![*f.this, *f.expression],
782 )))),
783
784 Expression::JSONFormat(f) => {
787 let mut args = Vec::new();
788 if let Some(this) = f.this {
789 args.push(*this);
790 }
791 Ok(Expression::Function(Box::new(Function::new(
792 "TO_JSON".to_string(),
793 args,
794 ))))
795 }
796
797 Expression::JSONKeys(f) => Ok(Expression::Function(Box::new(Function::new(
799 "OBJECT_KEYS".to_string(),
800 vec![*f.this],
801 )))),
802
803 Expression::GetExtract(f) => Ok(Expression::Function(Box::new(Function::new(
805 "GET".to_string(),
806 vec![*f.this, *f.expression],
807 )))),
808
809 Expression::StarMap(f) => Ok(Expression::Function(Box::new(Function::new(
811 "OBJECT_CONSTRUCT".to_string(),
812 vec![f.this, f.expression],
813 )))),
814
815 Expression::LowerHex(f) => Ok(Expression::Function(Box::new(Function::new(
817 "TO_CHAR".to_string(),
818 vec![f.this],
819 )))),
820
821 Expression::Skewness(f) => Ok(Expression::Function(Box::new(Function::new(
823 "SKEW".to_string(),
824 vec![f.this],
825 )))),
826
827 Expression::StPoint(f) => Ok(Expression::Function(Box::new(Function::new(
829 "ST_MAKEPOINT".to_string(),
830 vec![*f.this, *f.expression],
831 )))),
832
833 Expression::FromTimeZone(f) => Ok(Expression::Function(Box::new(Function::new(
835 "CONVERT_TIMEZONE".to_string(),
836 vec![*f.this],
837 )))),
838
839 Expression::Unhex(f) => Ok(Expression::Function(Box::new(Function::new(
842 "HEX_DECODE_BINARY".to_string(),
843 vec![*f.this],
844 )))),
845
846 Expression::UnixToTime(f) => {
848 let mut args = vec![*f.this];
849 if let Some(scale) = f.scale {
850 args.push(Expression::number(scale));
851 }
852 Ok(Expression::Function(Box::new(Function::new(
853 "TO_TIMESTAMP".to_string(),
854 args,
855 ))))
856 }
857
858 Expression::IfFunc(f) => Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
861 condition: f.condition,
862 true_value: f.true_value,
863 false_value: Some(
864 f.false_value
865 .unwrap_or(Expression::Null(crate::expressions::Null)),
866 ),
867 original_name: Some("IFF".to_string()),
868 inferred_type: None,
869 }))),
870
871 Expression::ApproxDistinct(f) => Ok(Expression::Function(Box::new(Function::new(
874 "APPROX_COUNT_DISTINCT".to_string(),
875 vec![f.this],
876 )))),
877
878 Expression::ArgMax(f) => Ok(Expression::Function(Box::new(Function::new(
880 "MAX_BY".to_string(),
881 vec![*f.this, *f.expression],
882 )))),
883
884 Expression::ArgMin(f) => Ok(Expression::Function(Box::new(Function::new(
886 "MIN_BY".to_string(),
887 vec![*f.this, *f.expression],
888 )))),
889
890 Expression::Random(_) => Ok(Expression::Random(crate::expressions::Random)),
893
894 Expression::Rand(r) => Ok(Expression::Rand(r)),
896
897 Expression::Uuid(u) => Ok(Expression::Uuid(u)),
900
901 Expression::Map(f) => Ok(Expression::Function(Box::new(Function::new(
904 "OBJECT_CONSTRUCT".to_string(),
905 f.keys
906 .into_iter()
907 .zip(f.values.into_iter())
908 .flat_map(|(k, v)| vec![k, v])
909 .collect(),
910 )))),
911
912 Expression::MapFunc(f) => Ok(Expression::Function(Box::new(Function::new(
914 "OBJECT_CONSTRUCT".to_string(),
915 f.keys
916 .into_iter()
917 .zip(f.values.into_iter())
918 .flat_map(|(k, v)| vec![k, v])
919 .collect(),
920 )))),
921
922 Expression::VarMap(f) => Ok(Expression::Function(Box::new(Function::new(
924 "OBJECT_CONSTRUCT".to_string(),
925 f.keys
926 .into_iter()
927 .zip(f.values.into_iter())
928 .flat_map(|(k, v)| vec![k, v])
929 .collect(),
930 )))),
931
932 Expression::JsonObject(f) => Ok(Expression::Function(Box::new(Function::new(
935 "OBJECT_CONSTRUCT_KEEP_NULL".to_string(),
936 f.pairs.into_iter().flat_map(|(k, v)| vec![k, v]).collect(),
937 )))),
938
939 Expression::JsonExtractScalar(f) => Ok(Expression::Function(Box::new(Function::new(
941 "JSON_EXTRACT_PATH_TEXT".to_string(),
942 vec![f.this, f.path],
943 )))),
944
945 Expression::Struct(f) => Ok(Expression::Function(Box::new(Function::new(
948 "OBJECT_CONSTRUCT".to_string(),
949 f.fields
950 .into_iter()
951 .flat_map(|(name, expr)| {
952 let key = match name {
953 Some(n) => Expression::string(n),
954 None => Expression::Null(crate::expressions::Null),
955 };
956 vec![key, expr]
957 })
958 .collect(),
959 )))),
960
961 Expression::JSONPathRoot(_) => Ok(Expression::Literal(Box::new(crate::expressions::Literal::String(String::new()),))),
964
965 Expression::VarSamp(agg) => Ok(Expression::Variance(agg)),
968
969 Expression::VarPop(agg) => Ok(Expression::VarPop(agg)),
972
973 Expression::Extract(f) => {
976 use crate::expressions::DateTimeField;
977 let transformed_this = self.transform_expr(f.this)?;
979 let field_name = match &f.field {
980 DateTimeField::Year => "YEAR",
981 DateTimeField::Month => "MONTH",
982 DateTimeField::Day => "DAY",
983 DateTimeField::Hour => "HOUR",
984 DateTimeField::Minute => "MINUTE",
985 DateTimeField::Second => "SECOND",
986 DateTimeField::Millisecond => "MILLISECOND",
987 DateTimeField::Microsecond => "MICROSECOND",
988 DateTimeField::Week => "WEEK",
989 DateTimeField::WeekWithModifier(m) => {
990 return Ok(Expression::Function(Box::new(Function::new(
991 "DATE_PART".to_string(),
992 vec![
993 Expression::Identifier(crate::expressions::Identifier {
994 name: format!("WEEK({})", m),
995 quoted: false,
996 trailing_comments: Vec::new(),
997 span: None,
998 }),
999 transformed_this,
1000 ],
1001 ))))
1002 }
1003 DateTimeField::DayOfWeek => "DAYOFWEEK",
1004 DateTimeField::DayOfYear => "DAYOFYEAR",
1005 DateTimeField::Quarter => "QUARTER",
1006 DateTimeField::Epoch => "EPOCH",
1007 DateTimeField::Timezone => "TIMEZONE",
1008 DateTimeField::TimezoneHour => "TIMEZONE_HOUR",
1009 DateTimeField::TimezoneMinute => "TIMEZONE_MINUTE",
1010 DateTimeField::Date => "DATE",
1011 DateTimeField::Time => "TIME",
1012 DateTimeField::Custom(s) => {
1013 match s.to_uppercase().as_str() {
1015 "DAYOFMONTH" => "DAY",
1016 "DOW" => "DAYOFWEEK",
1017 "DOY" => "DAYOFYEAR",
1018 "ISODOW" => "DAYOFWEEKISO",
1019 "EPOCH_SECOND" | "EPOCH_SECONDS" => "EPOCH_SECOND",
1020 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => "EPOCH_MILLISECOND",
1021 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => "EPOCH_MICROSECOND",
1022 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => "EPOCH_NANOSECOND",
1023 _ => {
1024 return {
1025 let field_ident =
1026 Expression::Identifier(crate::expressions::Identifier {
1027 name: s.to_string(),
1028 quoted: false,
1029 trailing_comments: Vec::new(),
1030 span: None,
1031 });
1032 Ok(Expression::Function(Box::new(Function::new(
1033 "DATE_PART".to_string(),
1034 vec![field_ident, transformed_this],
1035 ))))
1036 }
1037 }
1038 }
1039 }
1040 };
1041 let field_ident = Expression::Identifier(crate::expressions::Identifier {
1042 name: field_name.to_string(),
1043 quoted: false,
1044 trailing_comments: Vec::new(),
1045 span: None,
1046 });
1047 Ok(Expression::Function(Box::new(Function::new(
1048 "DATE_PART".to_string(),
1049 vec![field_ident, transformed_this],
1050 ))))
1051 }
1052
1053 Expression::Function(f) => self.transform_function(*f),
1055
1056 Expression::Sum(mut agg) => {
1058 agg.this = self.transform_expr(agg.this)?;
1059 Ok(Expression::Sum(agg))
1060 }
1061
1062 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
1064
1065 Expression::NamedArgument(na) => {
1067 let transformed_value = self.transform_expr(na.value)?;
1068 Ok(Expression::NamedArgument(Box::new(
1069 crate::expressions::NamedArgument {
1070 name: na.name,
1071 value: transformed_value,
1072 separator: na.separator,
1073 },
1074 )))
1075 }
1076
1077 Expression::CreateTable(mut ct) => {
1079 for col in &mut ct.columns {
1080 if let Expression::DataType(new_dt) =
1081 self.transform_data_type(col.data_type.clone())?
1082 {
1083 col.data_type = new_dt;
1084 }
1085 if let Some(default_expr) = col.default.take() {
1087 col.default = Some(self.transform_expr(default_expr)?);
1088 }
1089 for constraint in &mut col.constraints {
1091 if let crate::expressions::ColumnConstraint::ComputedColumn(cc) = constraint
1092 {
1093 let transformed = self.transform_expr(*cc.expression.clone())?;
1094 cc.expression = Box::new(transformed);
1095 }
1096 }
1097 }
1098
1099 if ct.table_modifier.as_deref() == Some("EXTERNAL")
1102 && !ct.with_properties.is_empty()
1103 {
1104 for (key, value) in ct.with_properties.drain(..) {
1105 let formatted = Self::format_external_table_property(&key, &value);
1106 ct.properties
1107 .push(Expression::Raw(crate::expressions::Raw { sql: formatted }));
1108 }
1109 }
1110
1111 Ok(Expression::CreateTable(ct))
1112 }
1113
1114 Expression::AlterTable(mut at) => {
1116 for action in &mut at.actions {
1117 if let crate::expressions::AlterTableAction::AddColumn { column, .. } = action {
1118 if let Expression::DataType(new_dt) =
1119 self.transform_data_type(column.data_type.clone())?
1120 {
1121 column.data_type = new_dt;
1122 }
1123 }
1124 }
1125 Ok(Expression::AlterTable(at))
1126 }
1127
1128 Expression::Table(mut t) => {
1130 if let Some(when) = t.when.take() {
1131 let transformed_expr = self.transform_expr(*when.expression)?;
1133 t.when = Some(Box::new(crate::expressions::HistoricalData {
1134 this: when.this,
1135 kind: when.kind,
1136 expression: Box::new(transformed_expr),
1137 }));
1138 }
1139 Ok(Expression::Table(t))
1140 }
1141
1142 Expression::Subscript(s) => {
1144 let transformed_this = self.transform_expr(s.this)?;
1145 let transformed_index = self.transform_expr(s.index)?;
1146 Ok(Expression::Subscript(Box::new(
1147 crate::expressions::Subscript {
1148 this: transformed_this,
1149 index: transformed_index,
1150 },
1151 )))
1152 }
1153
1154 Expression::Paren(p) => {
1156 let transformed = self.transform_expr(p.this)?;
1157 Ok(Expression::Paren(Box::new(crate::expressions::Paren {
1158 this: transformed,
1159 trailing_comments: p.trailing_comments,
1160 })))
1161 }
1162
1163 Expression::Select(mut select) => {
1167 if let Some(ref mut order) = select.order_by {
1168 for ord in &mut order.expressions {
1169 if ord.nulls_first.is_none() {
1170 ord.nulls_first = Some(ord.desc);
1171 }
1172 }
1173 }
1174 Ok(Expression::Select(select))
1175 }
1176
1177 Expression::WindowFunction(mut wf) => {
1179 for ord in &mut wf.over.order_by {
1180 if ord.nulls_first.is_none() {
1181 ord.nulls_first = Some(ord.desc);
1182 }
1183 }
1184 Ok(Expression::WindowFunction(wf))
1185 }
1186
1187 Expression::Window(mut w) => {
1189 for ord in &mut w.order_by {
1190 if ord.nulls_first.is_none() {
1191 ord.nulls_first = Some(ord.desc);
1192 }
1193 }
1194 Ok(Expression::Window(w))
1195 }
1196
1197 Expression::Lateral(mut lat) => {
1199 let is_flatten = match lat.this.as_ref() {
1201 Expression::Function(f) => f.name.to_uppercase() == "FLATTEN",
1202 _ => false,
1203 };
1204 if is_flatten && lat.column_aliases.is_empty() {
1205 lat.column_aliases = vec![
1207 "SEQ".to_string(),
1208 "KEY".to_string(),
1209 "PATH".to_string(),
1210 "INDEX".to_string(),
1211 "VALUE".to_string(),
1212 "THIS".to_string(),
1213 ];
1214 if lat.alias.is_none() {
1216 lat.alias = Some("_flattened".to_string());
1217 }
1218 }
1219 Ok(Expression::Lateral(lat))
1220 }
1221
1222 _ => Ok(expr),
1224 }
1225 }
1226}
1227
1228impl SnowflakeDialect {
1229 fn format_external_table_property(key: &str, value: &str) -> String {
1232 let lower_key = key.to_lowercase();
1233 match lower_key.as_str() {
1234 "location" => format!("LOCATION={}", value),
1235 "file_format" => {
1236 let formatted_value = Self::format_file_format_value(value);
1238 format!("FILE_FORMAT={}", formatted_value)
1239 }
1240 _ => format!("{}={}", key, value),
1241 }
1242 }
1243
1244 fn format_file_format_value(value: &str) -> String {
1248 if !value.starts_with('(') {
1249 return value.to_string();
1250 }
1251 let inner = value[1..value.len() - 1].trim();
1253 let mut result = String::from("(");
1255 let mut parts: Vec<String> = Vec::new();
1256 let tokens: Vec<&str> = inner.split_whitespace().collect();
1258 let mut i = 0;
1259 while i < tokens.len() {
1260 let token = tokens[i];
1261 if i + 2 < tokens.len() && tokens[i + 1] == "=" {
1262 let val = Self::format_property_value(tokens[i + 2]);
1264 parts.push(format!("{}={}", token, val));
1265 i += 3;
1266 } else if token.contains('=') {
1267 let eq_pos = token.find('=').unwrap();
1269 let k = &token[..eq_pos];
1270 let v = Self::format_property_value(&token[eq_pos + 1..]);
1271 parts.push(format!("{}={}", k, v));
1272 i += 1;
1273 } else {
1274 parts.push(token.to_string());
1275 i += 1;
1276 }
1277 }
1278 result.push_str(&parts.join(" "));
1279 result.push(')');
1280 result
1281 }
1282
1283 fn format_property_value(value: &str) -> String {
1285 match value.to_lowercase().as_str() {
1286 "true" => "TRUE".to_string(),
1287 "false" => "FALSE".to_string(),
1288 _ => value.to_string(),
1289 }
1290 }
1291
1292 fn transform_data_type(&self, dt: crate::expressions::DataType) -> Result<Expression> {
1294 use crate::expressions::DataType;
1295 let transformed = match dt {
1296 DataType::Text => DataType::VarChar {
1298 length: None,
1299 parenthesized_length: false,
1300 },
1301 DataType::Struct { fields, .. } => {
1303 let _ = fields; DataType::Custom {
1306 name: "OBJECT".to_string(),
1307 }
1308 }
1309 DataType::Custom { name } => {
1311 let upper_name = name.to_uppercase();
1312 match upper_name.as_str() {
1313 "NVARCHAR" | "NCHAR" | "NATIONAL CHARACTER VARYING" | "NATIONAL CHAR" => {
1315 DataType::VarChar {
1316 length: None,
1317 parenthesized_length: false,
1318 }
1319 }
1320 "STRING" => DataType::VarChar {
1322 length: None,
1323 parenthesized_length: false,
1324 },
1325 "BIGDECIMAL" => DataType::Double {
1327 precision: None,
1328 scale: None,
1329 },
1330 "NESTED" => DataType::Custom {
1332 name: "OBJECT".to_string(),
1333 },
1334 "BYTEINT" => DataType::Int {
1336 length: None,
1337 integer_spelling: false,
1338 },
1339 "CHAR VARYING" | "CHARACTER VARYING" => DataType::VarChar {
1341 length: None,
1342 parenthesized_length: false,
1343 },
1344 "SQL_DOUBLE" => DataType::Double {
1346 precision: None,
1347 scale: None,
1348 },
1349 "SQL_VARCHAR" => DataType::VarChar {
1351 length: None,
1352 parenthesized_length: false,
1353 },
1354 "TIMESTAMP_NTZ" => DataType::Custom {
1356 name: "TIMESTAMPNTZ".to_string(),
1357 },
1358 "TIMESTAMP_LTZ" => DataType::Custom {
1360 name: "TIMESTAMPLTZ".to_string(),
1361 },
1362 "TIMESTAMP_TZ" => DataType::Custom {
1364 name: "TIMESTAMPTZ".to_string(),
1365 },
1366 "NCHAR VARYING" => DataType::VarChar {
1368 length: None,
1369 parenthesized_length: false,
1370 },
1371 "NUMBER" => DataType::Decimal {
1373 precision: Some(38),
1374 scale: Some(0),
1375 },
1376 _ if name.starts_with("NUMBER(") => {
1377 let inner = &name[7..name.len() - 1]; let parts: Vec<&str> = inner.split(',').map(|s| s.trim()).collect();
1381 let precision = parts.first().and_then(|p| p.parse::<u32>().ok());
1382 let scale = parts.get(1).and_then(|s| s.parse::<u32>().ok());
1383 DataType::Decimal { precision, scale }
1384 }
1385 _ => DataType::Custom { name },
1386 }
1387 }
1388 DataType::Decimal {
1390 precision: None,
1391 scale: None,
1392 } => DataType::Decimal {
1393 precision: Some(38),
1394 scale: Some(0),
1395 },
1396 DataType::Float { .. } => DataType::Double {
1398 precision: None,
1399 scale: None,
1400 },
1401 other => other,
1403 };
1404 Ok(Expression::DataType(transformed))
1405 }
1406
1407 fn map_date_part(abbr: &str) -> Option<&'static str> {
1409 match abbr.to_uppercase().as_str() {
1410 "Y" | "YY" | "YYY" | "YYYY" | "YR" | "YEARS" | "YRS" => Some("YEAR"),
1412 "MM" | "MON" | "MONS" | "MONTHS" => Some("MONTH"),
1414 "D" | "DD" | "DAYS" | "DAYOFMONTH" => Some("DAY"),
1416 "DAY OF WEEK" | "WEEKDAY" | "DOW" | "DW" => Some("DAYOFWEEK"),
1418 "WEEKDAY_ISO" | "DOW_ISO" | "DW_ISO" | "DAYOFWEEK_ISO" => Some("DAYOFWEEKISO"),
1419 "DAY OF YEAR" | "DOY" | "DY" => Some("DAYOFYEAR"),
1421 "W" | "WK" | "WEEKOFYEAR" | "WOY" | "WY" => Some("WEEK"),
1423 "WEEK_ISO" | "WEEKOFYEARISO" | "WEEKOFYEAR_ISO" => Some("WEEKISO"),
1424 "Q" | "QTR" | "QTRS" | "QUARTERS" => Some("QUARTER"),
1426 "H" | "HH" | "HR" | "HOURS" | "HRS" => Some("HOUR"),
1428 "MI" | "MIN" | "MINUTES" | "MINS" => Some("MINUTE"),
1430 "S" | "SEC" | "SECONDS" | "SECS" => Some("SECOND"),
1432 "MS" | "MSEC" | "MSECS" | "MSECOND" | "MSECONDS" | "MILLISEC" | "MILLISECS"
1434 | "MILLISECON" | "MILLISECONDS" => Some("MILLISECOND"),
1435 "US" | "USEC" | "USECS" | "MICROSEC" | "MICROSECS" | "USECOND" | "USECONDS"
1437 | "MICROSECONDS" => Some("MICROSECOND"),
1438 "NS" | "NSEC" | "NANOSEC" | "NSECOND" | "NSECONDS" | "NANOSECS" => Some("NANOSECOND"),
1440 "EPOCH_SECOND" | "EPOCH_SECONDS" => Some("EPOCH_SECOND"),
1442 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Some("EPOCH_MILLISECOND"),
1443 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Some("EPOCH_MICROSECOND"),
1444 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Some("EPOCH_NANOSECOND"),
1445 "TZH" => Some("TIMEZONE_HOUR"),
1447 "TZM" => Some("TIMEZONE_MINUTE"),
1448 "DEC" | "DECS" | "DECADES" => Some("DECADE"),
1450 "MIL" | "MILS" | "MILLENIA" => Some("MILLENNIUM"),
1452 "C" | "CENT" | "CENTS" | "CENTURIES" => Some("CENTURY"),
1454 _ => None,
1456 }
1457 }
1458
1459 fn transform_date_part_arg(&self, expr: Expression) -> Expression {
1461 match &expr {
1462 Expression::Literal(lit) if matches!(lit.as_ref(), crate::expressions::Literal::String(_)) => {
1464 let crate::expressions::Literal::String(s) = lit.as_ref() else { unreachable!() };
1465 Expression::Identifier(crate::expressions::Identifier {
1466 name: s.clone(),
1467 quoted: false,
1468 trailing_comments: Vec::new(),
1469 span: None,
1470 })
1471 }
1472 Expression::Identifier(id) => {
1474 if let Some(canonical) = Self::map_date_part(&id.name) {
1475 Expression::Identifier(crate::expressions::Identifier {
1476 name: canonical.to_string(),
1477 quoted: false,
1478 trailing_comments: Vec::new(),
1479 span: None,
1480 })
1481 } else {
1482 expr
1484 }
1485 }
1486 Expression::Var(v) => {
1487 if let Some(canonical) = Self::map_date_part(&v.this) {
1488 Expression::Identifier(crate::expressions::Identifier {
1489 name: canonical.to_string(),
1490 quoted: false,
1491 trailing_comments: Vec::new(),
1492 span: None,
1493 })
1494 } else {
1495 expr
1496 }
1497 }
1498 Expression::Column(col) if col.table.is_none() => {
1500 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1501 Expression::Identifier(crate::expressions::Identifier {
1502 name: canonical.to_string(),
1503 quoted: false,
1504 trailing_comments: Vec::new(),
1505 span: None,
1506 })
1507 } else {
1508 expr
1510 }
1511 }
1512 _ => expr,
1513 }
1514 }
1515
1516 fn transform_date_part_arg_identifiers_only(&self, expr: Expression) -> Expression {
1519 match &expr {
1520 Expression::Identifier(id) => {
1521 if let Some(canonical) = Self::map_date_part(&id.name) {
1522 Expression::Identifier(crate::expressions::Identifier {
1523 name: canonical.to_string(),
1524 quoted: false,
1525 trailing_comments: Vec::new(),
1526 span: None,
1527 })
1528 } else {
1529 expr
1530 }
1531 }
1532 Expression::Var(v) => {
1533 if let Some(canonical) = Self::map_date_part(&v.this) {
1534 Expression::Identifier(crate::expressions::Identifier {
1535 name: canonical.to_string(),
1536 quoted: false,
1537 trailing_comments: Vec::new(),
1538 span: None,
1539 })
1540 } else {
1541 expr
1542 }
1543 }
1544 Expression::Column(col) if col.table.is_none() => {
1545 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1546 Expression::Identifier(crate::expressions::Identifier {
1547 name: canonical.to_string(),
1548 quoted: false,
1549 trailing_comments: Vec::new(),
1550 span: None,
1551 })
1552 } else {
1553 expr
1554 }
1555 }
1556 _ => expr,
1557 }
1558 }
1559
1560 fn transform_json_path(path: &str) -> String {
1564 fn is_safe_identifier(s: &str) -> bool {
1567 if s.is_empty() {
1568 return false;
1569 }
1570 let mut chars = s.chars();
1571 match chars.next() {
1572 Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
1573 _ => return false,
1574 }
1575 chars.all(|c| c.is_ascii_alphanumeric() || c == '_')
1576 }
1577
1578 if !path.contains('.') && !path.contains('[') && !path.contains(':') {
1581 if is_safe_identifier(path) {
1582 return path.to_string();
1583 } else {
1584 return format!("[\"{}\"]", path);
1586 }
1587 }
1588
1589 let result = path.replace(':', ".");
1592 result
1593 }
1594
1595 fn transform_interval(&self, interval: crate::expressions::Interval) -> Result<Expression> {
1597 use crate::expressions::{Interval, Literal};
1598
1599 fn expand_unit(abbr: &str) -> &'static str {
1601 match abbr.to_uppercase().as_str() {
1602 "D" => "DAY",
1603 "H" => "HOUR",
1604 "M" => "MINUTE",
1605 "MS" => "MILLISECOND",
1606 "NS" => "NANOSECOND",
1607 "Q" => "QUARTER",
1608 "S" => "SECOND",
1609 "US" => "MICROSECOND",
1610 "W" => "WEEK",
1611 "Y" => "YEAR",
1612 "WEEK" | "WEEKS" => "WEEK",
1614 "DAY" | "DAYS" => "DAY",
1615 "HOUR" | "HOURS" => "HOUR",
1616 "MINUTE" | "MINUTES" => "MINUTE",
1617 "SECOND" | "SECONDS" => "SECOND",
1618 "MONTH" | "MONTHS" => "MONTH",
1619 "YEAR" | "YEARS" => "YEAR",
1620 "QUARTER" | "QUARTERS" => "QUARTER",
1621 "MILLISECOND" | "MILLISECONDS" => "MILLISECOND",
1622 "MICROSECOND" | "MICROSECONDS" => "MICROSECOND",
1623 "NANOSECOND" | "NANOSECONDS" => "NANOSECOND",
1624 _ => "", }
1626 }
1627
1628 fn parse_interval_string(s: &str) -> Option<(&str, &str)> {
1630 let s = s.trim();
1631
1632 let mut num_end = 0;
1635 let mut chars = s.chars().peekable();
1636
1637 if chars.peek() == Some(&'-') {
1639 chars.next();
1640 num_end += 1;
1641 }
1642
1643 while let Some(&c) = chars.peek() {
1645 if c.is_ascii_digit() {
1646 chars.next();
1647 num_end += 1;
1648 } else {
1649 break;
1650 }
1651 }
1652
1653 if chars.peek() == Some(&'.') {
1655 chars.next();
1656 num_end += 1;
1657 while let Some(&c) = chars.peek() {
1658 if c.is_ascii_digit() {
1659 chars.next();
1660 num_end += 1;
1661 } else {
1662 break;
1663 }
1664 }
1665 }
1666
1667 if num_end == 0 || (num_end == 1 && s.starts_with('-')) {
1668 return None; }
1670
1671 let value = &s[..num_end];
1672 let rest = s[num_end..].trim();
1673
1674 if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_alphabetic()) {
1676 return None;
1677 }
1678
1679 Some((value, rest))
1680 }
1681
1682 if let Some(Expression::Literal(ref lit)) = interval.this {
1684 if let Literal::String(ref s) = lit.as_ref() {
1685 if let Some((value, unit)) = parse_interval_string(s) {
1686 let expanded = expand_unit(unit);
1687 if !expanded.is_empty() {
1688 let new_value = format!("{} {}", value, expanded);
1690
1691 return Ok(Expression::Interval(Box::new(Interval {
1692 this: Some(Expression::Literal(Box::new(Literal::String(new_value)))),
1693 unit: None, })));
1695 }
1696 }
1697 }
1698 }
1699
1700 Ok(Expression::Interval(Box::new(interval)))
1702 }
1703
1704 fn transform_function(&self, f: Function) -> Result<Expression> {
1705 let transformed_args: Vec<Expression> = f
1707 .args
1708 .into_iter()
1709 .map(|arg| self.transform_expr(arg))
1710 .collect::<Result<Vec<_>>>()?;
1711
1712 let f = Function {
1713 name: f.name,
1714 args: transformed_args,
1715 distinct: f.distinct,
1716 trailing_comments: f.trailing_comments,
1717 use_bracket_syntax: f.use_bracket_syntax,
1718 no_parens: f.no_parens,
1719 quoted: f.quoted,
1720 span: None,
1721 inferred_type: None,
1722 };
1723
1724 let name_upper = f.name.to_uppercase();
1725 match name_upper.as_str() {
1726 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1728 original_name: None,
1729 expressions: f.args,
1730 inferred_type: None,
1731 }))),
1732
1733 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1735 original_name: None,
1736 expressions: f.args,
1737 inferred_type: None,
1738 }))),
1739
1740 "NVL2" => Ok(Expression::Function(Box::new(f))),
1742
1743 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1745 Function::new("LISTAGG".to_string(), f.args),
1746 ))),
1747
1748 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1750 Function::new("LISTAGG".to_string(), f.args),
1751 ))),
1752
1753 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
1755 "SUBSTRING".to_string(),
1756 f.args,
1757 )))),
1758
1759 "UNNEST" => Ok(Expression::Function(Box::new(Function::new(
1761 "FLATTEN".to_string(),
1762 f.args,
1763 )))),
1764
1765 "EXPLODE" => Ok(Expression::Function(Box::new(Function::new(
1767 "FLATTEN".to_string(),
1768 f.args,
1769 )))),
1770
1771 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1773
1774 "NOW" => Ok(Expression::Function(Box::new(Function {
1776 name: "CURRENT_TIMESTAMP".to_string(),
1777 args: f.args,
1778 distinct: false,
1779 trailing_comments: Vec::new(),
1780 use_bracket_syntax: false,
1781 no_parens: f.no_parens,
1782 quoted: false,
1783 span: None,
1784 inferred_type: None,
1785 }))),
1786
1787 "GETDATE" => Ok(Expression::Function(Box::new(Function {
1789 name: "CURRENT_TIMESTAMP".to_string(),
1790 args: f.args,
1791 distinct: false,
1792 trailing_comments: Vec::new(),
1793 use_bracket_syntax: false,
1794 no_parens: f.no_parens,
1795 quoted: false,
1796 span: None,
1797 inferred_type: None,
1798 }))),
1799
1800 "CURRENT_TIMESTAMP" if f.args.is_empty() => {
1804 Ok(Expression::Function(Box::new(Function {
1805 name: "CURRENT_TIMESTAMP".to_string(),
1806 args: Vec::new(),
1807 distinct: false,
1808 trailing_comments: Vec::new(),
1809 use_bracket_syntax: false,
1810 no_parens: false, quoted: false,
1812 span: None,
1813 inferred_type: None,
1814 })))
1815 }
1816
1817 "TO_DATE" => {
1821 if f.args.len() == 1 {
1822 if let Expression::Literal(lit) = &f.args[0]
1823 {
1824 if let crate::expressions::Literal::String(s) = lit.as_ref() {
1825 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
1827 return Ok(Expression::Cast(Box::new(Cast {
1828 this: f.args.into_iter().next().unwrap(),
1829 to: crate::expressions::DataType::Date,
1830 double_colon_syntax: false,
1831 trailing_comments: Vec::new(),
1832 format: None,
1833 default: None,
1834 inferred_type: None,
1835 })));
1836 }
1837 }
1838 }
1839 }
1840 let mut args = f.args;
1842 if args.len() >= 2 {
1843 args[1] = Self::normalize_format_arg(args[1].clone());
1844 }
1845 Ok(Expression::Function(Box::new(Function::new(
1846 "TO_DATE".to_string(),
1847 args,
1848 ))))
1849 }
1850
1851 "TO_TIME" => {
1853 if f.args.len() == 1 {
1854 if let Expression::Literal(lit) = &f.args[0]
1855 {
1856 if let crate::expressions::Literal::String(_) = lit.as_ref() {
1857 return Ok(Expression::Cast(Box::new(Cast {
1858 this: f.args.into_iter().next().unwrap(),
1859 to: crate::expressions::DataType::Time {
1860 precision: None,
1861 timezone: false,
1862 },
1863 double_colon_syntax: false,
1864 trailing_comments: Vec::new(),
1865 format: None,
1866 default: None,
1867 inferred_type: None,
1868 })));
1869 }
1870 }
1871 }
1872 let mut args = f.args;
1874 if args.len() >= 2 {
1875 args[1] = Self::normalize_format_arg(args[1].clone());
1876 }
1877 Ok(Expression::Function(Box::new(Function::new(
1878 "TO_TIME".to_string(),
1879 args,
1880 ))))
1881 }
1882
1883 "TO_TIMESTAMP" => {
1890 let args = f.args;
1891 if args.len() == 1 {
1892 let arg = &args[0];
1893 match arg {
1894 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(s) if Self::looks_like_datetime(s)) => {
1895 let Literal::String(_) = lit.as_ref() else { unreachable!() };
1896 return Ok(Expression::Cast(Box::new(Cast {
1898 this: args.into_iter().next().unwrap(),
1899 to: DataType::Timestamp {
1900 precision: None,
1901 timezone: false,
1902 },
1903 double_colon_syntax: false,
1904 trailing_comments: vec![],
1905 format: None,
1906 default: None,
1907 inferred_type: None,
1908 })));
1909 }
1910 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(s) if Self::looks_like_epoch(s)) => {
1911 let Literal::String(_) = lit.as_ref() else { unreachable!() };
1912 return Ok(Expression::UnixToTime(Box::new(
1914 crate::expressions::UnixToTime {
1915 this: Box::new(args.into_iter().next().unwrap()),
1916 scale: None,
1917 zone: None,
1918 hours: None,
1919 minutes: None,
1920 format: None,
1921 target_type: None,
1922 },
1923 )));
1924 }
1925 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => {
1926 return Ok(Expression::UnixToTime(Box::new(
1928 crate::expressions::UnixToTime {
1929 this: Box::new(args.into_iter().next().unwrap()),
1930 scale: None,
1931 zone: None,
1932 hours: None,
1933 minutes: None,
1934 format: None,
1935 target_type: None,
1936 },
1937 )));
1938 }
1939 Expression::Neg(_) => {
1940 return Ok(Expression::UnixToTime(Box::new(
1942 crate::expressions::UnixToTime {
1943 this: Box::new(args.into_iter().next().unwrap()),
1944 scale: None,
1945 zone: None,
1946 hours: None,
1947 minutes: None,
1948 format: None,
1949 target_type: None,
1950 },
1951 )));
1952 }
1953 _ => {
1954 return Ok(Expression::Function(Box::new(Function::new(
1956 "TO_TIMESTAMP".to_string(),
1957 args,
1958 ))));
1959 }
1960 }
1961 } else if args.len() == 2 {
1962 let second_arg = &args[1];
1963 let is_int_scale = match second_arg {
1965 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)) => { let Literal::Number(n) = lit.as_ref() else { unreachable!() }; n.parse::<i64>().is_ok() },
1966 _ => false,
1967 };
1968
1969 if is_int_scale {
1970 let mut args_iter = args.into_iter();
1972 let value = args_iter.next().unwrap();
1973 let scale_expr = args_iter.next().unwrap();
1974 let scale = if let Expression::Literal(lit) = &scale_expr {
1975 if let Literal::Number(n) = lit.as_ref() {
1976 n.parse::<i64>().ok()
1977 } else { None }
1978 } else {
1979 None
1980 };
1981 return Ok(Expression::UnixToTime(Box::new(
1982 crate::expressions::UnixToTime {
1983 this: Box::new(value),
1984 scale,
1985 zone: None,
1986 hours: None,
1987 minutes: None,
1988 format: None,
1989 target_type: None,
1990 },
1991 )));
1992 } else {
1993 let mut args_iter = args.into_iter();
1995 let value = args_iter.next().unwrap();
1996 let format_expr = args_iter.next().unwrap();
1997 let format_str = match &format_expr {
1998 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => { let Literal::String(s) = lit.as_ref() else { unreachable!() }; s.clone() },
1999 _ => {
2000 return Ok(Expression::Function(Box::new(Function::new(
2002 "TO_TIMESTAMP".to_string(),
2003 vec![value, format_expr],
2004 ))));
2005 }
2006 };
2007 let normalized_format = Self::normalize_snowflake_format(&format_str);
2009 return Ok(Expression::StrToTime(Box::new(
2010 crate::expressions::StrToTime {
2011 this: Box::new(value),
2012 format: normalized_format,
2013 zone: None,
2014 safe: None,
2015 target_type: None,
2016 },
2017 )));
2018 }
2019 }
2020 Ok(Expression::Function(Box::new(Function::new(
2022 "TO_TIMESTAMP".to_string(),
2023 args,
2024 ))))
2025 }
2026
2027 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
2029
2030 "ROUND"
2033 if f.args
2034 .iter()
2035 .any(|a| matches!(a, Expression::NamedArgument(_))) =>
2036 {
2037 let mut expr_val = None;
2038 let mut scale_val = None;
2039 let mut rounding_mode_val = None;
2040 for arg in &f.args {
2041 if let Expression::NamedArgument(na) = arg {
2042 match na.name.name.to_uppercase().as_str() {
2043 "EXPR" => expr_val = Some(na.value.clone()),
2044 "SCALE" => scale_val = Some(na.value.clone()),
2045 "ROUNDING_MODE" => rounding_mode_val = Some(na.value.clone()),
2046 _ => {}
2047 }
2048 }
2049 }
2050 if let Some(expr) = expr_val {
2051 let mut args = vec![expr];
2052 if let Some(scale) = scale_val {
2053 args.push(scale);
2054 }
2055 if let Some(mode) = rounding_mode_val {
2056 args.push(mode);
2057 }
2058 Ok(Expression::Function(Box::new(Function::new(
2059 "ROUND".to_string(),
2060 args,
2061 ))))
2062 } else {
2063 Ok(Expression::Function(Box::new(f)))
2064 }
2065 }
2066
2067 "DATE_FORMAT" => {
2070 let mut args = f.args;
2071 if !args.is_empty() {
2073 if matches!(&args[0], Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_))) {
2074 args[0] = Expression::Cast(Box::new(crate::expressions::Cast {
2075 this: args[0].clone(),
2076 to: DataType::Timestamp {
2077 precision: None,
2078 timezone: false,
2079 },
2080 trailing_comments: Vec::new(),
2081 double_colon_syntax: false,
2082 format: None,
2083 default: None,
2084 inferred_type: None,
2085 }));
2086 }
2087 }
2088 if args.len() >= 2 {
2090 if let Expression::Literal(ref lit) = args[1] {
2091 if let Literal::String(ref fmt) = lit.as_ref() {
2092 let sf_fmt = strftime_to_snowflake_format(fmt);
2093 args[1] = Expression::Literal(Box::new(Literal::String(sf_fmt)));
2094 }
2095 }
2096 }
2097 Ok(Expression::Function(Box::new(Function::new(
2098 "TO_CHAR".to_string(),
2099 args,
2100 ))))
2101 }
2102
2103 "ARRAY" => Ok(Expression::Function(Box::new(Function::new(
2105 "ARRAY_CONSTRUCT".to_string(),
2106 f.args,
2107 )))),
2108
2109 "STRUCT" => {
2112 let mut oc_args = Vec::new();
2113 for arg in f.args {
2114 match arg {
2115 Expression::Alias(a) => {
2116 oc_args.push(Expression::Literal(Box::new(crate::expressions::Literal::String(
2118 a.alias.name.clone(),
2119 ))));
2120 oc_args.push(a.this);
2121 }
2122 other => {
2123 oc_args.push(other);
2125 }
2126 }
2127 }
2128 Ok(Expression::Function(Box::new(Function::new(
2129 "OBJECT_CONSTRUCT".to_string(),
2130 oc_args,
2131 ))))
2132 }
2133
2134 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2136 "GET_PATH".to_string(),
2137 f.args,
2138 )))),
2139
2140 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
2142 "JSON_EXTRACT_PATH_TEXT".to_string(),
2143 f.args,
2144 )))),
2145
2146 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
2148 f.args.into_iter().next().unwrap(),
2149 )))),
2150
2151 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
2153 this: f.args.into_iter().next().unwrap(),
2154 decimals: None,
2155 to: None,
2156 }))),
2157
2158 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
2160
2161 "SPLIT" => Ok(Expression::Function(Box::new(f))),
2163
2164 "ARRAY_AGG" => Ok(Expression::Function(Box::new(f))),
2166
2167 "JSON_PARSE" | "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
2169 "PARSE_JSON".to_string(),
2170 f.args,
2171 )))),
2172
2173 "RAND" => {
2175 let seed = f.args.first().cloned().map(Box::new);
2176 Ok(Expression::Rand(Box::new(crate::expressions::Rand {
2177 seed,
2178 lower: None,
2179 upper: None,
2180 })))
2181 }
2182
2183 "SHA" => Ok(Expression::Function(Box::new(Function::new(
2185 "SHA1".to_string(),
2186 f.args,
2187 )))),
2188
2189 "APPROX_DISTINCT" => Ok(Expression::Function(Box::new(Function::new(
2191 "APPROX_COUNT_DISTINCT".to_string(),
2192 f.args,
2193 )))),
2194
2195 "GEN_RANDOM_UUID" | "UUID" => {
2197 Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2198 this: None,
2199 name: None,
2200 is_string: None,
2201 })))
2202 }
2203
2204 "NEWID" => Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2206 this: None,
2207 name: None,
2208 is_string: None,
2209 }))),
2210
2211 "UUID_STRING" => {
2213 if f.args.is_empty() {
2214 Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2215 this: None,
2216 name: None,
2217 is_string: None,
2218 })))
2219 } else {
2220 Ok(Expression::Function(Box::new(Function::new(
2221 "UUID_STRING".to_string(),
2222 f.args,
2223 ))))
2224 }
2225 }
2226
2227 "IF" if f.args.len() >= 2 => {
2229 let mut args = f.args;
2230 let condition = args.remove(0);
2231 let true_val = args.remove(0);
2232 let false_val = if !args.is_empty() {
2233 Some(args.remove(0))
2234 } else {
2235 None
2236 };
2237 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2238 condition,
2239 true_value: true_val,
2240 false_value: Some(
2241 false_val.unwrap_or(Expression::Null(crate::expressions::Null)),
2242 ),
2243 original_name: Some("IFF".to_string()),
2244 inferred_type: None,
2245 })))
2246 }
2247
2248 "SQUARE" if f.args.len() == 1 => {
2250 let x = f.args.into_iter().next().unwrap();
2251 Ok(Expression::Power(Box::new(
2252 crate::expressions::BinaryFunc {
2253 original_name: None,
2254 this: x,
2255 expression: Expression::number(2),
2256 inferred_type: None,
2257 },
2258 )))
2259 }
2260
2261 "POW" if f.args.len() == 2 => {
2263 let mut args = f.args.into_iter();
2264 let x = args.next().unwrap();
2265 let y = args.next().unwrap();
2266 Ok(Expression::Power(Box::new(
2267 crate::expressions::BinaryFunc {
2268 original_name: None,
2269 this: x,
2270 expression: y,
2271 inferred_type: None,
2272 },
2273 )))
2274 }
2275
2276 "MOD" if f.args.len() == 2 => {
2278 let mut args = f.args.into_iter();
2279 let x = args.next().unwrap();
2280 let y = args.next().unwrap();
2281 Ok(Expression::Mod(Box::new(crate::expressions::BinaryOp {
2282 left: x,
2283 right: y,
2284 left_comments: Vec::new(),
2285 operator_comments: Vec::new(),
2286 trailing_comments: Vec::new(),
2287 inferred_type: None,
2288 })))
2289 }
2290
2291 "APPROXIMATE_JACCARD_INDEX" => Ok(Expression::Function(Box::new(Function::new(
2293 "APPROXIMATE_SIMILARITY".to_string(),
2294 f.args,
2295 )))),
2296
2297 "ARRAY_CONSTRUCT" => Ok(Expression::ArrayFunc(Box::new(
2299 crate::expressions::ArrayConstructor {
2300 expressions: f.args,
2301 bracket_notation: true,
2302 use_list_keyword: false,
2303 },
2304 ))),
2305
2306 "APPROX_TOP_K" if f.args.len() == 1 => {
2308 let mut args = f.args;
2309 args.push(Expression::number(1));
2310 Ok(Expression::Function(Box::new(Function::new(
2311 "APPROX_TOP_K".to_string(),
2312 args,
2313 ))))
2314 }
2315
2316 "TO_DECIMAL" | "TO_NUMERIC" => Ok(Expression::Function(Box::new(Function::new(
2318 "TO_NUMBER".to_string(),
2319 f.args,
2320 )))),
2321
2322 "TRY_TO_DECIMAL" | "TRY_TO_NUMERIC" => Ok(Expression::Function(Box::new(
2324 Function::new("TRY_TO_NUMBER".to_string(), f.args),
2325 ))),
2326
2327 "STDDEV_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2329 "STDDEV".to_string(),
2330 f.args,
2331 )))),
2332
2333 "STRTOK" if f.args.len() >= 1 => {
2335 let mut args = f.args;
2336 if args.len() == 1 {
2338 args.push(Expression::string(" ".to_string()));
2339 }
2340 if args.len() == 2 {
2342 args.push(Expression::number(1));
2343 }
2344 Ok(Expression::Function(Box::new(Function::new(
2345 "SPLIT_PART".to_string(),
2346 args,
2347 ))))
2348 }
2349
2350 "WEEKOFYEAR" => Ok(Expression::Function(Box::new(Function::new(
2352 "WEEK".to_string(),
2353 f.args,
2354 )))),
2355
2356 "LIKE" if f.args.len() >= 2 => {
2358 let mut args = f.args.into_iter();
2359 let left = args.next().unwrap();
2360 let right = args.next().unwrap();
2361 let escape = args.next();
2362 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
2363 left,
2364 right,
2365 escape,
2366 quantifier: None,
2367 inferred_type: None,
2368 })))
2369 }
2370
2371 "ILIKE" if f.args.len() >= 2 => {
2373 let mut args = f.args.into_iter();
2374 let left = args.next().unwrap();
2375 let right = args.next().unwrap();
2376 let escape = args.next();
2377 Ok(Expression::ILike(Box::new(crate::expressions::LikeOp {
2378 left,
2379 right,
2380 escape,
2381 quantifier: None,
2382 inferred_type: None,
2383 })))
2384 }
2385
2386 "RLIKE" if f.args.len() >= 2 => {
2388 let mut args = f.args.into_iter();
2389 let left = args.next().unwrap();
2390 let pattern = args.next().unwrap();
2391 let flags = args.next();
2392 Ok(Expression::RegexpLike(Box::new(
2393 crate::expressions::RegexpFunc {
2394 this: left,
2395 pattern,
2396 flags,
2397 },
2398 )))
2399 }
2400
2401 "IFF" if f.args.len() >= 2 => {
2403 let mut args = f.args;
2404 let condition = args.remove(0);
2405 let true_value = args.remove(0);
2406 let false_value = if !args.is_empty() {
2407 Some(args.remove(0))
2408 } else {
2409 None
2410 };
2411 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2412 condition,
2413 true_value,
2414 false_value,
2415 original_name: Some("IFF".to_string()),
2416 inferred_type: None,
2417 })))
2418 }
2419
2420 "TIMESTAMP_NTZ_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMPNTZFROMPARTS" => {
2422 Ok(Expression::Function(Box::new(Function::new(
2423 "TIMESTAMP_FROM_PARTS".to_string(),
2424 f.args,
2425 ))))
2426 }
2427
2428 "TIMESTAMPLTZFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2430 "TIMESTAMP_LTZ_FROM_PARTS".to_string(),
2431 f.args,
2432 )))),
2433
2434 "TIMESTAMPTZFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2436 "TIMESTAMP_TZ_FROM_PARTS".to_string(),
2437 f.args,
2438 )))),
2439
2440 "DATEADD" if f.args.len() >= 1 => {
2442 let mut args = f.args;
2443 args[0] = self.transform_date_part_arg(args[0].clone());
2444 Ok(Expression::Function(Box::new(Function::new(
2445 "DATEADD".to_string(),
2446 args,
2447 ))))
2448 }
2449
2450 "DATEDIFF" if f.args.len() >= 1 => {
2453 let mut args = f.args;
2454 args[0] = self.transform_date_part_arg(args[0].clone());
2455 for i in 1..args.len() {
2458 if let Expression::Function(ref func) = args[i] {
2459 if func.name == "_POLYGLOT_TO_DATE" {
2460 let inner_args = func.args.clone();
2461 args[i] = Expression::Function(Box::new(Function::new(
2462 "TO_DATE".to_string(),
2463 inner_args,
2464 )));
2465 }
2466 }
2467 }
2468 Ok(Expression::Function(Box::new(Function::new(
2469 "DATEDIFF".to_string(),
2470 args,
2471 ))))
2472 }
2473
2474 "TIMEDIFF" => Ok(Expression::Function(Box::new(Function::new(
2476 "DATEDIFF".to_string(),
2477 f.args,
2478 )))),
2479
2480 "TIMESTAMPDIFF" => Ok(Expression::Function(Box::new(Function::new(
2482 "DATEDIFF".to_string(),
2483 f.args,
2484 )))),
2485
2486 "TIMESTAMPADD" => Ok(Expression::Function(Box::new(Function::new(
2488 "DATEADD".to_string(),
2489 f.args,
2490 )))),
2491
2492 "TIMEADD" => Ok(Expression::Function(Box::new(f))),
2494
2495 "DATEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2497 "DATE_FROM_PARTS".to_string(),
2498 f.args,
2499 )))),
2500
2501 "TIMEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2503 "TIME_FROM_PARTS".to_string(),
2504 f.args,
2505 )))),
2506
2507 "DAYOFWEEK" => Ok(Expression::Function(Box::new(f))),
2509
2510 "DAYOFMONTH" => Ok(Expression::Function(Box::new(f))),
2512
2513 "DAYOFYEAR" => Ok(Expression::Function(Box::new(f))),
2515
2516 "MONTHNAME" if f.args.len() == 1 => {
2519 let arg = f.args.into_iter().next().unwrap();
2520 Ok(Expression::Monthname(Box::new(
2521 crate::expressions::Monthname {
2522 this: Box::new(arg),
2523 abbreviated: Some(Box::new(Expression::Literal(Box::new(Literal::String(
2524 "true".to_string(),
2525 ))))),
2526 },
2527 )))
2528 }
2529
2530 "DAYNAME" if f.args.len() == 1 => {
2533 let arg = f.args.into_iter().next().unwrap();
2534 Ok(Expression::Dayname(Box::new(crate::expressions::Dayname {
2535 this: Box::new(arg),
2536 abbreviated: Some(Box::new(Expression::Literal(Box::new(Literal::String(
2537 "true".to_string(),
2538 ))))),
2539 })))
2540 }
2541
2542 "BOOLAND_AGG" | "BOOL_AND" | "LOGICAL_AND" if !f.args.is_empty() => {
2544 let arg = f.args.into_iter().next().unwrap();
2545 Ok(Expression::LogicalAnd(Box::new(AggFunc {
2546 this: arg,
2547 distinct: false,
2548 filter: None,
2549 order_by: Vec::new(),
2550 name: Some("BOOLAND_AGG".to_string()),
2551 ignore_nulls: None,
2552 having_max: None,
2553 limit: None,
2554 inferred_type: None,
2555 })))
2556 }
2557
2558 "BOOLOR_AGG" | "BOOL_OR" | "LOGICAL_OR" if !f.args.is_empty() => {
2560 let arg = f.args.into_iter().next().unwrap();
2561 Ok(Expression::LogicalOr(Box::new(AggFunc {
2562 this: arg,
2563 distinct: false,
2564 filter: None,
2565 order_by: Vec::new(),
2566 name: Some("BOOLOR_AGG".to_string()),
2567 ignore_nulls: None,
2568 having_max: None,
2569 limit: None,
2570 inferred_type: None,
2571 })))
2572 }
2573
2574 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
2576 let arg = f.args.into_iter().next().unwrap();
2577 Ok(Expression::Skewness(Box::new(AggFunc {
2578 this: arg,
2579 distinct: false,
2580 filter: None,
2581 order_by: Vec::new(),
2582 name: Some("SKEW".to_string()),
2583 ignore_nulls: None,
2584 having_max: None,
2585 limit: None,
2586 inferred_type: None,
2587 })))
2588 }
2589
2590 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2592 "VARIANCE".to_string(),
2593 f.args,
2594 )))),
2595
2596 "VAR_POP" => Ok(Expression::Function(Box::new(Function::new(
2598 "VARIANCE_POP".to_string(),
2599 f.args,
2600 )))),
2601
2602 "DATE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2604 "TO_DATE".to_string(),
2605 f.args,
2606 )))),
2607 "DATE" if f.args.len() >= 2 => {
2611 let mut args = f.args;
2612 args[1] = Self::normalize_format_arg(args[1].clone());
2613 Ok(Expression::Function(Box::new(Function::new(
2614 "TO_DATE".to_string(),
2615 args,
2616 ))))
2617 }
2618 "_POLYGLOT_DATE" if f.args.len() >= 2 => {
2621 let mut args = f.args;
2622 args[1] = Self::normalize_format_arg(args[1].clone());
2623 Ok(Expression::Function(Box::new(Function::new(
2624 "DATE".to_string(),
2625 args,
2626 ))))
2627 }
2628
2629 "DESCRIBE" => Ok(Expression::Function(Box::new(f))),
2631
2632 "MD5_HEX" => Ok(Expression::Function(Box::new(Function::new(
2634 "MD5".to_string(),
2635 f.args,
2636 )))),
2637
2638 "SHA1_HEX" => Ok(Expression::Function(Box::new(Function::new(
2640 "SHA1".to_string(),
2641 f.args,
2642 )))),
2643
2644 "SHA2_HEX" => Ok(Expression::Function(Box::new(Function::new(
2646 "SHA2".to_string(),
2647 f.args,
2648 )))),
2649
2650 "LEVENSHTEIN" => Ok(Expression::Function(Box::new(Function::new(
2652 "EDITDISTANCE".to_string(),
2653 f.args,
2654 )))),
2655
2656 "BIT_NOT" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2658 "BITNOT".to_string(),
2659 f.args,
2660 )))),
2661
2662 "BIT_AND" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2664 "BITAND".to_string(),
2665 f.args,
2666 )))),
2667
2668 "BIT_OR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2670 "BITOR".to_string(),
2671 f.args,
2672 )))),
2673
2674 "BIT_XOR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2676 "BITXOR".to_string(),
2677 f.args,
2678 )))),
2679
2680 "BIT_SHIFTLEFT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
2682 Function::new("BITSHIFTLEFT".to_string(), f.args),
2683 ))),
2684
2685 "BIT_SHIFTRIGHT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
2687 Function::new("BITSHIFTRIGHT".to_string(), f.args),
2688 ))),
2689
2690 "SYSTIMESTAMP" => Ok(Expression::Function(Box::new(Function {
2692 name: "CURRENT_TIMESTAMP".to_string(),
2693 args: f.args,
2694 distinct: false,
2695 trailing_comments: Vec::new(),
2696 use_bracket_syntax: false,
2697 no_parens: f.no_parens,
2698 quoted: false,
2699 span: None,
2700 inferred_type: None,
2701 }))),
2702
2703 "LOCALTIMESTAMP" => Ok(Expression::Function(Box::new(Function {
2705 name: "CURRENT_TIMESTAMP".to_string(),
2706 args: f.args,
2707 distinct: false,
2708 trailing_comments: Vec::new(),
2709 use_bracket_syntax: false,
2710 no_parens: f.no_parens,
2711 quoted: false,
2712 span: None,
2713 inferred_type: None,
2714 }))),
2715
2716 "SPACE" if f.args.len() == 1 => {
2718 let arg = f.args.into_iter().next().unwrap();
2719 Ok(Expression::Function(Box::new(Function::new(
2720 "REPEAT".to_string(),
2721 vec![Expression::Literal(Box::new(Literal::String(" ".to_string()))), arg],
2722 ))))
2723 }
2724
2725 "CEILING" => Ok(Expression::Function(Box::new(Function::new(
2727 "CEIL".to_string(),
2728 f.args,
2729 )))),
2730
2731 "LOG" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2733 "LN".to_string(),
2734 f.args,
2735 )))),
2736
2737 "REGEXP_SUBSTR_ALL" => Ok(Expression::Function(Box::new(f))),
2739
2740 "GET_PATH" if f.args.len() >= 2 => {
2744 let mut args = f.args;
2745 if let Expression::Literal(lit) = &args[1] {
2747 if let crate::expressions::Literal::String(path) = lit.as_ref() {
2748 let transformed = Self::transform_json_path(path);
2749 args[1] = Expression::Literal(Box::new(crate::expressions::Literal::String(transformed)));
2750 }
2751 }
2752 Ok(Expression::Function(Box::new(Function::new(
2753 "GET_PATH".to_string(),
2754 args,
2755 ))))
2756 }
2757 "GET_PATH" => Ok(Expression::Function(Box::new(f))),
2758
2759 "FLATTEN" => Ok(Expression::Function(Box::new(f))),
2761
2762 "DATE_TRUNC" if f.args.len() >= 1 => {
2765 let mut args = f.args;
2766 let unit_name = match &args[0] {
2768 Expression::Identifier(id) => Some(id.name.as_str()),
2769 Expression::Column(col) if col.table.is_none() => Some(col.name.name.as_str()),
2770 _ => None,
2771 };
2772 if let Some(name) = unit_name {
2773 let canonical = Self::map_date_part(name).unwrap_or(name);
2774 args[0] = Expression::Literal(Box::new(crate::expressions::Literal::String(
2775 canonical.to_uppercase(),
2776 )));
2777 }
2778 Ok(Expression::Function(Box::new(Function::new(
2779 "DATE_TRUNC".to_string(),
2780 args,
2781 ))))
2782 }
2783
2784 "DATE_PART" if f.args.len() >= 1 => {
2790 let mut args = f.args;
2791 let from_typed_literal = args.len() >= 2
2792 && matches!(
2793 &args[1],
2794 Expression::Literal(lit) if matches!(lit.as_ref(),
2795 crate::expressions::Literal::Timestamp(_)
2796 | crate::expressions::Literal::Date(_)
2797 | crate::expressions::Literal::Time(_)
2798 | crate::expressions::Literal::Datetime(_)
2799 )
2800 );
2801 if from_typed_literal {
2802 args[0] = self.transform_date_part_arg(args[0].clone());
2803 } else {
2804 args[0] = self.transform_date_part_arg_identifiers_only(args[0].clone());
2807 }
2808 Ok(Expression::Function(Box::new(Function::new(
2809 "DATE_PART".to_string(),
2810 args,
2811 ))))
2812 }
2813
2814 "OBJECT_CONSTRUCT" => Ok(Expression::Function(Box::new(f))),
2816
2817 "OBJECT_CONSTRUCT_KEEP_NULL" => Ok(Expression::Function(Box::new(f))),
2819
2820 "DESC" => Ok(Expression::Function(Box::new(Function::new(
2822 "DESCRIBE".to_string(),
2823 f.args,
2824 )))),
2825
2826 "RLIKE" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2828 "REGEXP_LIKE".to_string(),
2829 f.args,
2830 )))),
2831
2832 "TRANSFORM" => {
2837 let transformed_args: Vec<Expression> = f
2838 .args
2839 .into_iter()
2840 .map(|arg| {
2841 if let Expression::Lambda(lambda) = arg {
2842 self.transform_typed_lambda(*lambda)
2843 } else {
2844 arg
2845 }
2846 })
2847 .collect();
2848 Ok(Expression::Function(Box::new(Function::new(
2849 "TRANSFORM".to_string(),
2850 transformed_args,
2851 ))))
2852 }
2853
2854 "SEARCH" if f.args.len() >= 2 => {
2856 let mut args = f.args.into_iter();
2857 let this = Box::new(args.next().unwrap());
2858 let expression = Box::new(args.next().unwrap());
2859
2860 let mut analyzer: Option<Box<Expression>> = None;
2861 let mut search_mode: Option<Box<Expression>> = None;
2862
2863 for arg in args {
2865 if let Expression::NamedArgument(na) = &arg {
2866 let name_upper = na.name.name.to_uppercase();
2867 match name_upper.as_str() {
2868 "ANALYZER" => analyzer = Some(Box::new(arg)),
2869 "SEARCH_MODE" => search_mode = Some(Box::new(arg)),
2870 _ => {}
2871 }
2872 }
2873 }
2874
2875 Ok(Expression::Search(Box::new(crate::expressions::Search {
2876 this,
2877 expression,
2878 json_scope: None,
2879 analyzer,
2880 analyzer_options: None,
2881 search_mode,
2882 })))
2883 }
2884
2885 "CONVERT" if f.args.len() == 2 => {
2888 let value = f.args.get(0).cloned().unwrap();
2889 let type_arg = f.args.get(1).cloned().unwrap();
2890
2891 if let Expression::Column(col) = &type_arg {
2893 let type_name = col.name.name.to_uppercase();
2894 let data_type = match type_name.as_str() {
2895 "SQL_DOUBLE" => Some(DataType::Double {
2896 precision: None,
2897 scale: None,
2898 }),
2899 "SQL_VARCHAR" => Some(DataType::VarChar {
2900 length: None,
2901 parenthesized_length: false,
2902 }),
2903 "SQL_INTEGER" | "SQL_INT" => Some(DataType::Int {
2904 length: None,
2905 integer_spelling: false,
2906 }),
2907 "SQL_BIGINT" => Some(DataType::BigInt { length: None }),
2908 "SQL_SMALLINT" => Some(DataType::SmallInt { length: None }),
2909 "SQL_FLOAT" => Some(DataType::Float {
2910 precision: None,
2911 scale: None,
2912 real_spelling: false,
2913 }),
2914 "SQL_REAL" => Some(DataType::Float {
2915 precision: None,
2916 scale: None,
2917 real_spelling: true,
2918 }),
2919 "SQL_DECIMAL" => Some(DataType::Decimal {
2920 precision: None,
2921 scale: None,
2922 }),
2923 "SQL_DATE" => Some(DataType::Date),
2924 "SQL_TIME" => Some(DataType::Time {
2925 precision: None,
2926 timezone: false,
2927 }),
2928 "SQL_TIMESTAMP" => Some(DataType::Timestamp {
2929 precision: None,
2930 timezone: false,
2931 }),
2932 _ => None,
2933 };
2934
2935 if let Some(dt) = data_type {
2936 return Ok(Expression::Cast(Box::new(Cast {
2937 this: value,
2938 to: dt,
2939 double_colon_syntax: false,
2940 trailing_comments: vec![],
2941 format: None,
2942 default: None,
2943 inferred_type: None,
2944 })));
2945 }
2946 }
2947 Ok(Expression::Function(Box::new(f)))
2949 }
2950
2951 "TO_TIMESTAMP_TZ" => {
2954 if f.args.len() == 1 {
2955 if let Expression::Literal(lit) = &f.args[0]
2956 {
2957 if let crate::expressions::Literal::String(_) = lit.as_ref() {
2958 return Ok(Expression::Cast(Box::new(Cast {
2959 this: f.args.into_iter().next().unwrap(),
2960 to: DataType::Custom {
2961 name: "TIMESTAMPTZ".to_string(),
2962 },
2963 double_colon_syntax: false,
2964 trailing_comments: vec![],
2965 format: None,
2966 default: None,
2967 inferred_type: None,
2968 })));
2969 }
2970 }
2971 }
2972 Ok(Expression::Function(Box::new(f)))
2973 }
2974
2975 "TO_TIMESTAMP_NTZ" => {
2977 if f.args.len() == 1 {
2978 if let Expression::Literal(lit) = &f.args[0]
2979 {
2980 if let crate::expressions::Literal::String(_) = lit.as_ref() {
2981 return Ok(Expression::Cast(Box::new(Cast {
2982 this: f.args.into_iter().next().unwrap(),
2983 to: DataType::Custom {
2984 name: "TIMESTAMPNTZ".to_string(),
2985 },
2986 double_colon_syntax: false,
2987 trailing_comments: vec![],
2988 format: None,
2989 default: None,
2990 inferred_type: None,
2991 })));
2992 }
2993 }
2994 }
2995 Ok(Expression::Function(Box::new(f)))
2996 }
2997
2998 "TO_TIMESTAMP_LTZ" => {
3000 if f.args.len() == 1 {
3001 if let Expression::Literal(lit) = &f.args[0]
3002 {
3003 if let crate::expressions::Literal::String(_) = lit.as_ref() {
3004 return Ok(Expression::Cast(Box::new(Cast {
3005 this: f.args.into_iter().next().unwrap(),
3006 to: DataType::Custom {
3007 name: "TIMESTAMPLTZ".to_string(),
3008 },
3009 double_colon_syntax: false,
3010 trailing_comments: vec![],
3011 format: None,
3012 default: None,
3013 inferred_type: None,
3014 })));
3015 }
3016 }
3017 }
3018 Ok(Expression::Function(Box::new(f)))
3019 }
3020
3021 "UNIFORM" => Ok(Expression::Function(Box::new(f))),
3023
3024 "REPLACE" if f.args.len() == 2 => {
3026 let mut args = f.args;
3027 args.push(Expression::Literal(Box::new(crate::expressions::Literal::String(
3028 String::new(),
3029 ))));
3030 Ok(Expression::Function(Box::new(Function::new(
3031 "REPLACE".to_string(),
3032 args,
3033 ))))
3034 }
3035
3036 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
3038 "ANY_VALUE".to_string(),
3039 f.args,
3040 )))),
3041
3042 "SAFE_DIVIDE" if f.args.len() == 2 => {
3044 let mut args = f.args;
3045 let x = args.remove(0);
3046 let y = args.remove(0);
3047 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3048 condition: Expression::Neq(Box::new(BinaryOp {
3049 left: y.clone(),
3050 right: Expression::number(0),
3051 left_comments: Vec::new(),
3052 operator_comments: Vec::new(),
3053 trailing_comments: Vec::new(),
3054 inferred_type: None,
3055 })),
3056 true_value: Expression::Div(Box::new(BinaryOp {
3057 left: x,
3058 right: y,
3059 left_comments: Vec::new(),
3060 operator_comments: Vec::new(),
3061 trailing_comments: Vec::new(),
3062 inferred_type: None,
3063 })),
3064 false_value: Some(Expression::Null(crate::expressions::Null)),
3065 original_name: Some("IFF".to_string()),
3066 inferred_type: None,
3067 })))
3068 }
3069
3070 "TIMESTAMP" if f.args.len() == 1 => {
3072 let arg = f.args.into_iter().next().unwrap();
3073 Ok(Expression::Cast(Box::new(Cast {
3074 this: arg,
3075 to: DataType::Custom {
3076 name: "TIMESTAMPTZ".to_string(),
3077 },
3078 trailing_comments: Vec::new(),
3079 double_colon_syntax: false,
3080 format: None,
3081 default: None,
3082 inferred_type: None,
3083 })))
3084 }
3085
3086 "TIMESTAMP" if f.args.len() == 2 => {
3088 let mut args = f.args;
3089 let value = args.remove(0);
3090 let tz = args.remove(0);
3091 Ok(Expression::Function(Box::new(Function::new(
3092 "CONVERT_TIMEZONE".to_string(),
3093 vec![
3094 tz,
3095 Expression::Cast(Box::new(Cast {
3096 this: value,
3097 to: DataType::Timestamp {
3098 precision: None,
3099 timezone: false,
3100 },
3101 trailing_comments: Vec::new(),
3102 double_colon_syntax: false,
3103 format: None,
3104 default: None,
3105 inferred_type: None,
3106 })),
3107 ],
3108 ))))
3109 }
3110
3111 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3113 "TIME_FROM_PARTS".to_string(),
3114 f.args,
3115 )))),
3116
3117 "DIV0" if f.args.len() == 2 => {
3119 let mut args = f.args;
3120 let x = args.remove(0);
3121 let y = args.remove(0);
3122 let x_expr = Self::maybe_paren(x.clone());
3124 let y_expr = Self::maybe_paren(y.clone());
3125 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3126 condition: Expression::And(Box::new(BinaryOp::new(
3127 Expression::Eq(Box::new(BinaryOp::new(
3128 y_expr.clone(),
3129 Expression::number(0),
3130 ))),
3131 Expression::Not(Box::new(crate::expressions::UnaryOp {
3132 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3133 this: x_expr.clone(),
3134 not: false,
3135 postfix_form: false,
3136 })),
3137 inferred_type: None,
3138 })),
3139 ))),
3140 true_value: Expression::number(0),
3141 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3142 original_name: Some("IFF".to_string()),
3143 inferred_type: None,
3144 })))
3145 }
3146
3147 "DIV0NULL" if f.args.len() == 2 => {
3149 let mut args = f.args;
3150 let x = args.remove(0);
3151 let y = args.remove(0);
3152 let x_expr = Self::maybe_paren(x.clone());
3153 let y_expr = Self::maybe_paren(y.clone());
3154 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3155 condition: Expression::Or(Box::new(BinaryOp::new(
3156 Expression::Eq(Box::new(BinaryOp::new(
3157 y_expr.clone(),
3158 Expression::number(0),
3159 ))),
3160 Expression::IsNull(Box::new(crate::expressions::IsNull {
3161 this: y_expr.clone(),
3162 not: false,
3163 postfix_form: false,
3164 })),
3165 ))),
3166 true_value: Expression::number(0),
3167 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3168 original_name: Some("IFF".to_string()),
3169 inferred_type: None,
3170 })))
3171 }
3172
3173 "ZEROIFNULL" if f.args.len() == 1 => {
3175 let x = f.args.into_iter().next().unwrap();
3176 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3177 condition: Expression::IsNull(Box::new(crate::expressions::IsNull {
3178 this: x.clone(),
3179 not: false,
3180 postfix_form: false,
3181 })),
3182 true_value: Expression::number(0),
3183 false_value: Some(x),
3184 original_name: Some("IFF".to_string()),
3185 inferred_type: None,
3186 })))
3187 }
3188
3189 "NULLIFZERO" if f.args.len() == 1 => {
3191 let x = f.args.into_iter().next().unwrap();
3192 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3193 condition: Expression::Eq(Box::new(BinaryOp::new(
3194 x.clone(),
3195 Expression::number(0),
3196 ))),
3197 true_value: Expression::Null(crate::expressions::Null),
3198 false_value: Some(x),
3199 original_name: Some("IFF".to_string()),
3200 inferred_type: None,
3201 })))
3202 }
3203
3204 "TRY_TO_TIME" => {
3206 if f.args.len() == 1 {
3207 if let Expression::Literal(lit) = &f.args[0]
3208 {
3209 if let crate::expressions::Literal::String(_) = lit.as_ref() {
3210 return Ok(Expression::TryCast(Box::new(Cast {
3211 this: f.args.into_iter().next().unwrap(),
3212 to: crate::expressions::DataType::Time {
3213 precision: None,
3214 timezone: false,
3215 },
3216 double_colon_syntax: false,
3217 trailing_comments: Vec::new(),
3218 format: None,
3219 default: None,
3220 inferred_type: None,
3221 })));
3222 }
3223 }
3224 }
3225 let mut args = f.args;
3227 if args.len() >= 2 {
3228 args[1] = Self::normalize_format_arg(args[1].clone());
3229 }
3230 Ok(Expression::Function(Box::new(Function::new(
3231 "TRY_TO_TIME".to_string(),
3232 args,
3233 ))))
3234 }
3235
3236 "TRY_TO_TIMESTAMP" => {
3239 if f.args.len() == 1 {
3240 if let Expression::Literal(lit) = &f.args[0]
3241 {
3242 if let crate::expressions::Literal::String(s) = lit.as_ref() {
3243 if !Self::looks_like_epoch(s) {
3244 return Ok(Expression::TryCast(Box::new(Cast {
3245 this: f.args.into_iter().next().unwrap(),
3246 to: DataType::Timestamp {
3247 precision: None,
3248 timezone: false,
3249 },
3250 double_colon_syntax: false,
3251 trailing_comments: Vec::new(),
3252 format: None,
3253 default: None,
3254 inferred_type: None,
3255 })));
3256 }
3257 }
3258 }
3259 }
3260 let mut args = f.args;
3262 if args.len() >= 2 {
3263 args[1] = Self::normalize_format_arg(args[1].clone());
3264 }
3265 Ok(Expression::Function(Box::new(Function::new(
3266 "TRY_TO_TIMESTAMP".to_string(),
3267 args,
3268 ))))
3269 }
3270
3271 "TRY_TO_DATE" => {
3273 if f.args.len() == 1 {
3274 if let Expression::Literal(lit) = &f.args[0]
3275 {
3276 if let crate::expressions::Literal::String(s) = lit.as_ref() {
3277 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
3279 return Ok(Expression::TryCast(Box::new(Cast {
3280 this: f.args.into_iter().next().unwrap(),
3281 to: crate::expressions::DataType::Date,
3282 double_colon_syntax: false,
3283 trailing_comments: Vec::new(),
3284 format: None,
3285 default: None,
3286 inferred_type: None,
3287 })));
3288 }
3289 }
3290 }
3291 }
3292 let mut args = f.args;
3294 if args.len() >= 2 {
3295 args[1] = Self::normalize_format_arg(args[1].clone());
3296 }
3297 Ok(Expression::Function(Box::new(Function::new(
3298 "TRY_TO_DATE".to_string(),
3299 args,
3300 ))))
3301 }
3302
3303 "TRY_TO_DOUBLE" => Ok(Expression::Function(Box::new(f))),
3305
3306 "REGEXP_REPLACE" if f.args.len() == 2 => {
3308 let mut args = f.args;
3309 args.push(Expression::Literal(Box::new(crate::expressions::Literal::String(
3310 String::new(),
3311 ))));
3312 Ok(Expression::Function(Box::new(Function::new(
3313 "REGEXP_REPLACE".to_string(),
3314 args,
3315 ))))
3316 }
3317
3318 "LAST_DAY" if f.args.len() == 2 => {
3320 let mut args = f.args;
3321 let date = args.remove(0);
3322 let unit = args.remove(0);
3323 let unit_str = match &unit {
3324 Expression::Column(c) => c.name.name.to_uppercase(),
3325 Expression::Identifier(i) => i.name.to_uppercase(),
3326 _ => String::new(),
3327 };
3328 if unit_str == "MONTH" {
3329 Ok(Expression::Function(Box::new(Function::new(
3330 "LAST_DAY".to_string(),
3331 vec![date],
3332 ))))
3333 } else {
3334 Ok(Expression::Function(Box::new(Function::new(
3335 "LAST_DAY".to_string(),
3336 vec![date, unit],
3337 ))))
3338 }
3339 }
3340
3341 "EXTRACT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
3343 "DATE_PART".to_string(),
3344 f.args,
3345 )))),
3346
3347 "ENDS_WITH" | "ENDSWITH" if f.args.len() == 2 => {
3349 let mut args = f.args;
3350 let this = args.remove(0);
3351 let expr = args.remove(0);
3352 Ok(Expression::EndsWith(Box::new(
3353 crate::expressions::BinaryFunc {
3354 original_name: None,
3355 this,
3356 expression: expr,
3357 inferred_type: None,
3358 },
3359 )))
3360 }
3361
3362 _ => Ok(Expression::Function(Box::new(f))),
3364 }
3365 }
3366
3367 fn looks_like_datetime(s: &str) -> bool {
3369 s.contains('-') || s.contains(':') || s.contains(' ') || s.contains('/')
3372 }
3373
3374 fn looks_like_epoch(s: &str) -> bool {
3376 !s.is_empty() && s.chars().all(|c| c.is_ascii_digit() || c == '.')
3377 }
3378
3379 fn maybe_paren(expr: Expression) -> Expression {
3381 match &expr {
3382 Expression::Sub(_) | Expression::Add(_) | Expression::Mul(_) | Expression::Div(_) => {
3383 Expression::Paren(Box::new(crate::expressions::Paren {
3384 this: expr,
3385 trailing_comments: Vec::new(),
3386 }))
3387 }
3388 _ => expr,
3389 }
3390 }
3391
3392 fn normalize_snowflake_format(format: &str) -> String {
3396 let mut result = String::new();
3397 let chars: Vec<char> = format.chars().collect();
3398 let mut i = 0;
3399 while i < chars.len() {
3400 if chars[i] == '"' {
3402 i += 1;
3403 while i < chars.len() && chars[i] != '"' {
3404 result.push(chars[i]);
3405 i += 1;
3406 }
3407 if i < chars.len() {
3408 i += 1; }
3410 continue;
3411 }
3412
3413 let remaining = &format[i..];
3414 let remaining_upper = remaining.to_uppercase();
3415
3416 if remaining_upper.starts_with("YYYY") {
3418 result.push_str("yyyy");
3419 i += 4;
3420 } else if remaining_upper.starts_with("YY") {
3421 result.push_str("yy");
3422 i += 2;
3423 } else if remaining_upper.starts_with("MMMM") {
3424 result.push_str("mmmm");
3425 i += 4;
3426 } else if remaining_upper.starts_with("MON") {
3427 result.push_str("mon");
3428 i += 3;
3429 } else if remaining_upper.starts_with("MM") {
3430 result.push_str("mm");
3431 i += 2;
3432 } else if remaining_upper.starts_with("DD") {
3433 result.push_str("DD");
3434 i += 2;
3435 } else if remaining_upper.starts_with("DY") {
3436 result.push_str("dy");
3437 i += 2;
3438 } else if remaining_upper.starts_with("HH24") {
3439 result.push_str("hh24");
3440 i += 4;
3441 } else if remaining_upper.starts_with("HH12") {
3442 result.push_str("hh12");
3443 i += 4;
3444 } else if remaining_upper.starts_with("HH") {
3445 result.push_str("hh");
3446 i += 2;
3447 } else if remaining_upper.starts_with("MISS") {
3448 result.push_str("miss");
3450 i += 4;
3451 } else if remaining_upper.starts_with("MI") {
3452 result.push_str("mi");
3453 i += 2;
3454 } else if remaining_upper.starts_with("SS") {
3455 result.push_str("ss");
3456 i += 2;
3457 } else if remaining_upper.starts_with("FF") {
3458 let ff_len = 2;
3460 let digit = if i + ff_len < chars.len() && chars[i + ff_len].is_ascii_digit() {
3461 let d = chars[i + ff_len];
3462 Some(d)
3463 } else {
3464 None
3465 };
3466 if let Some(d) = digit {
3467 result.push_str("ff");
3468 result.push(d);
3469 i += 3;
3470 } else {
3471 result.push_str("ff9");
3473 i += 2;
3474 }
3475 } else if remaining_upper.starts_with("AM") || remaining_upper.starts_with("PM") {
3476 result.push_str("pm");
3477 i += 2;
3478 } else if remaining_upper.starts_with("TZH") {
3479 result.push_str("tzh");
3480 i += 3;
3481 } else if remaining_upper.starts_with("TZM") {
3482 result.push_str("tzm");
3483 i += 3;
3484 } else {
3485 result.push(chars[i]);
3487 i += 1;
3488 }
3489 }
3490 result
3491 }
3492
3493 fn normalize_format_arg(expr: Expression) -> Expression {
3495 if let Expression::Literal(lit) = &expr {
3496 if let crate::expressions::Literal::String(s) = lit.as_ref() {
3497 let normalized = Self::normalize_snowflake_format(s);
3498 Expression::Literal(Box::new(crate::expressions::Literal::String(normalized)))
3499 } else { expr.clone() }
3500 } else {
3501 expr
3502 }
3503 }
3504
3505 fn transform_typed_lambda(&self, lambda: crate::expressions::LambdaExpr) -> Expression {
3508 use crate::expressions::{DataType, LambdaExpr};
3509 use std::collections::HashMap;
3510
3511 let mut param_types: HashMap<String, DataType> = HashMap::new();
3513 for (i, param) in lambda.parameters.iter().enumerate() {
3514 if let Some(Some(dt)) = lambda.parameter_types.get(i) {
3515 param_types.insert(param.name.to_uppercase(), dt.clone());
3516 }
3517 }
3518
3519 if param_types.is_empty() {
3521 return Expression::Lambda(Box::new(lambda));
3522 }
3523
3524 let transformed_body = self.replace_lambda_params_with_cast(lambda.body, ¶m_types);
3526
3527 Expression::Lambda(Box::new(LambdaExpr {
3529 parameters: lambda.parameters,
3530 body: transformed_body,
3531 colon: lambda.colon,
3532 parameter_types: Vec::new(), }))
3534 }
3535
3536 fn replace_lambda_params_with_cast(
3538 &self,
3539 expr: Expression,
3540 param_types: &std::collections::HashMap<String, crate::expressions::DataType>,
3541 ) -> Expression {
3542 use crate::expressions::{BinaryOp, Cast, Paren};
3543
3544 match expr {
3545 Expression::Column(col) if col.table.is_none() => {
3547 let name_upper = col.name.name.to_uppercase();
3548 if let Some(dt) = param_types.get(&name_upper) {
3549 Expression::Cast(Box::new(Cast {
3551 this: Expression::Column(col),
3552 to: dt.clone(),
3553 double_colon_syntax: false,
3554 trailing_comments: Vec::new(),
3555 format: None,
3556 default: None,
3557 inferred_type: None,
3558 }))
3559 } else {
3560 Expression::Column(col)
3561 }
3562 }
3563
3564 Expression::Identifier(id) => {
3566 let name_upper = id.name.to_uppercase();
3567 if let Some(dt) = param_types.get(&name_upper) {
3568 Expression::Cast(Box::new(Cast {
3570 this: Expression::Identifier(id),
3571 to: dt.clone(),
3572 double_colon_syntax: false,
3573 trailing_comments: Vec::new(),
3574 format: None,
3575 default: None,
3576 inferred_type: None,
3577 }))
3578 } else {
3579 Expression::Identifier(id)
3580 }
3581 }
3582
3583 Expression::Add(op) => Expression::Add(Box::new(BinaryOp::new(
3585 self.replace_lambda_params_with_cast(op.left, param_types),
3586 self.replace_lambda_params_with_cast(op.right, param_types),
3587 ))),
3588 Expression::Sub(op) => Expression::Sub(Box::new(BinaryOp::new(
3589 self.replace_lambda_params_with_cast(op.left, param_types),
3590 self.replace_lambda_params_with_cast(op.right, param_types),
3591 ))),
3592 Expression::Mul(op) => Expression::Mul(Box::new(BinaryOp::new(
3593 self.replace_lambda_params_with_cast(op.left, param_types),
3594 self.replace_lambda_params_with_cast(op.right, param_types),
3595 ))),
3596 Expression::Div(op) => Expression::Div(Box::new(BinaryOp::new(
3597 self.replace_lambda_params_with_cast(op.left, param_types),
3598 self.replace_lambda_params_with_cast(op.right, param_types),
3599 ))),
3600 Expression::Mod(op) => Expression::Mod(Box::new(BinaryOp::new(
3601 self.replace_lambda_params_with_cast(op.left, param_types),
3602 self.replace_lambda_params_with_cast(op.right, param_types),
3603 ))),
3604
3605 Expression::Paren(p) => Expression::Paren(Box::new(Paren {
3607 this: self.replace_lambda_params_with_cast(p.this, param_types),
3608 trailing_comments: p.trailing_comments,
3609 })),
3610
3611 Expression::Function(mut f) => {
3613 f.args = f
3614 .args
3615 .into_iter()
3616 .map(|arg| self.replace_lambda_params_with_cast(arg, param_types))
3617 .collect();
3618 Expression::Function(f)
3619 }
3620
3621 Expression::Eq(op) => Expression::Eq(Box::new(BinaryOp::new(
3623 self.replace_lambda_params_with_cast(op.left, param_types),
3624 self.replace_lambda_params_with_cast(op.right, param_types),
3625 ))),
3626 Expression::Neq(op) => Expression::Neq(Box::new(BinaryOp::new(
3627 self.replace_lambda_params_with_cast(op.left, param_types),
3628 self.replace_lambda_params_with_cast(op.right, param_types),
3629 ))),
3630 Expression::Lt(op) => Expression::Lt(Box::new(BinaryOp::new(
3631 self.replace_lambda_params_with_cast(op.left, param_types),
3632 self.replace_lambda_params_with_cast(op.right, param_types),
3633 ))),
3634 Expression::Lte(op) => Expression::Lte(Box::new(BinaryOp::new(
3635 self.replace_lambda_params_with_cast(op.left, param_types),
3636 self.replace_lambda_params_with_cast(op.right, param_types),
3637 ))),
3638 Expression::Gt(op) => Expression::Gt(Box::new(BinaryOp::new(
3639 self.replace_lambda_params_with_cast(op.left, param_types),
3640 self.replace_lambda_params_with_cast(op.right, param_types),
3641 ))),
3642 Expression::Gte(op) => Expression::Gte(Box::new(BinaryOp::new(
3643 self.replace_lambda_params_with_cast(op.left, param_types),
3644 self.replace_lambda_params_with_cast(op.right, param_types),
3645 ))),
3646
3647 Expression::And(op) => Expression::And(Box::new(BinaryOp::new(
3649 self.replace_lambda_params_with_cast(op.left, param_types),
3650 self.replace_lambda_params_with_cast(op.right, param_types),
3651 ))),
3652 Expression::Or(op) => Expression::Or(Box::new(BinaryOp::new(
3653 self.replace_lambda_params_with_cast(op.left, param_types),
3654 self.replace_lambda_params_with_cast(op.right, param_types),
3655 ))),
3656
3657 other => other,
3659 }
3660 }
3661
3662 fn transform_aggregate_function(
3663 &self,
3664 f: Box<crate::expressions::AggregateFunction>,
3665 ) -> Result<Expression> {
3666 let name_upper = f.name.to_uppercase();
3667 match name_upper.as_str() {
3668 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3670 Function::new("LISTAGG".to_string(), f.args),
3671 ))),
3672
3673 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3675 Function::new("LISTAGG".to_string(), f.args),
3676 ))),
3677
3678 "APPROX_DISTINCT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3680 Function::new("APPROX_COUNT_DISTINCT".to_string(), f.args),
3681 ))),
3682
3683 "BIT_AND" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3685 "BITAND_AGG".to_string(),
3686 f.args,
3687 )))),
3688
3689 "BIT_OR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3691 "BITOR_AGG".to_string(),
3692 f.args,
3693 )))),
3694
3695 "BIT_XOR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3697 "BITXOR_AGG".to_string(),
3698 f.args,
3699 )))),
3700
3701 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" if !f.args.is_empty() => {
3703 let arg = f.args.into_iter().next().unwrap();
3704 Ok(Expression::LogicalAnd(Box::new(AggFunc {
3705 this: arg,
3706 distinct: f.distinct,
3707 filter: f.filter,
3708 order_by: Vec::new(),
3709 name: Some("BOOLAND_AGG".to_string()),
3710 ignore_nulls: None,
3711 having_max: None,
3712 limit: None,
3713 inferred_type: None,
3714 })))
3715 }
3716
3717 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if !f.args.is_empty() => {
3719 let arg = f.args.into_iter().next().unwrap();
3720 Ok(Expression::LogicalOr(Box::new(AggFunc {
3721 this: arg,
3722 distinct: f.distinct,
3723 filter: f.filter,
3724 order_by: Vec::new(),
3725 name: Some("BOOLOR_AGG".to_string()),
3726 ignore_nulls: None,
3727 having_max: None,
3728 limit: None,
3729 inferred_type: None,
3730 })))
3731 }
3732
3733 "APPROX_TOP_K" if f.args.len() == 1 => {
3735 let mut args = f.args;
3736 args.push(Expression::number(1));
3737 Ok(Expression::AggregateFunction(Box::new(
3738 crate::expressions::AggregateFunction {
3739 name: "APPROX_TOP_K".to_string(),
3740 args,
3741 distinct: f.distinct,
3742 filter: f.filter,
3743 order_by: Vec::new(),
3744 limit: None,
3745 ignore_nulls: None,
3746 inferred_type: None,
3747 },
3748 )))
3749 }
3750
3751 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
3753 let arg = f.args.into_iter().next().unwrap();
3754 Ok(Expression::Skewness(Box::new(AggFunc {
3755 this: arg,
3756 distinct: f.distinct,
3757 filter: f.filter,
3758 order_by: Vec::new(),
3759 name: Some("SKEW".to_string()),
3760 ignore_nulls: None,
3761 having_max: None,
3762 limit: None,
3763 inferred_type: None,
3764 })))
3765 }
3766
3767 _ => Ok(Expression::AggregateFunction(f)),
3769 }
3770 }
3771}
3772
3773fn strftime_to_snowflake_format(fmt: &str) -> String {
3775 let mut result = String::new();
3776 let chars: Vec<char> = fmt.chars().collect();
3777 let mut i = 0;
3778 while i < chars.len() {
3779 if chars[i] == '%' && i + 1 < chars.len() {
3780 match chars[i + 1] {
3781 'Y' => {
3782 result.push_str("yyyy");
3783 i += 2;
3784 }
3785 'y' => {
3786 result.push_str("yy");
3787 i += 2;
3788 }
3789 'm' => {
3790 result.push_str("mm");
3791 i += 2;
3792 }
3793 'd' => {
3794 result.push_str("DD");
3795 i += 2;
3796 }
3797 'H' => {
3798 result.push_str("hh24");
3799 i += 2;
3800 }
3801 'M' => {
3802 result.push_str("mmmm");
3803 i += 2;
3804 } 'i' => {
3806 result.push_str("mi");
3807 i += 2;
3808 }
3809 'S' | 's' => {
3810 result.push_str("ss");
3811 i += 2;
3812 }
3813 'f' => {
3814 result.push_str("ff");
3815 i += 2;
3816 }
3817 'w' => {
3818 result.push_str("dy");
3819 i += 2;
3820 } 'a' => {
3822 result.push_str("DY");
3823 i += 2;
3824 } 'b' => {
3826 result.push_str("mon");
3827 i += 2;
3828 } 'T' => {
3830 result.push_str("hh24:mi:ss");
3831 i += 2;
3832 } _ => {
3834 result.push(chars[i]);
3835 result.push(chars[i + 1]);
3836 i += 2;
3837 }
3838 }
3839 } else {
3840 result.push(chars[i]);
3841 i += 1;
3842 }
3843 }
3844 result
3845}
3846
3847#[cfg(test)]
3848mod tests {
3849 use super::*;
3850 use crate::dialects::Dialect;
3851
3852 fn transpile_to_snowflake(sql: &str) -> String {
3853 let dialect = Dialect::get(DialectType::Generic);
3854 let result = dialect
3855 .transpile_to(sql, DialectType::Snowflake)
3856 .expect("Transpile failed");
3857 result[0].clone()
3858 }
3859
3860 #[test]
3861 fn test_ifnull_to_coalesce() {
3862 let result = transpile_to_snowflake("SELECT IFNULL(a, b)");
3863 assert!(
3864 result.contains("COALESCE"),
3865 "Expected COALESCE, got: {}",
3866 result
3867 );
3868 }
3869
3870 #[test]
3871 fn test_basic_select() {
3872 let result = transpile_to_snowflake("SELECT a, b FROM users WHERE id = 1");
3873 assert!(result.contains("SELECT"));
3874 assert!(result.contains("FROM users"));
3875 }
3876
3877 #[test]
3878 fn test_group_concat_to_listagg() {
3879 let result = transpile_to_snowflake("SELECT GROUP_CONCAT(name)");
3880 assert!(
3881 result.contains("LISTAGG"),
3882 "Expected LISTAGG, got: {}",
3883 result
3884 );
3885 }
3886
3887 #[test]
3888 fn test_string_agg_to_listagg() {
3889 let result = transpile_to_snowflake("SELECT STRING_AGG(name)");
3890 assert!(
3891 result.contains("LISTAGG"),
3892 "Expected LISTAGG, got: {}",
3893 result
3894 );
3895 }
3896
3897 #[test]
3898 fn test_array_to_array_construct() {
3899 let result = transpile_to_snowflake("SELECT ARRAY(1, 2, 3)");
3900 assert!(
3902 result.contains("[1, 2, 3]"),
3903 "Expected [1, 2, 3], got: {}",
3904 result
3905 );
3906 }
3907
3908 #[test]
3909 fn test_double_quote_identifiers() {
3910 let dialect = SnowflakeDialect;
3912 let config = dialect.generator_config();
3913 assert_eq!(config.identifier_quote, '"');
3914 }
3915}