1use super::{DialectImpl, DialectType};
13use crate::error::Result;
14use crate::expressions::{
15 AggFunc, BinaryOp, Cast, CeilFunc, DataType, Expression, Function, IntervalUnit, ListAggFunc,
16 Literal, UnaryFunc, VarArgFunc,
17};
18use crate::generator::GeneratorConfig;
19use crate::tokens::TokenizerConfig;
20
21fn interval_unit_to_str(unit: &IntervalUnit) -> String {
23 match unit {
24 IntervalUnit::Year => "YEAR".to_string(),
25 IntervalUnit::Quarter => "QUARTER".to_string(),
26 IntervalUnit::Month => "MONTH".to_string(),
27 IntervalUnit::Week => "WEEK".to_string(),
28 IntervalUnit::Day => "DAY".to_string(),
29 IntervalUnit::Hour => "HOUR".to_string(),
30 IntervalUnit::Minute => "MINUTE".to_string(),
31 IntervalUnit::Second => "SECOND".to_string(),
32 IntervalUnit::Millisecond => "MILLISECOND".to_string(),
33 IntervalUnit::Microsecond => "MICROSECOND".to_string(),
34 IntervalUnit::Nanosecond => "NANOSECOND".to_string(),
35 }
36}
37
38pub struct SnowflakeDialect;
40
41impl DialectImpl for SnowflakeDialect {
42 fn dialect_type(&self) -> DialectType {
43 DialectType::Snowflake
44 }
45
46 fn tokenizer_config(&self) -> TokenizerConfig {
47 let mut config = TokenizerConfig::default();
48 config.identifiers.insert('"', '"');
50 config.quotes.insert("$$".to_string(), "$$".to_string());
52 config.nested_comments = false;
54 config.comments.insert("//".to_string(), None);
56 config
57 }
58
59 fn generator_config(&self) -> GeneratorConfig {
60 use crate::generator::IdentifierQuoteStyle;
61 GeneratorConfig {
62 identifier_quote: '"',
63 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
64 dialect: Some(DialectType::Snowflake),
65 parameter_token: "$",
67 matched_by_source: false,
68 single_string_interval: true,
69 join_hints: false,
70 table_hints: false,
71 query_hints: false,
72 aggregate_filter_supported: false,
73 supports_table_copy: false,
74 collate_is_func: true,
75 limit_only_literals: true,
76 json_key_value_pair_sep: ",",
77 insert_overwrite: " OVERWRITE INTO",
78 struct_delimiter: ("(", ")"),
79 copy_params_are_wrapped: false,
80 copy_params_eq_required: true,
81 star_except: "EXCLUDE",
82 supports_exploding_projections: false,
83 array_concat_is_var_len: false,
84 supports_convert_timezone: true,
85 except_intersect_support_all_clause: false,
86 supports_median: true,
87 array_size_name: "ARRAY_SIZE",
88 supports_decode_case: true,
89 is_bool_allowed: false,
90 try_supported: true,
92 nvl2_supported: true,
94 unnest_with_ordinality: false,
96 quantified_no_paren_space: false,
98 ..Default::default()
99 }
100 }
101
102 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
103 match expr {
104 Expression::DataType(dt) => self.transform_data_type(dt),
106
107 Expression::In(in_expr) if in_expr.not && in_expr.query.is_some() => {
111 let inner = in_expr.query.unwrap();
113 let subquery = Expression::Subquery(Box::new(crate::expressions::Subquery {
115 this: inner,
116 alias: None,
117 column_aliases: Vec::new(),
118 order_by: None,
119 limit: None,
120 offset: None,
121 distribute_by: None,
122 sort_by: None,
123 cluster_by: None,
124 lateral: false,
125 modifiers_inside: false,
126 trailing_comments: Vec::new(),
127 inferred_type: None,
128 }));
129 Ok(Expression::All(Box::new(
130 crate::expressions::QuantifiedExpr {
131 this: in_expr.this,
132 subquery,
133 op: Some(crate::expressions::QuantifiedOp::Neq),
134 },
135 )))
136 }
137
138 Expression::In(in_expr) if in_expr.not => {
140 let in_without_not = crate::expressions::In {
142 this: in_expr.this,
143 expressions: in_expr.expressions,
144 query: in_expr.query,
145 not: false,
146 global: in_expr.global,
147 unnest: in_expr.unnest,
148 is_field: in_expr.is_field,
149 };
150 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
151 this: Expression::In(Box::new(in_without_not)),
152 inferred_type: None,
153 })))
154 }
155
156 Expression::Interval(interval) => self.transform_interval(*interval),
159
160 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
163 original_name: None,
164 expressions: vec![f.this, f.expression],
165 inferred_type: None,
166 }))),
167
168 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
170 original_name: None,
171 expressions: vec![f.this, f.expression],
172 inferred_type: None,
173 }))),
174
175 Expression::Coalesce(mut f) => {
177 f.original_name = None;
178 Ok(Expression::Coalesce(f))
179 }
180
181 Expression::GroupConcat(f) => Ok(Expression::ListAgg(Box::new(ListAggFunc {
183 this: f.this,
184 separator: f.separator,
185 on_overflow: None,
186 order_by: f.order_by,
187 distinct: f.distinct,
188 filter: f.filter,
189 inferred_type: None,
190 }))),
191
192 Expression::Cast(c) => {
196 use crate::expressions::DataType;
197 let transformed_this = self.transform_expr(c.this)?;
199 match &c.to {
200 DataType::Geography { .. } => Ok(Expression::Function(Box::new(
201 Function::new("TO_GEOGRAPHY".to_string(), vec![transformed_this]),
202 ))),
203 DataType::Geometry { .. } => Ok(Expression::Function(Box::new(Function::new(
204 "TO_GEOMETRY".to_string(),
205 vec![transformed_this],
206 )))),
207 _ => {
208 let transformed_dt = match self.transform_data_type(c.to.clone())? {
210 Expression::DataType(dt) => dt,
211 _ => c.to.clone(),
212 };
213 Ok(Expression::Cast(Box::new(Cast {
214 this: transformed_this,
215 to: transformed_dt,
216 double_colon_syntax: false, trailing_comments: c.trailing_comments,
218 format: c.format,
219 default: c.default,
220 inferred_type: None,
221 })))
222 }
223 }
224 }
225
226 Expression::TryCast(c) => {
229 let transformed_this = self.transform_expr(c.this)?;
230 Ok(Expression::TryCast(Box::new(Cast {
231 this: transformed_this,
232 to: c.to,
233 double_colon_syntax: false, trailing_comments: c.trailing_comments,
235 format: c.format,
236 default: c.default,
237 inferred_type: None,
238 })))
239 }
240
241 Expression::SafeCast(c) => {
244 let to = match c.to {
245 DataType::Timestamp { .. } => DataType::Custom {
246 name: "TIMESTAMPTZ".to_string(),
247 },
248 DataType::Custom { name } if name.eq_ignore_ascii_case("TIMESTAMP") => {
249 DataType::Custom {
250 name: "TIMESTAMPTZ".to_string(),
251 }
252 }
253 other => other,
254 };
255 let transformed_this = self.transform_expr(c.this)?;
256 Ok(Expression::Cast(Box::new(Cast {
257 this: transformed_this,
258 to,
259 double_colon_syntax: c.double_colon_syntax,
260 trailing_comments: c.trailing_comments,
261 format: c.format,
262 default: c.default,
263 inferred_type: None,
264 })))
265 }
266
267 Expression::Literal(Literal::Timestamp(s)) => Ok(Expression::Cast(Box::new(Cast {
270 this: Expression::Literal(Literal::String(s)),
271 to: DataType::Timestamp {
272 precision: None,
273 timezone: false,
274 },
275 double_colon_syntax: false,
276 trailing_comments: Vec::new(),
277 format: None,
278 default: None,
279 inferred_type: None,
280 }))),
281
282 Expression::Literal(Literal::Date(s)) => Ok(Expression::Cast(Box::new(Cast {
284 this: Expression::Literal(Literal::String(s)),
285 to: DataType::Date,
286 double_colon_syntax: false,
287 trailing_comments: Vec::new(),
288 format: None,
289 default: None,
290 inferred_type: None,
291 }))),
292
293 Expression::Literal(Literal::Time(s)) => Ok(Expression::Cast(Box::new(Cast {
295 this: Expression::Literal(Literal::String(s)),
296 to: DataType::Time {
297 precision: None,
298 timezone: false,
299 },
300 double_colon_syntax: false,
301 trailing_comments: Vec::new(),
302 format: None,
303 default: None,
304 inferred_type: None,
305 }))),
306
307 Expression::Literal(Literal::Datetime(s)) => Ok(Expression::Cast(Box::new(Cast {
309 this: Expression::Literal(Literal::String(s)),
310 to: DataType::Custom {
311 name: "DATETIME".to_string(),
312 },
313 double_colon_syntax: false,
314 trailing_comments: Vec::new(),
315 format: None,
316 default: None,
317 inferred_type: None,
318 }))),
319
320 Expression::ILike(op) => Ok(Expression::ILike(op)),
323
324 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
327 "FLATTEN".to_string(),
328 vec![f.this],
329 )))),
330
331 Expression::ExplodeOuter(f) => Ok(Expression::Function(Box::new(Function::new(
333 "FLATTEN".to_string(),
334 vec![f.this],
335 )))),
336
337 Expression::Unnest(f) => {
339 let input_arg =
341 Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
342 name: crate::expressions::Identifier::new("INPUT"),
343 value: f.this,
344 separator: crate::expressions::NamedArgSeparator::DArrow,
345 }));
346
347 let flatten = Expression::Function(Box::new(Function::new(
349 "FLATTEN".to_string(),
350 vec![input_arg],
351 )));
352
353 let table_func =
355 Expression::TableFromRows(Box::new(crate::expressions::TableFromRows {
356 this: Box::new(flatten),
357 alias: None,
358 joins: vec![],
359 pivots: None,
360 sample: None,
361 }));
362
363 Ok(Expression::Alias(Box::new(crate::expressions::Alias {
365 this: table_func,
366 alias: crate::expressions::Identifier::new("_t0"),
367 column_aliases: vec![
368 crate::expressions::Identifier::new("seq"),
369 crate::expressions::Identifier::new("key"),
370 crate::expressions::Identifier::new("path"),
371 crate::expressions::Identifier::new("index"),
372 crate::expressions::Identifier::new("value"),
373 crate::expressions::Identifier::new("this"),
374 ],
375 pre_alias_comments: vec![],
376 trailing_comments: vec![],
377 inferred_type: None,
378 })))
379 }
380
381 Expression::ArrayFunc(arr) => {
385 if arr.bracket_notation {
386 Ok(Expression::ArrayFunc(arr))
388 } else {
389 Ok(Expression::Function(Box::new(Function::new(
391 "ARRAY_CONSTRUCT".to_string(),
392 arr.expressions,
393 ))))
394 }
395 }
396
397 Expression::ArrayConcat(f) => Ok(Expression::Function(Box::new(Function::new(
399 "ARRAY_CAT".to_string(),
400 f.expressions,
401 )))),
402
403 Expression::ArrayConcatAgg(f) => Ok(Expression::Function(Box::new(Function::new(
405 "ARRAY_FLATTEN".to_string(),
406 vec![f.this],
407 )))),
408
409 Expression::ArrayContains(f) => Ok(Expression::Function(Box::new(Function::new(
411 "ARRAY_CONTAINS".to_string(),
412 vec![f.this, f.expression],
413 )))),
414
415 Expression::ArrayIntersect(f) => Ok(Expression::Function(Box::new(Function::new(
417 "ARRAY_INTERSECTION".to_string(),
418 f.expressions,
419 )))),
420
421 Expression::ArraySort(f) => Ok(Expression::Function(Box::new(Function::new(
423 "ARRAY_SORT".to_string(),
424 vec![f.this],
425 )))),
426
427 Expression::StringToArray(f) => {
429 let mut args = vec![*f.this];
430 if let Some(expr) = f.expression {
431 args.push(*expr);
432 }
433 Ok(Expression::Function(Box::new(Function::new(
434 "STRTOK_TO_ARRAY".to_string(),
435 args,
436 ))))
437 }
438
439 Expression::BitwiseOr(f) => Ok(Expression::Function(Box::new(Function::new(
442 "BITOR".to_string(),
443 vec![f.left, f.right],
444 )))),
445
446 Expression::BitwiseXor(f) => Ok(Expression::Function(Box::new(Function::new(
448 "BITXOR".to_string(),
449 vec![f.left, f.right],
450 )))),
451
452 Expression::BitwiseAnd(f) => Ok(Expression::Function(Box::new(Function::new(
454 "BITAND".to_string(),
455 vec![f.left, f.right],
456 )))),
457
458 Expression::BitwiseNot(f) => Ok(Expression::Function(Box::new(Function::new(
460 "BITNOT".to_string(),
461 vec![f.this],
462 )))),
463
464 Expression::BitwiseLeftShift(f) => Ok(Expression::Function(Box::new(Function::new(
466 "BITSHIFTLEFT".to_string(),
467 vec![f.left, f.right],
468 )))),
469
470 Expression::BitwiseRightShift(f) => Ok(Expression::Function(Box::new(Function::new(
472 "BITSHIFTRIGHT".to_string(),
473 vec![f.left, f.right],
474 )))),
475
476 Expression::BitwiseAndAgg(f) => Ok(Expression::Function(Box::new(Function::new(
478 "BITAND_AGG".to_string(),
479 vec![f.this],
480 )))),
481
482 Expression::BitwiseOrAgg(f) => Ok(Expression::Function(Box::new(Function::new(
484 "BITOR_AGG".to_string(),
485 vec![f.this],
486 )))),
487
488 Expression::BitwiseXorAgg(f) => Ok(Expression::Function(Box::new(Function::new(
490 "BITXOR_AGG".to_string(),
491 vec![f.this],
492 )))),
493
494 Expression::LogicalAnd(f) => Ok(Expression::Function(Box::new(Function::new(
497 "BOOLAND_AGG".to_string(),
498 vec![f.this],
499 )))),
500
501 Expression::LogicalOr(f) => Ok(Expression::Function(Box::new(Function::new(
503 "BOOLOR_AGG".to_string(),
504 vec![f.this],
505 )))),
506
507 Expression::Booland(f) => Ok(Expression::Function(Box::new(Function::new(
509 "BOOLAND".to_string(),
510 vec![*f.this, *f.expression],
511 )))),
512
513 Expression::Boolor(f) => Ok(Expression::Function(Box::new(Function::new(
515 "BOOLOR".to_string(),
516 vec![*f.this, *f.expression],
517 )))),
518
519 Expression::Xor(f) => {
521 let mut args = Vec::new();
522 if let Some(this) = f.this {
523 args.push(*this);
524 }
525 if let Some(expr) = f.expression {
526 args.push(*expr);
527 }
528 Ok(Expression::Function(Box::new(Function::new(
529 "BOOLXOR".to_string(),
530 args,
531 ))))
532 }
533
534 Expression::DayOfMonth(f) => Ok(Expression::Function(Box::new(Function::new(
537 "DAYOFMONTH".to_string(),
538 vec![f.this],
539 )))),
540
541 Expression::DayOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
543 "DAYOFWEEK".to_string(),
544 vec![f.this],
545 )))),
546
547 Expression::DayOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
549 "DAYOFWEEKISO".to_string(),
550 vec![f.this],
551 )))),
552
553 Expression::DayOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
555 "DAYOFYEAR".to_string(),
556 vec![f.this],
557 )))),
558
559 Expression::WeekOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
561 "WEEK".to_string(),
562 vec![f.this],
563 )))),
564
565 Expression::YearOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
567 "YEAROFWEEK".to_string(),
568 vec![f.this],
569 )))),
570
571 Expression::YearOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
573 "YEAROFWEEKISO".to_string(),
574 vec![f.this],
575 )))),
576
577 Expression::ByteLength(f) => Ok(Expression::Function(Box::new(Function::new(
579 "OCTET_LENGTH".to_string(),
580 vec![f.this],
581 )))),
582
583 Expression::TimestampDiff(f) => {
585 let mut args = vec![];
586 if let Some(ref unit_str) = f.unit {
588 args.push(Expression::Identifier(crate::expressions::Identifier::new(
589 unit_str.clone(),
590 )));
591 args.push(*f.this);
592 args.push(*f.expression);
593 } else {
594 args.push(*f.this);
595 args.push(*f.expression);
596 }
597 Ok(Expression::Function(Box::new(Function::new(
598 "TIMESTAMPDIFF".to_string(),
599 args,
600 ))))
601 }
602
603 Expression::TimestampAdd(f) => {
605 let mut args = vec![];
606 if let Some(ref unit_str) = f.unit {
607 args.push(Expression::Identifier(crate::expressions::Identifier::new(
608 unit_str.clone(),
609 )));
610 args.push(*f.this);
611 args.push(*f.expression);
612 } else {
613 args.push(*f.this);
614 args.push(*f.expression);
615 }
616 Ok(Expression::Function(Box::new(Function::new(
617 "TIMESTAMPADD".to_string(),
618 args,
619 ))))
620 }
621
622 Expression::ToArray(f) => Ok(Expression::Function(Box::new(Function::new(
624 "TO_ARRAY".to_string(),
625 vec![f.this],
626 )))),
627
628 Expression::DateAdd(f) => {
630 let unit_str = interval_unit_to_str(&f.unit);
631 let unit = Expression::Identifier(crate::expressions::Identifier {
632 name: unit_str,
633 quoted: false,
634 trailing_comments: Vec::new(),
635 span: None,
636 });
637 Ok(Expression::Function(Box::new(Function::new(
638 "DATEADD".to_string(),
639 vec![unit, f.interval, f.this],
640 ))))
641 }
642
643 Expression::DateSub(f) => {
645 let unit_str = interval_unit_to_str(&f.unit);
646 let unit = Expression::Identifier(crate::expressions::Identifier {
647 name: unit_str,
648 quoted: false,
649 trailing_comments: Vec::new(),
650 span: None,
651 });
652 let neg_expr = Expression::Mul(Box::new(crate::expressions::BinaryOp::new(
654 f.interval,
655 Expression::Neg(Box::new(crate::expressions::UnaryOp {
656 this: Expression::number(1),
657 inferred_type: None,
658 })),
659 )));
660 Ok(Expression::Function(Box::new(Function::new(
661 "DATEADD".to_string(),
662 vec![unit, neg_expr, f.this],
663 ))))
664 }
665
666 Expression::DateDiff(f) => {
668 let unit_str =
669 interval_unit_to_str(&f.unit.unwrap_or(crate::expressions::IntervalUnit::Day));
670 let unit = Expression::Identifier(crate::expressions::Identifier {
671 name: unit_str,
672 quoted: false,
673 trailing_comments: Vec::new(),
674 span: None,
675 });
676 Ok(Expression::Function(Box::new(Function::new(
677 "DATEDIFF".to_string(),
678 vec![unit, f.expression, f.this],
679 ))))
680 }
681
682 Expression::StringAgg(f) => {
685 let mut args = vec![f.this.clone()];
686 if let Some(separator) = &f.separator {
687 args.push(separator.clone());
688 }
689 Ok(Expression::Function(Box::new(Function::new(
690 "LISTAGG".to_string(),
691 args,
692 ))))
693 }
694
695 Expression::StartsWith(f) => Ok(Expression::Function(Box::new(Function::new(
697 "STARTSWITH".to_string(),
698 vec![f.this, f.expression],
699 )))),
700
701 Expression::EndsWith(f) => Ok(Expression::EndsWith(f)),
703
704 Expression::Stuff(f) => {
706 let mut args = vec![*f.this];
707 if let Some(start) = f.start {
708 args.push(*start);
709 }
710 if let Some(length) = f.length {
711 args.push(Expression::number(length));
712 }
713 args.push(*f.expression);
714 Ok(Expression::Function(Box::new(Function::new(
715 "INSERT".to_string(),
716 args,
717 ))))
718 }
719
720 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
723 "SHA1".to_string(),
724 vec![f.this],
725 )))),
726
727 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
729 "SHA1_BINARY".to_string(),
730 vec![f.this],
731 )))),
732
733 Expression::SHA2Digest(f) => Ok(Expression::Function(Box::new(Function::new(
735 "SHA2_BINARY".to_string(),
736 vec![*f.this],
737 )))),
738
739 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
741 "MD5_BINARY".to_string(),
742 vec![*f.this],
743 )))),
744
745 Expression::MD5NumberLower64(f) => Ok(Expression::Function(Box::new(Function::new(
747 "MD5_NUMBER_LOWER64".to_string(),
748 vec![f.this],
749 )))),
750
751 Expression::MD5NumberUpper64(f) => Ok(Expression::Function(Box::new(Function::new(
753 "MD5_NUMBER_UPPER64".to_string(),
754 vec![f.this],
755 )))),
756
757 Expression::CosineDistance(f) => Ok(Expression::Function(Box::new(Function::new(
760 "VECTOR_COSINE_SIMILARITY".to_string(),
761 vec![*f.this, *f.expression],
762 )))),
763
764 Expression::DotProduct(f) => Ok(Expression::Function(Box::new(Function::new(
766 "VECTOR_INNER_PRODUCT".to_string(),
767 vec![*f.this, *f.expression],
768 )))),
769
770 Expression::EuclideanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
772 "VECTOR_L2_DISTANCE".to_string(),
773 vec![*f.this, *f.expression],
774 )))),
775
776 Expression::ManhattanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
778 "VECTOR_L1_DISTANCE".to_string(),
779 vec![*f.this, *f.expression],
780 )))),
781
782 Expression::JSONFormat(f) => {
785 let mut args = Vec::new();
786 if let Some(this) = f.this {
787 args.push(*this);
788 }
789 Ok(Expression::Function(Box::new(Function::new(
790 "TO_JSON".to_string(),
791 args,
792 ))))
793 }
794
795 Expression::JSONKeys(f) => Ok(Expression::Function(Box::new(Function::new(
797 "OBJECT_KEYS".to_string(),
798 vec![*f.this],
799 )))),
800
801 Expression::GetExtract(f) => Ok(Expression::Function(Box::new(Function::new(
803 "GET".to_string(),
804 vec![*f.this, *f.expression],
805 )))),
806
807 Expression::StarMap(f) => Ok(Expression::Function(Box::new(Function::new(
809 "OBJECT_CONSTRUCT".to_string(),
810 vec![f.this, f.expression],
811 )))),
812
813 Expression::LowerHex(f) => Ok(Expression::Function(Box::new(Function::new(
815 "TO_CHAR".to_string(),
816 vec![f.this],
817 )))),
818
819 Expression::Skewness(f) => Ok(Expression::Function(Box::new(Function::new(
821 "SKEW".to_string(),
822 vec![f.this],
823 )))),
824
825 Expression::StPoint(f) => Ok(Expression::Function(Box::new(Function::new(
827 "ST_MAKEPOINT".to_string(),
828 vec![*f.this, *f.expression],
829 )))),
830
831 Expression::FromTimeZone(f) => Ok(Expression::Function(Box::new(Function::new(
833 "CONVERT_TIMEZONE".to_string(),
834 vec![*f.this],
835 )))),
836
837 Expression::Unhex(f) => Ok(Expression::Function(Box::new(Function::new(
840 "HEX_DECODE_BINARY".to_string(),
841 vec![*f.this],
842 )))),
843
844 Expression::UnixToTime(f) => {
846 let mut args = vec![*f.this];
847 if let Some(scale) = f.scale {
848 args.push(Expression::number(scale));
849 }
850 Ok(Expression::Function(Box::new(Function::new(
851 "TO_TIMESTAMP".to_string(),
852 args,
853 ))))
854 }
855
856 Expression::IfFunc(f) => Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
859 condition: f.condition,
860 true_value: f.true_value,
861 false_value: Some(
862 f.false_value
863 .unwrap_or(Expression::Null(crate::expressions::Null)),
864 ),
865 original_name: Some("IFF".to_string()),
866 inferred_type: None,
867 }))),
868
869 Expression::ApproxDistinct(f) => Ok(Expression::Function(Box::new(Function::new(
872 "APPROX_COUNT_DISTINCT".to_string(),
873 vec![f.this],
874 )))),
875
876 Expression::ArgMax(f) => Ok(Expression::Function(Box::new(Function::new(
878 "MAX_BY".to_string(),
879 vec![*f.this, *f.expression],
880 )))),
881
882 Expression::ArgMin(f) => Ok(Expression::Function(Box::new(Function::new(
884 "MIN_BY".to_string(),
885 vec![*f.this, *f.expression],
886 )))),
887
888 Expression::Random(_) => Ok(Expression::Random(crate::expressions::Random)),
891
892 Expression::Rand(r) => Ok(Expression::Rand(r)),
894
895 Expression::Uuid(u) => Ok(Expression::Uuid(u)),
898
899 Expression::Map(f) => Ok(Expression::Function(Box::new(Function::new(
902 "OBJECT_CONSTRUCT".to_string(),
903 f.keys
904 .into_iter()
905 .zip(f.values.into_iter())
906 .flat_map(|(k, v)| vec![k, v])
907 .collect(),
908 )))),
909
910 Expression::MapFunc(f) => Ok(Expression::Function(Box::new(Function::new(
912 "OBJECT_CONSTRUCT".to_string(),
913 f.keys
914 .into_iter()
915 .zip(f.values.into_iter())
916 .flat_map(|(k, v)| vec![k, v])
917 .collect(),
918 )))),
919
920 Expression::VarMap(f) => Ok(Expression::Function(Box::new(Function::new(
922 "OBJECT_CONSTRUCT".to_string(),
923 f.keys
924 .into_iter()
925 .zip(f.values.into_iter())
926 .flat_map(|(k, v)| vec![k, v])
927 .collect(),
928 )))),
929
930 Expression::JsonObject(f) => Ok(Expression::Function(Box::new(Function::new(
933 "OBJECT_CONSTRUCT_KEEP_NULL".to_string(),
934 f.pairs.into_iter().flat_map(|(k, v)| vec![k, v]).collect(),
935 )))),
936
937 Expression::JsonExtractScalar(f) => Ok(Expression::Function(Box::new(Function::new(
939 "JSON_EXTRACT_PATH_TEXT".to_string(),
940 vec![f.this, f.path],
941 )))),
942
943 Expression::Struct(f) => Ok(Expression::Function(Box::new(Function::new(
946 "OBJECT_CONSTRUCT".to_string(),
947 f.fields
948 .into_iter()
949 .flat_map(|(name, expr)| {
950 let key = match name {
951 Some(n) => Expression::string(n),
952 None => Expression::Null(crate::expressions::Null),
953 };
954 vec![key, expr]
955 })
956 .collect(),
957 )))),
958
959 Expression::JSONPathRoot(_) => Ok(Expression::Literal(
962 crate::expressions::Literal::String(String::new()),
963 )),
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(crate::expressions::Literal::String(s)) => {
1464 Expression::Identifier(crate::expressions::Identifier {
1465 name: s.clone(),
1466 quoted: false,
1467 trailing_comments: Vec::new(),
1468 span: None,
1469 })
1470 }
1471 Expression::Identifier(id) => {
1473 if let Some(canonical) = Self::map_date_part(&id.name) {
1474 Expression::Identifier(crate::expressions::Identifier {
1475 name: canonical.to_string(),
1476 quoted: false,
1477 trailing_comments: Vec::new(),
1478 span: None,
1479 })
1480 } else {
1481 expr
1483 }
1484 }
1485 Expression::Var(v) => {
1486 if let Some(canonical) = Self::map_date_part(&v.this) {
1487 Expression::Identifier(crate::expressions::Identifier {
1488 name: canonical.to_string(),
1489 quoted: false,
1490 trailing_comments: Vec::new(),
1491 span: None,
1492 })
1493 } else {
1494 expr
1495 }
1496 }
1497 Expression::Column(col) if col.table.is_none() => {
1499 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1500 Expression::Identifier(crate::expressions::Identifier {
1501 name: canonical.to_string(),
1502 quoted: false,
1503 trailing_comments: Vec::new(),
1504 span: None,
1505 })
1506 } else {
1507 expr
1509 }
1510 }
1511 _ => expr,
1512 }
1513 }
1514
1515 fn transform_date_part_arg_identifiers_only(&self, expr: Expression) -> Expression {
1518 match &expr {
1519 Expression::Identifier(id) => {
1520 if let Some(canonical) = Self::map_date_part(&id.name) {
1521 Expression::Identifier(crate::expressions::Identifier {
1522 name: canonical.to_string(),
1523 quoted: false,
1524 trailing_comments: Vec::new(),
1525 span: None,
1526 })
1527 } else {
1528 expr
1529 }
1530 }
1531 Expression::Var(v) => {
1532 if let Some(canonical) = Self::map_date_part(&v.this) {
1533 Expression::Identifier(crate::expressions::Identifier {
1534 name: canonical.to_string(),
1535 quoted: false,
1536 trailing_comments: Vec::new(),
1537 span: None,
1538 })
1539 } else {
1540 expr
1541 }
1542 }
1543 Expression::Column(col) if col.table.is_none() => {
1544 if let Some(canonical) = Self::map_date_part(&col.name.name) {
1545 Expression::Identifier(crate::expressions::Identifier {
1546 name: canonical.to_string(),
1547 quoted: false,
1548 trailing_comments: Vec::new(),
1549 span: None,
1550 })
1551 } else {
1552 expr
1553 }
1554 }
1555 _ => expr,
1556 }
1557 }
1558
1559 fn transform_json_path(path: &str) -> String {
1563 fn is_safe_identifier(s: &str) -> bool {
1566 if s.is_empty() {
1567 return false;
1568 }
1569 let mut chars = s.chars();
1570 match chars.next() {
1571 Some(c) if c.is_ascii_alphabetic() || c == '_' => {}
1572 _ => return false,
1573 }
1574 chars.all(|c| c.is_ascii_alphanumeric() || c == '_')
1575 }
1576
1577 if !path.contains('.') && !path.contains('[') && !path.contains(':') {
1580 if is_safe_identifier(path) {
1581 return path.to_string();
1582 } else {
1583 return format!("[\"{}\"]", path);
1585 }
1586 }
1587
1588 let result = path.replace(':', ".");
1591 result
1592 }
1593
1594 fn transform_interval(&self, interval: crate::expressions::Interval) -> Result<Expression> {
1596 use crate::expressions::{Interval, Literal};
1597
1598 fn expand_unit(abbr: &str) -> &'static str {
1600 match abbr.to_uppercase().as_str() {
1601 "D" => "DAY",
1602 "H" => "HOUR",
1603 "M" => "MINUTE",
1604 "MS" => "MILLISECOND",
1605 "NS" => "NANOSECOND",
1606 "Q" => "QUARTER",
1607 "S" => "SECOND",
1608 "US" => "MICROSECOND",
1609 "W" => "WEEK",
1610 "Y" => "YEAR",
1611 "WEEK" | "WEEKS" => "WEEK",
1613 "DAY" | "DAYS" => "DAY",
1614 "HOUR" | "HOURS" => "HOUR",
1615 "MINUTE" | "MINUTES" => "MINUTE",
1616 "SECOND" | "SECONDS" => "SECOND",
1617 "MONTH" | "MONTHS" => "MONTH",
1618 "YEAR" | "YEARS" => "YEAR",
1619 "QUARTER" | "QUARTERS" => "QUARTER",
1620 "MILLISECOND" | "MILLISECONDS" => "MILLISECOND",
1621 "MICROSECOND" | "MICROSECONDS" => "MICROSECOND",
1622 "NANOSECOND" | "NANOSECONDS" => "NANOSECOND",
1623 _ => "", }
1625 }
1626
1627 fn parse_interval_string(s: &str) -> Option<(&str, &str)> {
1629 let s = s.trim();
1630
1631 let mut num_end = 0;
1634 let mut chars = s.chars().peekable();
1635
1636 if chars.peek() == Some(&'-') {
1638 chars.next();
1639 num_end += 1;
1640 }
1641
1642 while let Some(&c) = chars.peek() {
1644 if c.is_ascii_digit() {
1645 chars.next();
1646 num_end += 1;
1647 } else {
1648 break;
1649 }
1650 }
1651
1652 if chars.peek() == Some(&'.') {
1654 chars.next();
1655 num_end += 1;
1656 while let Some(&c) = chars.peek() {
1657 if c.is_ascii_digit() {
1658 chars.next();
1659 num_end += 1;
1660 } else {
1661 break;
1662 }
1663 }
1664 }
1665
1666 if num_end == 0 || (num_end == 1 && s.starts_with('-')) {
1667 return None; }
1669
1670 let value = &s[..num_end];
1671 let rest = s[num_end..].trim();
1672
1673 if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_alphabetic()) {
1675 return None;
1676 }
1677
1678 Some((value, rest))
1679 }
1680
1681 if let Some(Expression::Literal(Literal::String(ref s))) = interval.this {
1683 if let Some((value, unit)) = parse_interval_string(s) {
1684 let expanded = expand_unit(unit);
1685 if !expanded.is_empty() {
1686 let new_value = format!("{} {}", value, expanded);
1688
1689 return Ok(Expression::Interval(Box::new(Interval {
1690 this: Some(Expression::Literal(Literal::String(new_value))),
1691 unit: None, })));
1693 }
1694 }
1695 }
1696
1697 Ok(Expression::Interval(Box::new(interval)))
1699 }
1700
1701 fn transform_function(&self, f: Function) -> Result<Expression> {
1702 let transformed_args: Vec<Expression> = f
1704 .args
1705 .into_iter()
1706 .map(|arg| self.transform_expr(arg))
1707 .collect::<Result<Vec<_>>>()?;
1708
1709 let f = Function {
1710 name: f.name,
1711 args: transformed_args,
1712 distinct: f.distinct,
1713 trailing_comments: f.trailing_comments,
1714 use_bracket_syntax: f.use_bracket_syntax,
1715 no_parens: f.no_parens,
1716 quoted: f.quoted,
1717 span: None,
1718 inferred_type: None,
1719 };
1720
1721 let name_upper = f.name.to_uppercase();
1722 match name_upper.as_str() {
1723 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1725 original_name: None,
1726 expressions: f.args,
1727 inferred_type: None,
1728 }))),
1729
1730 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
1732 original_name: None,
1733 expressions: f.args,
1734 inferred_type: None,
1735 }))),
1736
1737 "NVL2" => Ok(Expression::Function(Box::new(f))),
1739
1740 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1742 Function::new("LISTAGG".to_string(), f.args),
1743 ))),
1744
1745 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1747 Function::new("LISTAGG".to_string(), f.args),
1748 ))),
1749
1750 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
1752 "SUBSTRING".to_string(),
1753 f.args,
1754 )))),
1755
1756 "UNNEST" => Ok(Expression::Function(Box::new(Function::new(
1758 "FLATTEN".to_string(),
1759 f.args,
1760 )))),
1761
1762 "EXPLODE" => Ok(Expression::Function(Box::new(Function::new(
1764 "FLATTEN".to_string(),
1765 f.args,
1766 )))),
1767
1768 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1770
1771 "NOW" => Ok(Expression::Function(Box::new(Function {
1773 name: "CURRENT_TIMESTAMP".to_string(),
1774 args: f.args,
1775 distinct: false,
1776 trailing_comments: Vec::new(),
1777 use_bracket_syntax: false,
1778 no_parens: f.no_parens,
1779 quoted: false,
1780 span: None,
1781 inferred_type: None,
1782 }))),
1783
1784 "GETDATE" => Ok(Expression::Function(Box::new(Function {
1786 name: "CURRENT_TIMESTAMP".to_string(),
1787 args: f.args,
1788 distinct: false,
1789 trailing_comments: Vec::new(),
1790 use_bracket_syntax: false,
1791 no_parens: f.no_parens,
1792 quoted: false,
1793 span: None,
1794 inferred_type: None,
1795 }))),
1796
1797 "CURRENT_TIMESTAMP" if f.args.is_empty() => {
1801 Ok(Expression::Function(Box::new(Function {
1802 name: "CURRENT_TIMESTAMP".to_string(),
1803 args: Vec::new(),
1804 distinct: false,
1805 trailing_comments: Vec::new(),
1806 use_bracket_syntax: false,
1807 no_parens: false, quoted: false,
1809 span: None,
1810 inferred_type: None,
1811 })))
1812 }
1813
1814 "TO_DATE" => {
1818 if f.args.len() == 1 {
1819 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
1820 {
1821 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
1823 return Ok(Expression::Cast(Box::new(Cast {
1824 this: f.args.into_iter().next().unwrap(),
1825 to: crate::expressions::DataType::Date,
1826 double_colon_syntax: false,
1827 trailing_comments: Vec::new(),
1828 format: None,
1829 default: None,
1830 inferred_type: None,
1831 })));
1832 }
1833 }
1834 }
1835 let mut args = f.args;
1837 if args.len() >= 2 {
1838 args[1] = Self::normalize_format_arg(args[1].clone());
1839 }
1840 Ok(Expression::Function(Box::new(Function::new(
1841 "TO_DATE".to_string(),
1842 args,
1843 ))))
1844 }
1845
1846 "TO_TIME" => {
1848 if f.args.len() == 1 {
1849 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
1850 {
1851 return Ok(Expression::Cast(Box::new(Cast {
1852 this: f.args.into_iter().next().unwrap(),
1853 to: crate::expressions::DataType::Time {
1854 precision: None,
1855 timezone: false,
1856 },
1857 double_colon_syntax: false,
1858 trailing_comments: Vec::new(),
1859 format: None,
1860 default: None,
1861 inferred_type: None,
1862 })));
1863 }
1864 }
1865 let mut args = f.args;
1867 if args.len() >= 2 {
1868 args[1] = Self::normalize_format_arg(args[1].clone());
1869 }
1870 Ok(Expression::Function(Box::new(Function::new(
1871 "TO_TIME".to_string(),
1872 args,
1873 ))))
1874 }
1875
1876 "TO_TIMESTAMP" => {
1883 let args = f.args;
1884 if args.len() == 1 {
1885 let arg = &args[0];
1886 match arg {
1887 Expression::Literal(Literal::String(s)) if Self::looks_like_datetime(s) => {
1888 return Ok(Expression::Cast(Box::new(Cast {
1890 this: args.into_iter().next().unwrap(),
1891 to: DataType::Timestamp {
1892 precision: None,
1893 timezone: false,
1894 },
1895 double_colon_syntax: false,
1896 trailing_comments: vec![],
1897 format: None,
1898 default: None,
1899 inferred_type: None,
1900 })));
1901 }
1902 Expression::Literal(Literal::String(s)) if Self::looks_like_epoch(s) => {
1903 return Ok(Expression::UnixToTime(Box::new(
1905 crate::expressions::UnixToTime {
1906 this: Box::new(args.into_iter().next().unwrap()),
1907 scale: None,
1908 zone: None,
1909 hours: None,
1910 minutes: None,
1911 format: None,
1912 target_type: None,
1913 },
1914 )));
1915 }
1916 Expression::Literal(Literal::Number(_)) | Expression::Neg(_) => {
1917 return Ok(Expression::UnixToTime(Box::new(
1919 crate::expressions::UnixToTime {
1920 this: Box::new(args.into_iter().next().unwrap()),
1921 scale: None,
1922 zone: None,
1923 hours: None,
1924 minutes: None,
1925 format: None,
1926 target_type: None,
1927 },
1928 )));
1929 }
1930 _ => {
1931 return Ok(Expression::Function(Box::new(Function::new(
1933 "TO_TIMESTAMP".to_string(),
1934 args,
1935 ))));
1936 }
1937 }
1938 } else if args.len() == 2 {
1939 let second_arg = &args[1];
1940 let is_int_scale = match second_arg {
1942 Expression::Literal(Literal::Number(n)) => n.parse::<i64>().is_ok(),
1943 _ => false,
1944 };
1945
1946 if is_int_scale {
1947 let mut args_iter = args.into_iter();
1949 let value = args_iter.next().unwrap();
1950 let scale_expr = args_iter.next().unwrap();
1951 let scale = if let Expression::Literal(Literal::Number(n)) = &scale_expr {
1952 n.parse::<i64>().ok()
1953 } else {
1954 None
1955 };
1956 return Ok(Expression::UnixToTime(Box::new(
1957 crate::expressions::UnixToTime {
1958 this: Box::new(value),
1959 scale,
1960 zone: None,
1961 hours: None,
1962 minutes: None,
1963 format: None,
1964 target_type: None,
1965 },
1966 )));
1967 } else {
1968 let mut args_iter = args.into_iter();
1970 let value = args_iter.next().unwrap();
1971 let format_expr = args_iter.next().unwrap();
1972 let format_str = match &format_expr {
1973 Expression::Literal(Literal::String(s)) => s.clone(),
1974 _ => {
1975 return Ok(Expression::Function(Box::new(Function::new(
1977 "TO_TIMESTAMP".to_string(),
1978 vec![value, format_expr],
1979 ))));
1980 }
1981 };
1982 let normalized_format = Self::normalize_snowflake_format(&format_str);
1984 return Ok(Expression::StrToTime(Box::new(
1985 crate::expressions::StrToTime {
1986 this: Box::new(value),
1987 format: normalized_format,
1988 zone: None,
1989 safe: None,
1990 target_type: None,
1991 },
1992 )));
1993 }
1994 }
1995 Ok(Expression::Function(Box::new(Function::new(
1997 "TO_TIMESTAMP".to_string(),
1998 args,
1999 ))))
2000 }
2001
2002 "TO_CHAR" => Ok(Expression::Function(Box::new(f))),
2004
2005 "ROUND"
2008 if f.args
2009 .iter()
2010 .any(|a| matches!(a, Expression::NamedArgument(_))) =>
2011 {
2012 let mut expr_val = None;
2013 let mut scale_val = None;
2014 let mut rounding_mode_val = None;
2015 for arg in &f.args {
2016 if let Expression::NamedArgument(na) = arg {
2017 match na.name.name.to_uppercase().as_str() {
2018 "EXPR" => expr_val = Some(na.value.clone()),
2019 "SCALE" => scale_val = Some(na.value.clone()),
2020 "ROUNDING_MODE" => rounding_mode_val = Some(na.value.clone()),
2021 _ => {}
2022 }
2023 }
2024 }
2025 if let Some(expr) = expr_val {
2026 let mut args = vec![expr];
2027 if let Some(scale) = scale_val {
2028 args.push(scale);
2029 }
2030 if let Some(mode) = rounding_mode_val {
2031 args.push(mode);
2032 }
2033 Ok(Expression::Function(Box::new(Function::new(
2034 "ROUND".to_string(),
2035 args,
2036 ))))
2037 } else {
2038 Ok(Expression::Function(Box::new(f)))
2039 }
2040 }
2041
2042 "DATE_FORMAT" => {
2045 let mut args = f.args;
2046 if !args.is_empty() {
2048 if matches!(&args[0], Expression::Literal(Literal::String(_))) {
2049 args[0] = Expression::Cast(Box::new(crate::expressions::Cast {
2050 this: args[0].clone(),
2051 to: DataType::Timestamp {
2052 precision: None,
2053 timezone: false,
2054 },
2055 trailing_comments: Vec::new(),
2056 double_colon_syntax: false,
2057 format: None,
2058 default: None,
2059 inferred_type: None,
2060 }));
2061 }
2062 }
2063 if args.len() >= 2 {
2065 if let Expression::Literal(Literal::String(ref fmt)) = args[1] {
2066 let sf_fmt = strftime_to_snowflake_format(fmt);
2067 args[1] = Expression::Literal(Literal::String(sf_fmt));
2068 }
2069 }
2070 Ok(Expression::Function(Box::new(Function::new(
2071 "TO_CHAR".to_string(),
2072 args,
2073 ))))
2074 }
2075
2076 "ARRAY" => Ok(Expression::Function(Box::new(Function::new(
2078 "ARRAY_CONSTRUCT".to_string(),
2079 f.args,
2080 )))),
2081
2082 "STRUCT" => {
2085 let mut oc_args = Vec::new();
2086 for arg in f.args {
2087 match arg {
2088 Expression::Alias(a) => {
2089 oc_args.push(Expression::Literal(crate::expressions::Literal::String(
2091 a.alias.name.clone(),
2092 )));
2093 oc_args.push(a.this);
2094 }
2095 other => {
2096 oc_args.push(other);
2098 }
2099 }
2100 }
2101 Ok(Expression::Function(Box::new(Function::new(
2102 "OBJECT_CONSTRUCT".to_string(),
2103 oc_args,
2104 ))))
2105 }
2106
2107 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2109 "GET_PATH".to_string(),
2110 f.args,
2111 )))),
2112
2113 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
2115 "JSON_EXTRACT_PATH_TEXT".to_string(),
2116 f.args,
2117 )))),
2118
2119 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
2121 f.args.into_iter().next().unwrap(),
2122 )))),
2123
2124 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
2126 this: f.args.into_iter().next().unwrap(),
2127 decimals: None,
2128 to: None,
2129 }))),
2130
2131 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
2133
2134 "SPLIT" => Ok(Expression::Function(Box::new(f))),
2136
2137 "ARRAY_AGG" => Ok(Expression::Function(Box::new(f))),
2139
2140 "JSON_PARSE" | "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
2142 "PARSE_JSON".to_string(),
2143 f.args,
2144 )))),
2145
2146 "RAND" => {
2148 let seed = f.args.first().cloned().map(Box::new);
2149 Ok(Expression::Rand(Box::new(crate::expressions::Rand {
2150 seed,
2151 lower: None,
2152 upper: None,
2153 })))
2154 }
2155
2156 "SHA" => Ok(Expression::Function(Box::new(Function::new(
2158 "SHA1".to_string(),
2159 f.args,
2160 )))),
2161
2162 "APPROX_DISTINCT" => Ok(Expression::Function(Box::new(Function::new(
2164 "APPROX_COUNT_DISTINCT".to_string(),
2165 f.args,
2166 )))),
2167
2168 "GEN_RANDOM_UUID" | "UUID" => {
2170 Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2171 this: None,
2172 name: None,
2173 is_string: None,
2174 })))
2175 }
2176
2177 "NEWID" => Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2179 this: None,
2180 name: None,
2181 is_string: None,
2182 }))),
2183
2184 "UUID_STRING" => {
2186 if f.args.is_empty() {
2187 Ok(Expression::Uuid(Box::new(crate::expressions::Uuid {
2188 this: None,
2189 name: None,
2190 is_string: None,
2191 })))
2192 } else {
2193 Ok(Expression::Function(Box::new(Function::new(
2194 "UUID_STRING".to_string(),
2195 f.args,
2196 ))))
2197 }
2198 }
2199
2200 "IF" if f.args.len() >= 2 => {
2202 let mut args = f.args;
2203 let condition = args.remove(0);
2204 let true_val = args.remove(0);
2205 let false_val = if !args.is_empty() {
2206 Some(args.remove(0))
2207 } else {
2208 None
2209 };
2210 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2211 condition,
2212 true_value: true_val,
2213 false_value: Some(
2214 false_val.unwrap_or(Expression::Null(crate::expressions::Null)),
2215 ),
2216 original_name: Some("IFF".to_string()),
2217 inferred_type: None,
2218 })))
2219 }
2220
2221 "SQUARE" if f.args.len() == 1 => {
2223 let x = f.args.into_iter().next().unwrap();
2224 Ok(Expression::Power(Box::new(
2225 crate::expressions::BinaryFunc {
2226 original_name: None,
2227 this: x,
2228 expression: Expression::number(2),
2229 inferred_type: None,
2230 },
2231 )))
2232 }
2233
2234 "POW" if f.args.len() == 2 => {
2236 let mut args = f.args.into_iter();
2237 let x = args.next().unwrap();
2238 let y = args.next().unwrap();
2239 Ok(Expression::Power(Box::new(
2240 crate::expressions::BinaryFunc {
2241 original_name: None,
2242 this: x,
2243 expression: y,
2244 inferred_type: None,
2245 },
2246 )))
2247 }
2248
2249 "MOD" if f.args.len() == 2 => {
2251 let mut args = f.args.into_iter();
2252 let x = args.next().unwrap();
2253 let y = args.next().unwrap();
2254 Ok(Expression::Mod(Box::new(crate::expressions::BinaryOp {
2255 left: x,
2256 right: y,
2257 left_comments: Vec::new(),
2258 operator_comments: Vec::new(),
2259 trailing_comments: Vec::new(),
2260 inferred_type: None,
2261 })))
2262 }
2263
2264 "APPROXIMATE_JACCARD_INDEX" => Ok(Expression::Function(Box::new(Function::new(
2266 "APPROXIMATE_SIMILARITY".to_string(),
2267 f.args,
2268 )))),
2269
2270 "ARRAY_CONSTRUCT" => Ok(Expression::ArrayFunc(Box::new(
2272 crate::expressions::ArrayConstructor {
2273 expressions: f.args,
2274 bracket_notation: true,
2275 use_list_keyword: false,
2276 },
2277 ))),
2278
2279 "APPROX_TOP_K" if f.args.len() == 1 => {
2281 let mut args = f.args;
2282 args.push(Expression::number(1));
2283 Ok(Expression::Function(Box::new(Function::new(
2284 "APPROX_TOP_K".to_string(),
2285 args,
2286 ))))
2287 }
2288
2289 "TO_DECIMAL" | "TO_NUMERIC" => Ok(Expression::Function(Box::new(Function::new(
2291 "TO_NUMBER".to_string(),
2292 f.args,
2293 )))),
2294
2295 "TRY_TO_DECIMAL" | "TRY_TO_NUMERIC" => Ok(Expression::Function(Box::new(
2297 Function::new("TRY_TO_NUMBER".to_string(), f.args),
2298 ))),
2299
2300 "STDDEV_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2302 "STDDEV".to_string(),
2303 f.args,
2304 )))),
2305
2306 "STRTOK" if f.args.len() >= 1 => {
2308 let mut args = f.args;
2309 if args.len() == 1 {
2311 args.push(Expression::string(" ".to_string()));
2312 }
2313 if args.len() == 2 {
2315 args.push(Expression::number(1));
2316 }
2317 Ok(Expression::Function(Box::new(Function::new(
2318 "SPLIT_PART".to_string(),
2319 args,
2320 ))))
2321 }
2322
2323 "WEEKOFYEAR" => Ok(Expression::Function(Box::new(Function::new(
2325 "WEEK".to_string(),
2326 f.args,
2327 )))),
2328
2329 "LIKE" if f.args.len() >= 2 => {
2331 let mut args = f.args.into_iter();
2332 let left = args.next().unwrap();
2333 let right = args.next().unwrap();
2334 let escape = args.next();
2335 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
2336 left,
2337 right,
2338 escape,
2339 quantifier: None,
2340 inferred_type: None,
2341 })))
2342 }
2343
2344 "ILIKE" if f.args.len() >= 2 => {
2346 let mut args = f.args.into_iter();
2347 let left = args.next().unwrap();
2348 let right = args.next().unwrap();
2349 let escape = args.next();
2350 Ok(Expression::ILike(Box::new(crate::expressions::LikeOp {
2351 left,
2352 right,
2353 escape,
2354 quantifier: None,
2355 inferred_type: None,
2356 })))
2357 }
2358
2359 "RLIKE" if f.args.len() >= 2 => {
2361 let mut args = f.args.into_iter();
2362 let left = args.next().unwrap();
2363 let pattern = args.next().unwrap();
2364 let flags = args.next();
2365 Ok(Expression::RegexpLike(Box::new(
2366 crate::expressions::RegexpFunc {
2367 this: left,
2368 pattern,
2369 flags,
2370 },
2371 )))
2372 }
2373
2374 "IFF" if f.args.len() >= 2 => {
2376 let mut args = f.args;
2377 let condition = args.remove(0);
2378 let true_value = args.remove(0);
2379 let false_value = if !args.is_empty() {
2380 Some(args.remove(0))
2381 } else {
2382 None
2383 };
2384 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
2385 condition,
2386 true_value,
2387 false_value,
2388 original_name: Some("IFF".to_string()),
2389 inferred_type: None,
2390 })))
2391 }
2392
2393 "TIMESTAMP_NTZ_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMPNTZFROMPARTS" => {
2395 Ok(Expression::Function(Box::new(Function::new(
2396 "TIMESTAMP_FROM_PARTS".to_string(),
2397 f.args,
2398 ))))
2399 }
2400
2401 "TIMESTAMPLTZFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2403 "TIMESTAMP_LTZ_FROM_PARTS".to_string(),
2404 f.args,
2405 )))),
2406
2407 "TIMESTAMPTZFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2409 "TIMESTAMP_TZ_FROM_PARTS".to_string(),
2410 f.args,
2411 )))),
2412
2413 "DATEADD" if f.args.len() >= 1 => {
2415 let mut args = f.args;
2416 args[0] = self.transform_date_part_arg(args[0].clone());
2417 Ok(Expression::Function(Box::new(Function::new(
2418 "DATEADD".to_string(),
2419 args,
2420 ))))
2421 }
2422
2423 "DATEDIFF" if f.args.len() >= 1 => {
2426 let mut args = f.args;
2427 args[0] = self.transform_date_part_arg(args[0].clone());
2428 for i in 1..args.len() {
2431 if let Expression::Function(ref func) = args[i] {
2432 if func.name == "_POLYGLOT_TO_DATE" {
2433 let inner_args = func.args.clone();
2434 args[i] = Expression::Function(Box::new(Function::new(
2435 "TO_DATE".to_string(),
2436 inner_args,
2437 )));
2438 }
2439 }
2440 }
2441 Ok(Expression::Function(Box::new(Function::new(
2442 "DATEDIFF".to_string(),
2443 args,
2444 ))))
2445 }
2446
2447 "TIMEDIFF" => Ok(Expression::Function(Box::new(Function::new(
2449 "DATEDIFF".to_string(),
2450 f.args,
2451 )))),
2452
2453 "TIMESTAMPDIFF" => Ok(Expression::Function(Box::new(Function::new(
2455 "DATEDIFF".to_string(),
2456 f.args,
2457 )))),
2458
2459 "TIMESTAMPADD" => Ok(Expression::Function(Box::new(Function::new(
2461 "DATEADD".to_string(),
2462 f.args,
2463 )))),
2464
2465 "TIMEADD" => Ok(Expression::Function(Box::new(f))),
2467
2468 "DATEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2470 "DATE_FROM_PARTS".to_string(),
2471 f.args,
2472 )))),
2473
2474 "TIMEFROMPARTS" => Ok(Expression::Function(Box::new(Function::new(
2476 "TIME_FROM_PARTS".to_string(),
2477 f.args,
2478 )))),
2479
2480 "DAYOFWEEK" => Ok(Expression::Function(Box::new(f))),
2482
2483 "DAYOFMONTH" => Ok(Expression::Function(Box::new(f))),
2485
2486 "DAYOFYEAR" => Ok(Expression::Function(Box::new(f))),
2488
2489 "MONTHNAME" if f.args.len() == 1 => {
2492 let arg = f.args.into_iter().next().unwrap();
2493 Ok(Expression::Monthname(Box::new(
2494 crate::expressions::Monthname {
2495 this: Box::new(arg),
2496 abbreviated: Some(Box::new(Expression::Literal(Literal::String(
2497 "true".to_string(),
2498 )))),
2499 },
2500 )))
2501 }
2502
2503 "DAYNAME" if f.args.len() == 1 => {
2506 let arg = f.args.into_iter().next().unwrap();
2507 Ok(Expression::Dayname(Box::new(crate::expressions::Dayname {
2508 this: Box::new(arg),
2509 abbreviated: Some(Box::new(Expression::Literal(Literal::String(
2510 "true".to_string(),
2511 )))),
2512 })))
2513 }
2514
2515 "BOOLAND_AGG" | "BOOL_AND" | "LOGICAL_AND" if !f.args.is_empty() => {
2517 let arg = f.args.into_iter().next().unwrap();
2518 Ok(Expression::LogicalAnd(Box::new(AggFunc {
2519 this: arg,
2520 distinct: false,
2521 filter: None,
2522 order_by: Vec::new(),
2523 name: Some("BOOLAND_AGG".to_string()),
2524 ignore_nulls: None,
2525 having_max: None,
2526 limit: None,
2527 inferred_type: None,
2528 })))
2529 }
2530
2531 "BOOLOR_AGG" | "BOOL_OR" | "LOGICAL_OR" if !f.args.is_empty() => {
2533 let arg = f.args.into_iter().next().unwrap();
2534 Ok(Expression::LogicalOr(Box::new(AggFunc {
2535 this: arg,
2536 distinct: false,
2537 filter: None,
2538 order_by: Vec::new(),
2539 name: Some("BOOLOR_AGG".to_string()),
2540 ignore_nulls: None,
2541 having_max: None,
2542 limit: None,
2543 inferred_type: None,
2544 })))
2545 }
2546
2547 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
2549 let arg = f.args.into_iter().next().unwrap();
2550 Ok(Expression::Skewness(Box::new(AggFunc {
2551 this: arg,
2552 distinct: false,
2553 filter: None,
2554 order_by: Vec::new(),
2555 name: Some("SKEW".to_string()),
2556 ignore_nulls: None,
2557 having_max: None,
2558 limit: None,
2559 inferred_type: None,
2560 })))
2561 }
2562
2563 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2565 "VARIANCE".to_string(),
2566 f.args,
2567 )))),
2568
2569 "VAR_POP" => Ok(Expression::Function(Box::new(Function::new(
2571 "VARIANCE_POP".to_string(),
2572 f.args,
2573 )))),
2574
2575 "DATE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2577 "TO_DATE".to_string(),
2578 f.args,
2579 )))),
2580 "DATE" if f.args.len() >= 2 => {
2584 let mut args = f.args;
2585 args[1] = Self::normalize_format_arg(args[1].clone());
2586 Ok(Expression::Function(Box::new(Function::new(
2587 "TO_DATE".to_string(),
2588 args,
2589 ))))
2590 }
2591 "_POLYGLOT_DATE" if f.args.len() >= 2 => {
2594 let mut args = f.args;
2595 args[1] = Self::normalize_format_arg(args[1].clone());
2596 Ok(Expression::Function(Box::new(Function::new(
2597 "DATE".to_string(),
2598 args,
2599 ))))
2600 }
2601
2602 "DESCRIBE" => Ok(Expression::Function(Box::new(f))),
2604
2605 "MD5_HEX" => Ok(Expression::Function(Box::new(Function::new(
2607 "MD5".to_string(),
2608 f.args,
2609 )))),
2610
2611 "SHA1_HEX" => Ok(Expression::Function(Box::new(Function::new(
2613 "SHA1".to_string(),
2614 f.args,
2615 )))),
2616
2617 "SHA2_HEX" => Ok(Expression::Function(Box::new(Function::new(
2619 "SHA2".to_string(),
2620 f.args,
2621 )))),
2622
2623 "LEVENSHTEIN" => Ok(Expression::Function(Box::new(Function::new(
2625 "EDITDISTANCE".to_string(),
2626 f.args,
2627 )))),
2628
2629 "BIT_NOT" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2631 "BITNOT".to_string(),
2632 f.args,
2633 )))),
2634
2635 "BIT_AND" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2637 "BITAND".to_string(),
2638 f.args,
2639 )))),
2640
2641 "BIT_OR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2643 "BITOR".to_string(),
2644 f.args,
2645 )))),
2646
2647 "BIT_XOR" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2649 "BITXOR".to_string(),
2650 f.args,
2651 )))),
2652
2653 "BIT_SHIFTLEFT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
2655 Function::new("BITSHIFTLEFT".to_string(), f.args),
2656 ))),
2657
2658 "BIT_SHIFTRIGHT" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(
2660 Function::new("BITSHIFTRIGHT".to_string(), f.args),
2661 ))),
2662
2663 "SYSTIMESTAMP" => Ok(Expression::Function(Box::new(Function {
2665 name: "CURRENT_TIMESTAMP".to_string(),
2666 args: f.args,
2667 distinct: false,
2668 trailing_comments: Vec::new(),
2669 use_bracket_syntax: false,
2670 no_parens: f.no_parens,
2671 quoted: false,
2672 span: None,
2673 inferred_type: None,
2674 }))),
2675
2676 "LOCALTIMESTAMP" => Ok(Expression::Function(Box::new(Function {
2678 name: "CURRENT_TIMESTAMP".to_string(),
2679 args: f.args,
2680 distinct: false,
2681 trailing_comments: Vec::new(),
2682 use_bracket_syntax: false,
2683 no_parens: f.no_parens,
2684 quoted: false,
2685 span: None,
2686 inferred_type: None,
2687 }))),
2688
2689 "SPACE" if f.args.len() == 1 => {
2691 let arg = f.args.into_iter().next().unwrap();
2692 Ok(Expression::Function(Box::new(Function::new(
2693 "REPEAT".to_string(),
2694 vec![Expression::Literal(Literal::String(" ".to_string())), arg],
2695 ))))
2696 }
2697
2698 "CEILING" => Ok(Expression::Function(Box::new(Function::new(
2700 "CEIL".to_string(),
2701 f.args,
2702 )))),
2703
2704 "LOG" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2706 "LN".to_string(),
2707 f.args,
2708 )))),
2709
2710 "REGEXP_SUBSTR_ALL" => Ok(Expression::Function(Box::new(Function::new(
2712 "REGEXP_EXTRACT_ALL".to_string(),
2713 f.args,
2714 )))),
2715
2716 "GET_PATH" if f.args.len() >= 2 => {
2720 let mut args = f.args;
2721 if let Expression::Literal(crate::expressions::Literal::String(path)) = &args[1] {
2723 let transformed = Self::transform_json_path(path);
2724 args[1] = Expression::Literal(crate::expressions::Literal::String(transformed));
2725 }
2726 Ok(Expression::Function(Box::new(Function::new(
2727 "GET_PATH".to_string(),
2728 args,
2729 ))))
2730 }
2731 "GET_PATH" => Ok(Expression::Function(Box::new(f))),
2732
2733 "FLATTEN" => Ok(Expression::Function(Box::new(f))),
2735
2736 "DATE_TRUNC" if f.args.len() >= 1 => {
2739 let mut args = f.args;
2740 let unit_name = match &args[0] {
2742 Expression::Identifier(id) => Some(id.name.as_str()),
2743 Expression::Column(col) if col.table.is_none() => Some(col.name.name.as_str()),
2744 _ => None,
2745 };
2746 if let Some(name) = unit_name {
2747 let canonical = Self::map_date_part(name).unwrap_or(name);
2748 args[0] = Expression::Literal(crate::expressions::Literal::String(
2749 canonical.to_uppercase(),
2750 ));
2751 }
2752 Ok(Expression::Function(Box::new(Function::new(
2753 "DATE_TRUNC".to_string(),
2754 args,
2755 ))))
2756 }
2757
2758 "DATE_PART" if f.args.len() >= 1 => {
2764 let mut args = f.args;
2765 let from_typed_literal = args.len() >= 2
2766 && matches!(
2767 &args[1],
2768 Expression::Literal(crate::expressions::Literal::Timestamp(_))
2769 | Expression::Literal(crate::expressions::Literal::Date(_))
2770 | Expression::Literal(crate::expressions::Literal::Time(_))
2771 | Expression::Literal(crate::expressions::Literal::Datetime(_))
2772 );
2773 if from_typed_literal {
2774 args[0] = self.transform_date_part_arg(args[0].clone());
2775 } else {
2776 args[0] = self.transform_date_part_arg_identifiers_only(args[0].clone());
2779 }
2780 Ok(Expression::Function(Box::new(Function::new(
2781 "DATE_PART".to_string(),
2782 args,
2783 ))))
2784 }
2785
2786 "OBJECT_CONSTRUCT" => Ok(Expression::Function(Box::new(f))),
2788
2789 "OBJECT_CONSTRUCT_KEEP_NULL" => Ok(Expression::Function(Box::new(f))),
2791
2792 "DESC" => Ok(Expression::Function(Box::new(Function::new(
2794 "DESCRIBE".to_string(),
2795 f.args,
2796 )))),
2797
2798 "RLIKE" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2800 "REGEXP_LIKE".to_string(),
2801 f.args,
2802 )))),
2803
2804 "TRANSFORM" => {
2809 let transformed_args: Vec<Expression> = f
2810 .args
2811 .into_iter()
2812 .map(|arg| {
2813 if let Expression::Lambda(lambda) = arg {
2814 self.transform_typed_lambda(*lambda)
2815 } else {
2816 arg
2817 }
2818 })
2819 .collect();
2820 Ok(Expression::Function(Box::new(Function::new(
2821 "TRANSFORM".to_string(),
2822 transformed_args,
2823 ))))
2824 }
2825
2826 "SEARCH" if f.args.len() >= 2 => {
2828 let mut args = f.args.into_iter();
2829 let this = Box::new(args.next().unwrap());
2830 let expression = Box::new(args.next().unwrap());
2831
2832 let mut analyzer: Option<Box<Expression>> = None;
2833 let mut search_mode: Option<Box<Expression>> = None;
2834
2835 for arg in args {
2837 if let Expression::NamedArgument(na) = &arg {
2838 let name_upper = na.name.name.to_uppercase();
2839 match name_upper.as_str() {
2840 "ANALYZER" => analyzer = Some(Box::new(arg)),
2841 "SEARCH_MODE" => search_mode = Some(Box::new(arg)),
2842 _ => {}
2843 }
2844 }
2845 }
2846
2847 Ok(Expression::Search(Box::new(crate::expressions::Search {
2848 this,
2849 expression,
2850 json_scope: None,
2851 analyzer,
2852 analyzer_options: None,
2853 search_mode,
2854 })))
2855 }
2856
2857 "CONVERT" if f.args.len() == 2 => {
2860 let value = f.args.get(0).cloned().unwrap();
2861 let type_arg = f.args.get(1).cloned().unwrap();
2862
2863 if let Expression::Column(col) = &type_arg {
2865 let type_name = col.name.name.to_uppercase();
2866 let data_type = match type_name.as_str() {
2867 "SQL_DOUBLE" => Some(DataType::Double {
2868 precision: None,
2869 scale: None,
2870 }),
2871 "SQL_VARCHAR" => Some(DataType::VarChar {
2872 length: None,
2873 parenthesized_length: false,
2874 }),
2875 "SQL_INTEGER" | "SQL_INT" => Some(DataType::Int {
2876 length: None,
2877 integer_spelling: false,
2878 }),
2879 "SQL_BIGINT" => Some(DataType::BigInt { length: None }),
2880 "SQL_SMALLINT" => Some(DataType::SmallInt { length: None }),
2881 "SQL_FLOAT" => Some(DataType::Float {
2882 precision: None,
2883 scale: None,
2884 real_spelling: false,
2885 }),
2886 "SQL_REAL" => Some(DataType::Float {
2887 precision: None,
2888 scale: None,
2889 real_spelling: true,
2890 }),
2891 "SQL_DECIMAL" => Some(DataType::Decimal {
2892 precision: None,
2893 scale: None,
2894 }),
2895 "SQL_DATE" => Some(DataType::Date),
2896 "SQL_TIME" => Some(DataType::Time {
2897 precision: None,
2898 timezone: false,
2899 }),
2900 "SQL_TIMESTAMP" => Some(DataType::Timestamp {
2901 precision: None,
2902 timezone: false,
2903 }),
2904 _ => None,
2905 };
2906
2907 if let Some(dt) = data_type {
2908 return Ok(Expression::Cast(Box::new(Cast {
2909 this: value,
2910 to: dt,
2911 double_colon_syntax: false,
2912 trailing_comments: vec![],
2913 format: None,
2914 default: None,
2915 inferred_type: None,
2916 })));
2917 }
2918 }
2919 Ok(Expression::Function(Box::new(f)))
2921 }
2922
2923 "TO_TIMESTAMP_TZ" => {
2926 if f.args.len() == 1 {
2927 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2928 {
2929 return Ok(Expression::Cast(Box::new(Cast {
2930 this: f.args.into_iter().next().unwrap(),
2931 to: DataType::Custom {
2932 name: "TIMESTAMPTZ".to_string(),
2933 },
2934 double_colon_syntax: false,
2935 trailing_comments: vec![],
2936 format: None,
2937 default: None,
2938 inferred_type: None,
2939 })));
2940 }
2941 }
2942 Ok(Expression::Function(Box::new(f)))
2943 }
2944
2945 "TO_TIMESTAMP_NTZ" => {
2947 if f.args.len() == 1 {
2948 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2949 {
2950 return Ok(Expression::Cast(Box::new(Cast {
2951 this: f.args.into_iter().next().unwrap(),
2952 to: DataType::Custom {
2953 name: "TIMESTAMPNTZ".to_string(),
2954 },
2955 double_colon_syntax: false,
2956 trailing_comments: vec![],
2957 format: None,
2958 default: None,
2959 inferred_type: None,
2960 })));
2961 }
2962 }
2963 Ok(Expression::Function(Box::new(f)))
2964 }
2965
2966 "TO_TIMESTAMP_LTZ" => {
2968 if f.args.len() == 1 {
2969 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2970 {
2971 return Ok(Expression::Cast(Box::new(Cast {
2972 this: f.args.into_iter().next().unwrap(),
2973 to: DataType::Custom {
2974 name: "TIMESTAMPLTZ".to_string(),
2975 },
2976 double_colon_syntax: false,
2977 trailing_comments: vec![],
2978 format: None,
2979 default: None,
2980 inferred_type: None,
2981 })));
2982 }
2983 }
2984 Ok(Expression::Function(Box::new(f)))
2985 }
2986
2987 "UNIFORM" => Ok(Expression::Function(Box::new(f))),
2989
2990 "REPLACE" if f.args.len() == 2 => {
2992 let mut args = f.args;
2993 args.push(Expression::Literal(crate::expressions::Literal::String(
2994 String::new(),
2995 )));
2996 Ok(Expression::Function(Box::new(Function::new(
2997 "REPLACE".to_string(),
2998 args,
2999 ))))
3000 }
3001
3002 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
3004 "ANY_VALUE".to_string(),
3005 f.args,
3006 )))),
3007
3008 "SAFE_DIVIDE" if f.args.len() == 2 => {
3010 let mut args = f.args;
3011 let x = args.remove(0);
3012 let y = args.remove(0);
3013 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3014 condition: Expression::Neq(Box::new(BinaryOp {
3015 left: y.clone(),
3016 right: Expression::number(0),
3017 left_comments: Vec::new(),
3018 operator_comments: Vec::new(),
3019 trailing_comments: Vec::new(),
3020 inferred_type: None,
3021 })),
3022 true_value: Expression::Div(Box::new(BinaryOp {
3023 left: x,
3024 right: y,
3025 left_comments: Vec::new(),
3026 operator_comments: Vec::new(),
3027 trailing_comments: Vec::new(),
3028 inferred_type: None,
3029 })),
3030 false_value: Some(Expression::Null(crate::expressions::Null)),
3031 original_name: Some("IFF".to_string()),
3032 inferred_type: None,
3033 })))
3034 }
3035
3036 "TIMESTAMP" if f.args.len() == 1 => {
3038 let arg = f.args.into_iter().next().unwrap();
3039 Ok(Expression::Cast(Box::new(Cast {
3040 this: arg,
3041 to: DataType::Custom {
3042 name: "TIMESTAMPTZ".to_string(),
3043 },
3044 trailing_comments: Vec::new(),
3045 double_colon_syntax: false,
3046 format: None,
3047 default: None,
3048 inferred_type: None,
3049 })))
3050 }
3051
3052 "TIMESTAMP" if f.args.len() == 2 => {
3054 let mut args = f.args;
3055 let value = args.remove(0);
3056 let tz = args.remove(0);
3057 Ok(Expression::Function(Box::new(Function::new(
3058 "CONVERT_TIMEZONE".to_string(),
3059 vec![
3060 tz,
3061 Expression::Cast(Box::new(Cast {
3062 this: value,
3063 to: DataType::Timestamp {
3064 precision: None,
3065 timezone: false,
3066 },
3067 trailing_comments: Vec::new(),
3068 double_colon_syntax: false,
3069 format: None,
3070 default: None,
3071 inferred_type: None,
3072 })),
3073 ],
3074 ))))
3075 }
3076
3077 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3079 "TIME_FROM_PARTS".to_string(),
3080 f.args,
3081 )))),
3082
3083 "DIV0" if f.args.len() == 2 => {
3085 let mut args = f.args;
3086 let x = args.remove(0);
3087 let y = args.remove(0);
3088 let x_expr = Self::maybe_paren(x.clone());
3090 let y_expr = Self::maybe_paren(y.clone());
3091 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3092 condition: Expression::And(Box::new(BinaryOp::new(
3093 Expression::Eq(Box::new(BinaryOp::new(
3094 y_expr.clone(),
3095 Expression::number(0),
3096 ))),
3097 Expression::Not(Box::new(crate::expressions::UnaryOp {
3098 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3099 this: x_expr.clone(),
3100 not: false,
3101 postfix_form: false,
3102 })),
3103 inferred_type: None,
3104 })),
3105 ))),
3106 true_value: Expression::number(0),
3107 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3108 original_name: Some("IFF".to_string()),
3109 inferred_type: None,
3110 })))
3111 }
3112
3113 "DIV0NULL" if f.args.len() == 2 => {
3115 let mut args = f.args;
3116 let x = args.remove(0);
3117 let y = args.remove(0);
3118 let x_expr = Self::maybe_paren(x.clone());
3119 let y_expr = Self::maybe_paren(y.clone());
3120 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3121 condition: Expression::Or(Box::new(BinaryOp::new(
3122 Expression::Eq(Box::new(BinaryOp::new(
3123 y_expr.clone(),
3124 Expression::number(0),
3125 ))),
3126 Expression::IsNull(Box::new(crate::expressions::IsNull {
3127 this: y_expr.clone(),
3128 not: false,
3129 postfix_form: false,
3130 })),
3131 ))),
3132 true_value: Expression::number(0),
3133 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3134 original_name: Some("IFF".to_string()),
3135 inferred_type: None,
3136 })))
3137 }
3138
3139 "ZEROIFNULL" if f.args.len() == 1 => {
3141 let x = f.args.into_iter().next().unwrap();
3142 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3143 condition: Expression::IsNull(Box::new(crate::expressions::IsNull {
3144 this: x.clone(),
3145 not: false,
3146 postfix_form: false,
3147 })),
3148 true_value: Expression::number(0),
3149 false_value: Some(x),
3150 original_name: Some("IFF".to_string()),
3151 inferred_type: None,
3152 })))
3153 }
3154
3155 "NULLIFZERO" if f.args.len() == 1 => {
3157 let x = f.args.into_iter().next().unwrap();
3158 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3159 condition: Expression::Eq(Box::new(BinaryOp::new(
3160 x.clone(),
3161 Expression::number(0),
3162 ))),
3163 true_value: Expression::Null(crate::expressions::Null),
3164 false_value: Some(x),
3165 original_name: Some("IFF".to_string()),
3166 inferred_type: None,
3167 })))
3168 }
3169
3170 "TRY_TO_TIME" => {
3172 if f.args.len() == 1 {
3173 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
3174 {
3175 return Ok(Expression::TryCast(Box::new(Cast {
3176 this: f.args.into_iter().next().unwrap(),
3177 to: crate::expressions::DataType::Time {
3178 precision: None,
3179 timezone: false,
3180 },
3181 double_colon_syntax: false,
3182 trailing_comments: Vec::new(),
3183 format: None,
3184 default: None,
3185 inferred_type: None,
3186 })));
3187 }
3188 }
3189 let mut args = f.args;
3191 if args.len() >= 2 {
3192 args[1] = Self::normalize_format_arg(args[1].clone());
3193 }
3194 Ok(Expression::Function(Box::new(Function::new(
3195 "TRY_TO_TIME".to_string(),
3196 args,
3197 ))))
3198 }
3199
3200 "TRY_TO_TIMESTAMP" => {
3203 if f.args.len() == 1 {
3204 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
3205 {
3206 if !Self::looks_like_epoch(s) {
3207 return Ok(Expression::TryCast(Box::new(Cast {
3208 this: f.args.into_iter().next().unwrap(),
3209 to: DataType::Timestamp {
3210 precision: None,
3211 timezone: false,
3212 },
3213 double_colon_syntax: false,
3214 trailing_comments: Vec::new(),
3215 format: None,
3216 default: None,
3217 inferred_type: None,
3218 })));
3219 }
3220 }
3221 }
3222 let mut args = f.args;
3224 if args.len() >= 2 {
3225 args[1] = Self::normalize_format_arg(args[1].clone());
3226 }
3227 Ok(Expression::Function(Box::new(Function::new(
3228 "TRY_TO_TIMESTAMP".to_string(),
3229 args,
3230 ))))
3231 }
3232
3233 "TRY_TO_DATE" => {
3235 if f.args.len() == 1 {
3236 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
3237 {
3238 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
3240 return Ok(Expression::TryCast(Box::new(Cast {
3241 this: f.args.into_iter().next().unwrap(),
3242 to: crate::expressions::DataType::Date,
3243 double_colon_syntax: false,
3244 trailing_comments: Vec::new(),
3245 format: None,
3246 default: None,
3247 inferred_type: None,
3248 })));
3249 }
3250 }
3251 }
3252 let mut args = f.args;
3254 if args.len() >= 2 {
3255 args[1] = Self::normalize_format_arg(args[1].clone());
3256 }
3257 Ok(Expression::Function(Box::new(Function::new(
3258 "TRY_TO_DATE".to_string(),
3259 args,
3260 ))))
3261 }
3262
3263 "TRY_TO_DOUBLE" => Ok(Expression::Function(Box::new(f))),
3265
3266 "REGEXP_REPLACE" if f.args.len() == 2 => {
3268 let mut args = f.args;
3269 args.push(Expression::Literal(crate::expressions::Literal::String(
3270 String::new(),
3271 )));
3272 Ok(Expression::Function(Box::new(Function::new(
3273 "REGEXP_REPLACE".to_string(),
3274 args,
3275 ))))
3276 }
3277
3278 "LAST_DAY" if f.args.len() == 2 => {
3280 let mut args = f.args;
3281 let date = args.remove(0);
3282 let unit = args.remove(0);
3283 let unit_str = match &unit {
3284 Expression::Column(c) => c.name.name.to_uppercase(),
3285 Expression::Identifier(i) => i.name.to_uppercase(),
3286 _ => String::new(),
3287 };
3288 if unit_str == "MONTH" {
3289 Ok(Expression::Function(Box::new(Function::new(
3290 "LAST_DAY".to_string(),
3291 vec![date],
3292 ))))
3293 } else {
3294 Ok(Expression::Function(Box::new(Function::new(
3295 "LAST_DAY".to_string(),
3296 vec![date, unit],
3297 ))))
3298 }
3299 }
3300
3301 "EXTRACT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
3303 "DATE_PART".to_string(),
3304 f.args,
3305 )))),
3306
3307 "ENDS_WITH" | "ENDSWITH" if f.args.len() == 2 => {
3309 let mut args = f.args;
3310 let this = args.remove(0);
3311 let expr = args.remove(0);
3312 Ok(Expression::EndsWith(Box::new(
3313 crate::expressions::BinaryFunc {
3314 original_name: None,
3315 this,
3316 expression: expr,
3317 inferred_type: None,
3318 },
3319 )))
3320 }
3321
3322 _ => Ok(Expression::Function(Box::new(f))),
3324 }
3325 }
3326
3327 fn looks_like_datetime(s: &str) -> bool {
3329 s.contains('-') || s.contains(':') || s.contains(' ') || s.contains('/')
3332 }
3333
3334 fn looks_like_epoch(s: &str) -> bool {
3336 !s.is_empty() && s.chars().all(|c| c.is_ascii_digit() || c == '.')
3337 }
3338
3339 fn maybe_paren(expr: Expression) -> Expression {
3341 match &expr {
3342 Expression::Sub(_) | Expression::Add(_) | Expression::Mul(_) | Expression::Div(_) => {
3343 Expression::Paren(Box::new(crate::expressions::Paren {
3344 this: expr,
3345 trailing_comments: Vec::new(),
3346 }))
3347 }
3348 _ => expr,
3349 }
3350 }
3351
3352 fn normalize_snowflake_format(format: &str) -> String {
3356 let mut result = String::new();
3357 let chars: Vec<char> = format.chars().collect();
3358 let mut i = 0;
3359 while i < chars.len() {
3360 if chars[i] == '"' {
3362 i += 1;
3363 while i < chars.len() && chars[i] != '"' {
3364 result.push(chars[i]);
3365 i += 1;
3366 }
3367 if i < chars.len() {
3368 i += 1; }
3370 continue;
3371 }
3372
3373 let remaining = &format[i..];
3374 let remaining_upper = remaining.to_uppercase();
3375
3376 if remaining_upper.starts_with("YYYY") {
3378 result.push_str("yyyy");
3379 i += 4;
3380 } else if remaining_upper.starts_with("YY") {
3381 result.push_str("yy");
3382 i += 2;
3383 } else if remaining_upper.starts_with("MMMM") {
3384 result.push_str("mmmm");
3385 i += 4;
3386 } else if remaining_upper.starts_with("MON") {
3387 result.push_str("mon");
3388 i += 3;
3389 } else if remaining_upper.starts_with("MM") {
3390 result.push_str("mm");
3391 i += 2;
3392 } else if remaining_upper.starts_with("DD") {
3393 result.push_str("DD");
3394 i += 2;
3395 } else if remaining_upper.starts_with("DY") {
3396 result.push_str("dy");
3397 i += 2;
3398 } else if remaining_upper.starts_with("HH24") {
3399 result.push_str("hh24");
3400 i += 4;
3401 } else if remaining_upper.starts_with("HH12") {
3402 result.push_str("hh12");
3403 i += 4;
3404 } else if remaining_upper.starts_with("HH") {
3405 result.push_str("hh");
3406 i += 2;
3407 } else if remaining_upper.starts_with("MISS") {
3408 result.push_str("miss");
3410 i += 4;
3411 } else if remaining_upper.starts_with("MI") {
3412 result.push_str("mi");
3413 i += 2;
3414 } else if remaining_upper.starts_with("SS") {
3415 result.push_str("ss");
3416 i += 2;
3417 } else if remaining_upper.starts_with("FF") {
3418 let ff_len = 2;
3420 let digit = if i + ff_len < chars.len() && chars[i + ff_len].is_ascii_digit() {
3421 let d = chars[i + ff_len];
3422 Some(d)
3423 } else {
3424 None
3425 };
3426 if let Some(d) = digit {
3427 result.push_str("ff");
3428 result.push(d);
3429 i += 3;
3430 } else {
3431 result.push_str("ff9");
3433 i += 2;
3434 }
3435 } else if remaining_upper.starts_with("AM") || remaining_upper.starts_with("PM") {
3436 result.push_str("pm");
3437 i += 2;
3438 } else if remaining_upper.starts_with("TZH") {
3439 result.push_str("tzh");
3440 i += 3;
3441 } else if remaining_upper.starts_with("TZM") {
3442 result.push_str("tzm");
3443 i += 3;
3444 } else {
3445 result.push(chars[i]);
3447 i += 1;
3448 }
3449 }
3450 result
3451 }
3452
3453 fn normalize_format_arg(expr: Expression) -> Expression {
3455 if let Expression::Literal(crate::expressions::Literal::String(s)) = &expr {
3456 let normalized = Self::normalize_snowflake_format(s);
3457 Expression::Literal(crate::expressions::Literal::String(normalized))
3458 } else {
3459 expr
3460 }
3461 }
3462
3463 fn transform_typed_lambda(&self, lambda: crate::expressions::LambdaExpr) -> Expression {
3466 use crate::expressions::{DataType, LambdaExpr};
3467 use std::collections::HashMap;
3468
3469 let mut param_types: HashMap<String, DataType> = HashMap::new();
3471 for (i, param) in lambda.parameters.iter().enumerate() {
3472 if let Some(Some(dt)) = lambda.parameter_types.get(i) {
3473 param_types.insert(param.name.to_uppercase(), dt.clone());
3474 }
3475 }
3476
3477 if param_types.is_empty() {
3479 return Expression::Lambda(Box::new(lambda));
3480 }
3481
3482 let transformed_body = self.replace_lambda_params_with_cast(lambda.body, ¶m_types);
3484
3485 Expression::Lambda(Box::new(LambdaExpr {
3487 parameters: lambda.parameters,
3488 body: transformed_body,
3489 colon: lambda.colon,
3490 parameter_types: Vec::new(), }))
3492 }
3493
3494 fn replace_lambda_params_with_cast(
3496 &self,
3497 expr: Expression,
3498 param_types: &std::collections::HashMap<String, crate::expressions::DataType>,
3499 ) -> Expression {
3500 use crate::expressions::{BinaryOp, Cast, Paren};
3501
3502 match expr {
3503 Expression::Column(col) if col.table.is_none() => {
3505 let name_upper = col.name.name.to_uppercase();
3506 if let Some(dt) = param_types.get(&name_upper) {
3507 Expression::Cast(Box::new(Cast {
3509 this: Expression::Column(col),
3510 to: dt.clone(),
3511 double_colon_syntax: false,
3512 trailing_comments: Vec::new(),
3513 format: None,
3514 default: None,
3515 inferred_type: None,
3516 }))
3517 } else {
3518 Expression::Column(col)
3519 }
3520 }
3521
3522 Expression::Identifier(id) => {
3524 let name_upper = id.name.to_uppercase();
3525 if let Some(dt) = param_types.get(&name_upper) {
3526 Expression::Cast(Box::new(Cast {
3528 this: Expression::Identifier(id),
3529 to: dt.clone(),
3530 double_colon_syntax: false,
3531 trailing_comments: Vec::new(),
3532 format: None,
3533 default: None,
3534 inferred_type: None,
3535 }))
3536 } else {
3537 Expression::Identifier(id)
3538 }
3539 }
3540
3541 Expression::Add(op) => Expression::Add(Box::new(BinaryOp::new(
3543 self.replace_lambda_params_with_cast(op.left, param_types),
3544 self.replace_lambda_params_with_cast(op.right, param_types),
3545 ))),
3546 Expression::Sub(op) => Expression::Sub(Box::new(BinaryOp::new(
3547 self.replace_lambda_params_with_cast(op.left, param_types),
3548 self.replace_lambda_params_with_cast(op.right, param_types),
3549 ))),
3550 Expression::Mul(op) => Expression::Mul(Box::new(BinaryOp::new(
3551 self.replace_lambda_params_with_cast(op.left, param_types),
3552 self.replace_lambda_params_with_cast(op.right, param_types),
3553 ))),
3554 Expression::Div(op) => Expression::Div(Box::new(BinaryOp::new(
3555 self.replace_lambda_params_with_cast(op.left, param_types),
3556 self.replace_lambda_params_with_cast(op.right, param_types),
3557 ))),
3558 Expression::Mod(op) => Expression::Mod(Box::new(BinaryOp::new(
3559 self.replace_lambda_params_with_cast(op.left, param_types),
3560 self.replace_lambda_params_with_cast(op.right, param_types),
3561 ))),
3562
3563 Expression::Paren(p) => Expression::Paren(Box::new(Paren {
3565 this: self.replace_lambda_params_with_cast(p.this, param_types),
3566 trailing_comments: p.trailing_comments,
3567 })),
3568
3569 Expression::Function(mut f) => {
3571 f.args = f
3572 .args
3573 .into_iter()
3574 .map(|arg| self.replace_lambda_params_with_cast(arg, param_types))
3575 .collect();
3576 Expression::Function(f)
3577 }
3578
3579 Expression::Eq(op) => Expression::Eq(Box::new(BinaryOp::new(
3581 self.replace_lambda_params_with_cast(op.left, param_types),
3582 self.replace_lambda_params_with_cast(op.right, param_types),
3583 ))),
3584 Expression::Neq(op) => Expression::Neq(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::Lt(op) => Expression::Lt(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::Lte(op) => Expression::Lte(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::Gt(op) => Expression::Gt(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::Gte(op) => Expression::Gte(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::And(op) => Expression::And(Box::new(BinaryOp::new(
3607 self.replace_lambda_params_with_cast(op.left, param_types),
3608 self.replace_lambda_params_with_cast(op.right, param_types),
3609 ))),
3610 Expression::Or(op) => Expression::Or(Box::new(BinaryOp::new(
3611 self.replace_lambda_params_with_cast(op.left, param_types),
3612 self.replace_lambda_params_with_cast(op.right, param_types),
3613 ))),
3614
3615 other => other,
3617 }
3618 }
3619
3620 fn transform_aggregate_function(
3621 &self,
3622 f: Box<crate::expressions::AggregateFunction>,
3623 ) -> Result<Expression> {
3624 let name_upper = f.name.to_uppercase();
3625 match name_upper.as_str() {
3626 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3628 Function::new("LISTAGG".to_string(), f.args),
3629 ))),
3630
3631 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3633 Function::new("LISTAGG".to_string(), f.args),
3634 ))),
3635
3636 "APPROX_DISTINCT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3638 Function::new("APPROX_COUNT_DISTINCT".to_string(), f.args),
3639 ))),
3640
3641 "BIT_AND" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3643 "BITAND_AGG".to_string(),
3644 f.args,
3645 )))),
3646
3647 "BIT_OR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3649 "BITOR_AGG".to_string(),
3650 f.args,
3651 )))),
3652
3653 "BIT_XOR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3655 "BITXOR_AGG".to_string(),
3656 f.args,
3657 )))),
3658
3659 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" if !f.args.is_empty() => {
3661 let arg = f.args.into_iter().next().unwrap();
3662 Ok(Expression::LogicalAnd(Box::new(AggFunc {
3663 this: arg,
3664 distinct: f.distinct,
3665 filter: f.filter,
3666 order_by: Vec::new(),
3667 name: Some("BOOLAND_AGG".to_string()),
3668 ignore_nulls: None,
3669 having_max: None,
3670 limit: None,
3671 inferred_type: None,
3672 })))
3673 }
3674
3675 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if !f.args.is_empty() => {
3677 let arg = f.args.into_iter().next().unwrap();
3678 Ok(Expression::LogicalOr(Box::new(AggFunc {
3679 this: arg,
3680 distinct: f.distinct,
3681 filter: f.filter,
3682 order_by: Vec::new(),
3683 name: Some("BOOLOR_AGG".to_string()),
3684 ignore_nulls: None,
3685 having_max: None,
3686 limit: None,
3687 inferred_type: None,
3688 })))
3689 }
3690
3691 "APPROX_TOP_K" if f.args.len() == 1 => {
3693 let mut args = f.args;
3694 args.push(Expression::number(1));
3695 Ok(Expression::AggregateFunction(Box::new(
3696 crate::expressions::AggregateFunction {
3697 name: "APPROX_TOP_K".to_string(),
3698 args,
3699 distinct: f.distinct,
3700 filter: f.filter,
3701 order_by: Vec::new(),
3702 limit: None,
3703 ignore_nulls: None,
3704 inferred_type: None,
3705 },
3706 )))
3707 }
3708
3709 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
3711 let arg = f.args.into_iter().next().unwrap();
3712 Ok(Expression::Skewness(Box::new(AggFunc {
3713 this: arg,
3714 distinct: f.distinct,
3715 filter: f.filter,
3716 order_by: Vec::new(),
3717 name: Some("SKEW".to_string()),
3718 ignore_nulls: None,
3719 having_max: None,
3720 limit: None,
3721 inferred_type: None,
3722 })))
3723 }
3724
3725 _ => Ok(Expression::AggregateFunction(f)),
3727 }
3728 }
3729}
3730
3731fn strftime_to_snowflake_format(fmt: &str) -> String {
3733 let mut result = String::new();
3734 let chars: Vec<char> = fmt.chars().collect();
3735 let mut i = 0;
3736 while i < chars.len() {
3737 if chars[i] == '%' && i + 1 < chars.len() {
3738 match chars[i + 1] {
3739 'Y' => {
3740 result.push_str("yyyy");
3741 i += 2;
3742 }
3743 'y' => {
3744 result.push_str("yy");
3745 i += 2;
3746 }
3747 'm' => {
3748 result.push_str("mm");
3749 i += 2;
3750 }
3751 'd' => {
3752 result.push_str("DD");
3753 i += 2;
3754 }
3755 'H' => {
3756 result.push_str("hh24");
3757 i += 2;
3758 }
3759 'M' => {
3760 result.push_str("mmmm");
3761 i += 2;
3762 } 'i' => {
3764 result.push_str("mi");
3765 i += 2;
3766 }
3767 'S' | 's' => {
3768 result.push_str("ss");
3769 i += 2;
3770 }
3771 'f' => {
3772 result.push_str("ff");
3773 i += 2;
3774 }
3775 'w' => {
3776 result.push_str("dy");
3777 i += 2;
3778 } 'a' => {
3780 result.push_str("DY");
3781 i += 2;
3782 } 'b' => {
3784 result.push_str("mon");
3785 i += 2;
3786 } 'T' => {
3788 result.push_str("hh24:mi:ss");
3789 i += 2;
3790 } _ => {
3792 result.push(chars[i]);
3793 result.push(chars[i + 1]);
3794 i += 2;
3795 }
3796 }
3797 } else {
3798 result.push(chars[i]);
3799 i += 1;
3800 }
3801 }
3802 result
3803}
3804
3805#[cfg(test)]
3806mod tests {
3807 use super::*;
3808 use crate::dialects::Dialect;
3809
3810 fn transpile_to_snowflake(sql: &str) -> String {
3811 let dialect = Dialect::get(DialectType::Generic);
3812 let result = dialect
3813 .transpile_to(sql, DialectType::Snowflake)
3814 .expect("Transpile failed");
3815 result[0].clone()
3816 }
3817
3818 #[test]
3819 fn test_ifnull_to_coalesce() {
3820 let result = transpile_to_snowflake("SELECT IFNULL(a, b)");
3821 assert!(
3822 result.contains("COALESCE"),
3823 "Expected COALESCE, got: {}",
3824 result
3825 );
3826 }
3827
3828 #[test]
3829 fn test_basic_select() {
3830 let result = transpile_to_snowflake("SELECT a, b FROM users WHERE id = 1");
3831 assert!(result.contains("SELECT"));
3832 assert!(result.contains("FROM users"));
3833 }
3834
3835 #[test]
3836 fn test_group_concat_to_listagg() {
3837 let result = transpile_to_snowflake("SELECT GROUP_CONCAT(name)");
3838 assert!(
3839 result.contains("LISTAGG"),
3840 "Expected LISTAGG, got: {}",
3841 result
3842 );
3843 }
3844
3845 #[test]
3846 fn test_string_agg_to_listagg() {
3847 let result = transpile_to_snowflake("SELECT STRING_AGG(name)");
3848 assert!(
3849 result.contains("LISTAGG"),
3850 "Expected LISTAGG, got: {}",
3851 result
3852 );
3853 }
3854
3855 #[test]
3856 fn test_array_to_array_construct() {
3857 let result = transpile_to_snowflake("SELECT ARRAY(1, 2, 3)");
3858 assert!(
3859 result.contains("ARRAY_CONSTRUCT"),
3860 "Expected ARRAY_CONSTRUCT, got: {}",
3861 result
3862 );
3863 }
3864
3865 #[test]
3866 fn test_double_quote_identifiers() {
3867 let dialect = SnowflakeDialect;
3869 let config = dialect.generator_config();
3870 assert_eq!(config.identifier_quote, '"');
3871 }
3872}