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(f))),
2712
2713 "GET_PATH" if f.args.len() >= 2 => {
2717 let mut args = f.args;
2718 if let Expression::Literal(crate::expressions::Literal::String(path)) = &args[1] {
2720 let transformed = Self::transform_json_path(path);
2721 args[1] = Expression::Literal(crate::expressions::Literal::String(transformed));
2722 }
2723 Ok(Expression::Function(Box::new(Function::new(
2724 "GET_PATH".to_string(),
2725 args,
2726 ))))
2727 }
2728 "GET_PATH" => Ok(Expression::Function(Box::new(f))),
2729
2730 "FLATTEN" => Ok(Expression::Function(Box::new(f))),
2732
2733 "DATE_TRUNC" if f.args.len() >= 1 => {
2736 let mut args = f.args;
2737 let unit_name = match &args[0] {
2739 Expression::Identifier(id) => Some(id.name.as_str()),
2740 Expression::Column(col) if col.table.is_none() => Some(col.name.name.as_str()),
2741 _ => None,
2742 };
2743 if let Some(name) = unit_name {
2744 let canonical = Self::map_date_part(name).unwrap_or(name);
2745 args[0] = Expression::Literal(crate::expressions::Literal::String(
2746 canonical.to_uppercase(),
2747 ));
2748 }
2749 Ok(Expression::Function(Box::new(Function::new(
2750 "DATE_TRUNC".to_string(),
2751 args,
2752 ))))
2753 }
2754
2755 "DATE_PART" if f.args.len() >= 1 => {
2761 let mut args = f.args;
2762 let from_typed_literal = args.len() >= 2
2763 && matches!(
2764 &args[1],
2765 Expression::Literal(crate::expressions::Literal::Timestamp(_))
2766 | Expression::Literal(crate::expressions::Literal::Date(_))
2767 | Expression::Literal(crate::expressions::Literal::Time(_))
2768 | Expression::Literal(crate::expressions::Literal::Datetime(_))
2769 );
2770 if from_typed_literal {
2771 args[0] = self.transform_date_part_arg(args[0].clone());
2772 } else {
2773 args[0] = self.transform_date_part_arg_identifiers_only(args[0].clone());
2776 }
2777 Ok(Expression::Function(Box::new(Function::new(
2778 "DATE_PART".to_string(),
2779 args,
2780 ))))
2781 }
2782
2783 "OBJECT_CONSTRUCT" => Ok(Expression::Function(Box::new(f))),
2785
2786 "OBJECT_CONSTRUCT_KEEP_NULL" => Ok(Expression::Function(Box::new(f))),
2788
2789 "DESC" => Ok(Expression::Function(Box::new(Function::new(
2791 "DESCRIBE".to_string(),
2792 f.args,
2793 )))),
2794
2795 "RLIKE" if f.args.len() >= 2 => Ok(Expression::Function(Box::new(Function::new(
2797 "REGEXP_LIKE".to_string(),
2798 f.args,
2799 )))),
2800
2801 "TRANSFORM" => {
2806 let transformed_args: Vec<Expression> = f
2807 .args
2808 .into_iter()
2809 .map(|arg| {
2810 if let Expression::Lambda(lambda) = arg {
2811 self.transform_typed_lambda(*lambda)
2812 } else {
2813 arg
2814 }
2815 })
2816 .collect();
2817 Ok(Expression::Function(Box::new(Function::new(
2818 "TRANSFORM".to_string(),
2819 transformed_args,
2820 ))))
2821 }
2822
2823 "SEARCH" if f.args.len() >= 2 => {
2825 let mut args = f.args.into_iter();
2826 let this = Box::new(args.next().unwrap());
2827 let expression = Box::new(args.next().unwrap());
2828
2829 let mut analyzer: Option<Box<Expression>> = None;
2830 let mut search_mode: Option<Box<Expression>> = None;
2831
2832 for arg in args {
2834 if let Expression::NamedArgument(na) = &arg {
2835 let name_upper = na.name.name.to_uppercase();
2836 match name_upper.as_str() {
2837 "ANALYZER" => analyzer = Some(Box::new(arg)),
2838 "SEARCH_MODE" => search_mode = Some(Box::new(arg)),
2839 _ => {}
2840 }
2841 }
2842 }
2843
2844 Ok(Expression::Search(Box::new(crate::expressions::Search {
2845 this,
2846 expression,
2847 json_scope: None,
2848 analyzer,
2849 analyzer_options: None,
2850 search_mode,
2851 })))
2852 }
2853
2854 "CONVERT" if f.args.len() == 2 => {
2857 let value = f.args.get(0).cloned().unwrap();
2858 let type_arg = f.args.get(1).cloned().unwrap();
2859
2860 if let Expression::Column(col) = &type_arg {
2862 let type_name = col.name.name.to_uppercase();
2863 let data_type = match type_name.as_str() {
2864 "SQL_DOUBLE" => Some(DataType::Double {
2865 precision: None,
2866 scale: None,
2867 }),
2868 "SQL_VARCHAR" => Some(DataType::VarChar {
2869 length: None,
2870 parenthesized_length: false,
2871 }),
2872 "SQL_INTEGER" | "SQL_INT" => Some(DataType::Int {
2873 length: None,
2874 integer_spelling: false,
2875 }),
2876 "SQL_BIGINT" => Some(DataType::BigInt { length: None }),
2877 "SQL_SMALLINT" => Some(DataType::SmallInt { length: None }),
2878 "SQL_FLOAT" => Some(DataType::Float {
2879 precision: None,
2880 scale: None,
2881 real_spelling: false,
2882 }),
2883 "SQL_REAL" => Some(DataType::Float {
2884 precision: None,
2885 scale: None,
2886 real_spelling: true,
2887 }),
2888 "SQL_DECIMAL" => Some(DataType::Decimal {
2889 precision: None,
2890 scale: None,
2891 }),
2892 "SQL_DATE" => Some(DataType::Date),
2893 "SQL_TIME" => Some(DataType::Time {
2894 precision: None,
2895 timezone: false,
2896 }),
2897 "SQL_TIMESTAMP" => Some(DataType::Timestamp {
2898 precision: None,
2899 timezone: false,
2900 }),
2901 _ => None,
2902 };
2903
2904 if let Some(dt) = data_type {
2905 return Ok(Expression::Cast(Box::new(Cast {
2906 this: value,
2907 to: dt,
2908 double_colon_syntax: false,
2909 trailing_comments: vec![],
2910 format: None,
2911 default: None,
2912 inferred_type: None,
2913 })));
2914 }
2915 }
2916 Ok(Expression::Function(Box::new(f)))
2918 }
2919
2920 "TO_TIMESTAMP_TZ" => {
2923 if f.args.len() == 1 {
2924 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2925 {
2926 return Ok(Expression::Cast(Box::new(Cast {
2927 this: f.args.into_iter().next().unwrap(),
2928 to: DataType::Custom {
2929 name: "TIMESTAMPTZ".to_string(),
2930 },
2931 double_colon_syntax: false,
2932 trailing_comments: vec![],
2933 format: None,
2934 default: None,
2935 inferred_type: None,
2936 })));
2937 }
2938 }
2939 Ok(Expression::Function(Box::new(f)))
2940 }
2941
2942 "TO_TIMESTAMP_NTZ" => {
2944 if f.args.len() == 1 {
2945 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2946 {
2947 return Ok(Expression::Cast(Box::new(Cast {
2948 this: f.args.into_iter().next().unwrap(),
2949 to: DataType::Custom {
2950 name: "TIMESTAMPNTZ".to_string(),
2951 },
2952 double_colon_syntax: false,
2953 trailing_comments: vec![],
2954 format: None,
2955 default: None,
2956 inferred_type: None,
2957 })));
2958 }
2959 }
2960 Ok(Expression::Function(Box::new(f)))
2961 }
2962
2963 "TO_TIMESTAMP_LTZ" => {
2965 if f.args.len() == 1 {
2966 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
2967 {
2968 return Ok(Expression::Cast(Box::new(Cast {
2969 this: f.args.into_iter().next().unwrap(),
2970 to: DataType::Custom {
2971 name: "TIMESTAMPLTZ".to_string(),
2972 },
2973 double_colon_syntax: false,
2974 trailing_comments: vec![],
2975 format: None,
2976 default: None,
2977 inferred_type: None,
2978 })));
2979 }
2980 }
2981 Ok(Expression::Function(Box::new(f)))
2982 }
2983
2984 "UNIFORM" => Ok(Expression::Function(Box::new(f))),
2986
2987 "REPLACE" if f.args.len() == 2 => {
2989 let mut args = f.args;
2990 args.push(Expression::Literal(crate::expressions::Literal::String(
2991 String::new(),
2992 )));
2993 Ok(Expression::Function(Box::new(Function::new(
2994 "REPLACE".to_string(),
2995 args,
2996 ))))
2997 }
2998
2999 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
3001 "ANY_VALUE".to_string(),
3002 f.args,
3003 )))),
3004
3005 "SAFE_DIVIDE" if f.args.len() == 2 => {
3007 let mut args = f.args;
3008 let x = args.remove(0);
3009 let y = args.remove(0);
3010 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3011 condition: Expression::Neq(Box::new(BinaryOp {
3012 left: y.clone(),
3013 right: Expression::number(0),
3014 left_comments: Vec::new(),
3015 operator_comments: Vec::new(),
3016 trailing_comments: Vec::new(),
3017 inferred_type: None,
3018 })),
3019 true_value: Expression::Div(Box::new(BinaryOp {
3020 left: x,
3021 right: y,
3022 left_comments: Vec::new(),
3023 operator_comments: Vec::new(),
3024 trailing_comments: Vec::new(),
3025 inferred_type: None,
3026 })),
3027 false_value: Some(Expression::Null(crate::expressions::Null)),
3028 original_name: Some("IFF".to_string()),
3029 inferred_type: None,
3030 })))
3031 }
3032
3033 "TIMESTAMP" if f.args.len() == 1 => {
3035 let arg = f.args.into_iter().next().unwrap();
3036 Ok(Expression::Cast(Box::new(Cast {
3037 this: arg,
3038 to: DataType::Custom {
3039 name: "TIMESTAMPTZ".to_string(),
3040 },
3041 trailing_comments: Vec::new(),
3042 double_colon_syntax: false,
3043 format: None,
3044 default: None,
3045 inferred_type: None,
3046 })))
3047 }
3048
3049 "TIMESTAMP" if f.args.len() == 2 => {
3051 let mut args = f.args;
3052 let value = args.remove(0);
3053 let tz = args.remove(0);
3054 Ok(Expression::Function(Box::new(Function::new(
3055 "CONVERT_TIMEZONE".to_string(),
3056 vec![
3057 tz,
3058 Expression::Cast(Box::new(Cast {
3059 this: value,
3060 to: DataType::Timestamp {
3061 precision: None,
3062 timezone: false,
3063 },
3064 trailing_comments: Vec::new(),
3065 double_colon_syntax: false,
3066 format: None,
3067 default: None,
3068 inferred_type: None,
3069 })),
3070 ],
3071 ))))
3072 }
3073
3074 "TIME" if f.args.len() == 3 => Ok(Expression::Function(Box::new(Function::new(
3076 "TIME_FROM_PARTS".to_string(),
3077 f.args,
3078 )))),
3079
3080 "DIV0" if f.args.len() == 2 => {
3082 let mut args = f.args;
3083 let x = args.remove(0);
3084 let y = args.remove(0);
3085 let x_expr = Self::maybe_paren(x.clone());
3087 let y_expr = Self::maybe_paren(y.clone());
3088 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3089 condition: Expression::And(Box::new(BinaryOp::new(
3090 Expression::Eq(Box::new(BinaryOp::new(
3091 y_expr.clone(),
3092 Expression::number(0),
3093 ))),
3094 Expression::Not(Box::new(crate::expressions::UnaryOp {
3095 this: Expression::IsNull(Box::new(crate::expressions::IsNull {
3096 this: x_expr.clone(),
3097 not: false,
3098 postfix_form: false,
3099 })),
3100 inferred_type: None,
3101 })),
3102 ))),
3103 true_value: Expression::number(0),
3104 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3105 original_name: Some("IFF".to_string()),
3106 inferred_type: None,
3107 })))
3108 }
3109
3110 "DIV0NULL" if f.args.len() == 2 => {
3112 let mut args = f.args;
3113 let x = args.remove(0);
3114 let y = args.remove(0);
3115 let x_expr = Self::maybe_paren(x.clone());
3116 let y_expr = Self::maybe_paren(y.clone());
3117 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3118 condition: Expression::Or(Box::new(BinaryOp::new(
3119 Expression::Eq(Box::new(BinaryOp::new(
3120 y_expr.clone(),
3121 Expression::number(0),
3122 ))),
3123 Expression::IsNull(Box::new(crate::expressions::IsNull {
3124 this: y_expr.clone(),
3125 not: false,
3126 postfix_form: false,
3127 })),
3128 ))),
3129 true_value: Expression::number(0),
3130 false_value: Some(Expression::Div(Box::new(BinaryOp::new(x_expr, y_expr)))),
3131 original_name: Some("IFF".to_string()),
3132 inferred_type: None,
3133 })))
3134 }
3135
3136 "ZEROIFNULL" if f.args.len() == 1 => {
3138 let x = f.args.into_iter().next().unwrap();
3139 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3140 condition: Expression::IsNull(Box::new(crate::expressions::IsNull {
3141 this: x.clone(),
3142 not: false,
3143 postfix_form: false,
3144 })),
3145 true_value: Expression::number(0),
3146 false_value: Some(x),
3147 original_name: Some("IFF".to_string()),
3148 inferred_type: None,
3149 })))
3150 }
3151
3152 "NULLIFZERO" if f.args.len() == 1 => {
3154 let x = f.args.into_iter().next().unwrap();
3155 Ok(Expression::IfFunc(Box::new(crate::expressions::IfFunc {
3156 condition: Expression::Eq(Box::new(BinaryOp::new(
3157 x.clone(),
3158 Expression::number(0),
3159 ))),
3160 true_value: Expression::Null(crate::expressions::Null),
3161 false_value: Some(x),
3162 original_name: Some("IFF".to_string()),
3163 inferred_type: None,
3164 })))
3165 }
3166
3167 "TRY_TO_TIME" => {
3169 if f.args.len() == 1 {
3170 if let Expression::Literal(crate::expressions::Literal::String(_)) = &f.args[0]
3171 {
3172 return Ok(Expression::TryCast(Box::new(Cast {
3173 this: f.args.into_iter().next().unwrap(),
3174 to: crate::expressions::DataType::Time {
3175 precision: None,
3176 timezone: false,
3177 },
3178 double_colon_syntax: false,
3179 trailing_comments: Vec::new(),
3180 format: None,
3181 default: None,
3182 inferred_type: None,
3183 })));
3184 }
3185 }
3186 let mut args = f.args;
3188 if args.len() >= 2 {
3189 args[1] = Self::normalize_format_arg(args[1].clone());
3190 }
3191 Ok(Expression::Function(Box::new(Function::new(
3192 "TRY_TO_TIME".to_string(),
3193 args,
3194 ))))
3195 }
3196
3197 "TRY_TO_TIMESTAMP" => {
3200 if f.args.len() == 1 {
3201 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
3202 {
3203 if !Self::looks_like_epoch(s) {
3204 return Ok(Expression::TryCast(Box::new(Cast {
3205 this: f.args.into_iter().next().unwrap(),
3206 to: DataType::Timestamp {
3207 precision: None,
3208 timezone: false,
3209 },
3210 double_colon_syntax: false,
3211 trailing_comments: Vec::new(),
3212 format: None,
3213 default: None,
3214 inferred_type: None,
3215 })));
3216 }
3217 }
3218 }
3219 let mut args = f.args;
3221 if args.len() >= 2 {
3222 args[1] = Self::normalize_format_arg(args[1].clone());
3223 }
3224 Ok(Expression::Function(Box::new(Function::new(
3225 "TRY_TO_TIMESTAMP".to_string(),
3226 args,
3227 ))))
3228 }
3229
3230 "TRY_TO_DATE" => {
3232 if f.args.len() == 1 {
3233 if let Expression::Literal(crate::expressions::Literal::String(s)) = &f.args[0]
3234 {
3235 if s.contains('-') && s.len() >= 8 && s.len() <= 12 {
3237 return Ok(Expression::TryCast(Box::new(Cast {
3238 this: f.args.into_iter().next().unwrap(),
3239 to: crate::expressions::DataType::Date,
3240 double_colon_syntax: false,
3241 trailing_comments: Vec::new(),
3242 format: None,
3243 default: None,
3244 inferred_type: None,
3245 })));
3246 }
3247 }
3248 }
3249 let mut args = f.args;
3251 if args.len() >= 2 {
3252 args[1] = Self::normalize_format_arg(args[1].clone());
3253 }
3254 Ok(Expression::Function(Box::new(Function::new(
3255 "TRY_TO_DATE".to_string(),
3256 args,
3257 ))))
3258 }
3259
3260 "TRY_TO_DOUBLE" => Ok(Expression::Function(Box::new(f))),
3262
3263 "REGEXP_REPLACE" if f.args.len() == 2 => {
3265 let mut args = f.args;
3266 args.push(Expression::Literal(crate::expressions::Literal::String(
3267 String::new(),
3268 )));
3269 Ok(Expression::Function(Box::new(Function::new(
3270 "REGEXP_REPLACE".to_string(),
3271 args,
3272 ))))
3273 }
3274
3275 "LAST_DAY" if f.args.len() == 2 => {
3277 let mut args = f.args;
3278 let date = args.remove(0);
3279 let unit = args.remove(0);
3280 let unit_str = match &unit {
3281 Expression::Column(c) => c.name.name.to_uppercase(),
3282 Expression::Identifier(i) => i.name.to_uppercase(),
3283 _ => String::new(),
3284 };
3285 if unit_str == "MONTH" {
3286 Ok(Expression::Function(Box::new(Function::new(
3287 "LAST_DAY".to_string(),
3288 vec![date],
3289 ))))
3290 } else {
3291 Ok(Expression::Function(Box::new(Function::new(
3292 "LAST_DAY".to_string(),
3293 vec![date, unit],
3294 ))))
3295 }
3296 }
3297
3298 "EXTRACT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
3300 "DATE_PART".to_string(),
3301 f.args,
3302 )))),
3303
3304 "ENDS_WITH" | "ENDSWITH" if f.args.len() == 2 => {
3306 let mut args = f.args;
3307 let this = args.remove(0);
3308 let expr = args.remove(0);
3309 Ok(Expression::EndsWith(Box::new(
3310 crate::expressions::BinaryFunc {
3311 original_name: None,
3312 this,
3313 expression: expr,
3314 inferred_type: None,
3315 },
3316 )))
3317 }
3318
3319 _ => Ok(Expression::Function(Box::new(f))),
3321 }
3322 }
3323
3324 fn looks_like_datetime(s: &str) -> bool {
3326 s.contains('-') || s.contains(':') || s.contains(' ') || s.contains('/')
3329 }
3330
3331 fn looks_like_epoch(s: &str) -> bool {
3333 !s.is_empty() && s.chars().all(|c| c.is_ascii_digit() || c == '.')
3334 }
3335
3336 fn maybe_paren(expr: Expression) -> Expression {
3338 match &expr {
3339 Expression::Sub(_) | Expression::Add(_) | Expression::Mul(_) | Expression::Div(_) => {
3340 Expression::Paren(Box::new(crate::expressions::Paren {
3341 this: expr,
3342 trailing_comments: Vec::new(),
3343 }))
3344 }
3345 _ => expr,
3346 }
3347 }
3348
3349 fn normalize_snowflake_format(format: &str) -> String {
3353 let mut result = String::new();
3354 let chars: Vec<char> = format.chars().collect();
3355 let mut i = 0;
3356 while i < chars.len() {
3357 if chars[i] == '"' {
3359 i += 1;
3360 while i < chars.len() && chars[i] != '"' {
3361 result.push(chars[i]);
3362 i += 1;
3363 }
3364 if i < chars.len() {
3365 i += 1; }
3367 continue;
3368 }
3369
3370 let remaining = &format[i..];
3371 let remaining_upper = remaining.to_uppercase();
3372
3373 if remaining_upper.starts_with("YYYY") {
3375 result.push_str("yyyy");
3376 i += 4;
3377 } else if remaining_upper.starts_with("YY") {
3378 result.push_str("yy");
3379 i += 2;
3380 } else if remaining_upper.starts_with("MMMM") {
3381 result.push_str("mmmm");
3382 i += 4;
3383 } else if remaining_upper.starts_with("MON") {
3384 result.push_str("mon");
3385 i += 3;
3386 } else if remaining_upper.starts_with("MM") {
3387 result.push_str("mm");
3388 i += 2;
3389 } else if remaining_upper.starts_with("DD") {
3390 result.push_str("DD");
3391 i += 2;
3392 } else if remaining_upper.starts_with("DY") {
3393 result.push_str("dy");
3394 i += 2;
3395 } else if remaining_upper.starts_with("HH24") {
3396 result.push_str("hh24");
3397 i += 4;
3398 } else if remaining_upper.starts_with("HH12") {
3399 result.push_str("hh12");
3400 i += 4;
3401 } else if remaining_upper.starts_with("HH") {
3402 result.push_str("hh");
3403 i += 2;
3404 } else if remaining_upper.starts_with("MISS") {
3405 result.push_str("miss");
3407 i += 4;
3408 } else if remaining_upper.starts_with("MI") {
3409 result.push_str("mi");
3410 i += 2;
3411 } else if remaining_upper.starts_with("SS") {
3412 result.push_str("ss");
3413 i += 2;
3414 } else if remaining_upper.starts_with("FF") {
3415 let ff_len = 2;
3417 let digit = if i + ff_len < chars.len() && chars[i + ff_len].is_ascii_digit() {
3418 let d = chars[i + ff_len];
3419 Some(d)
3420 } else {
3421 None
3422 };
3423 if let Some(d) = digit {
3424 result.push_str("ff");
3425 result.push(d);
3426 i += 3;
3427 } else {
3428 result.push_str("ff9");
3430 i += 2;
3431 }
3432 } else if remaining_upper.starts_with("AM") || remaining_upper.starts_with("PM") {
3433 result.push_str("pm");
3434 i += 2;
3435 } else if remaining_upper.starts_with("TZH") {
3436 result.push_str("tzh");
3437 i += 3;
3438 } else if remaining_upper.starts_with("TZM") {
3439 result.push_str("tzm");
3440 i += 3;
3441 } else {
3442 result.push(chars[i]);
3444 i += 1;
3445 }
3446 }
3447 result
3448 }
3449
3450 fn normalize_format_arg(expr: Expression) -> Expression {
3452 if let Expression::Literal(crate::expressions::Literal::String(s)) = &expr {
3453 let normalized = Self::normalize_snowflake_format(s);
3454 Expression::Literal(crate::expressions::Literal::String(normalized))
3455 } else {
3456 expr
3457 }
3458 }
3459
3460 fn transform_typed_lambda(&self, lambda: crate::expressions::LambdaExpr) -> Expression {
3463 use crate::expressions::{DataType, LambdaExpr};
3464 use std::collections::HashMap;
3465
3466 let mut param_types: HashMap<String, DataType> = HashMap::new();
3468 for (i, param) in lambda.parameters.iter().enumerate() {
3469 if let Some(Some(dt)) = lambda.parameter_types.get(i) {
3470 param_types.insert(param.name.to_uppercase(), dt.clone());
3471 }
3472 }
3473
3474 if param_types.is_empty() {
3476 return Expression::Lambda(Box::new(lambda));
3477 }
3478
3479 let transformed_body = self.replace_lambda_params_with_cast(lambda.body, ¶m_types);
3481
3482 Expression::Lambda(Box::new(LambdaExpr {
3484 parameters: lambda.parameters,
3485 body: transformed_body,
3486 colon: lambda.colon,
3487 parameter_types: Vec::new(), }))
3489 }
3490
3491 fn replace_lambda_params_with_cast(
3493 &self,
3494 expr: Expression,
3495 param_types: &std::collections::HashMap<String, crate::expressions::DataType>,
3496 ) -> Expression {
3497 use crate::expressions::{BinaryOp, Cast, Paren};
3498
3499 match expr {
3500 Expression::Column(col) if col.table.is_none() => {
3502 let name_upper = col.name.name.to_uppercase();
3503 if let Some(dt) = param_types.get(&name_upper) {
3504 Expression::Cast(Box::new(Cast {
3506 this: Expression::Column(col),
3507 to: dt.clone(),
3508 double_colon_syntax: false,
3509 trailing_comments: Vec::new(),
3510 format: None,
3511 default: None,
3512 inferred_type: None,
3513 }))
3514 } else {
3515 Expression::Column(col)
3516 }
3517 }
3518
3519 Expression::Identifier(id) => {
3521 let name_upper = id.name.to_uppercase();
3522 if let Some(dt) = param_types.get(&name_upper) {
3523 Expression::Cast(Box::new(Cast {
3525 this: Expression::Identifier(id),
3526 to: dt.clone(),
3527 double_colon_syntax: false,
3528 trailing_comments: Vec::new(),
3529 format: None,
3530 default: None,
3531 inferred_type: None,
3532 }))
3533 } else {
3534 Expression::Identifier(id)
3535 }
3536 }
3537
3538 Expression::Add(op) => Expression::Add(Box::new(BinaryOp::new(
3540 self.replace_lambda_params_with_cast(op.left, param_types),
3541 self.replace_lambda_params_with_cast(op.right, param_types),
3542 ))),
3543 Expression::Sub(op) => Expression::Sub(Box::new(BinaryOp::new(
3544 self.replace_lambda_params_with_cast(op.left, param_types),
3545 self.replace_lambda_params_with_cast(op.right, param_types),
3546 ))),
3547 Expression::Mul(op) => Expression::Mul(Box::new(BinaryOp::new(
3548 self.replace_lambda_params_with_cast(op.left, param_types),
3549 self.replace_lambda_params_with_cast(op.right, param_types),
3550 ))),
3551 Expression::Div(op) => Expression::Div(Box::new(BinaryOp::new(
3552 self.replace_lambda_params_with_cast(op.left, param_types),
3553 self.replace_lambda_params_with_cast(op.right, param_types),
3554 ))),
3555 Expression::Mod(op) => Expression::Mod(Box::new(BinaryOp::new(
3556 self.replace_lambda_params_with_cast(op.left, param_types),
3557 self.replace_lambda_params_with_cast(op.right, param_types),
3558 ))),
3559
3560 Expression::Paren(p) => Expression::Paren(Box::new(Paren {
3562 this: self.replace_lambda_params_with_cast(p.this, param_types),
3563 trailing_comments: p.trailing_comments,
3564 })),
3565
3566 Expression::Function(mut f) => {
3568 f.args = f
3569 .args
3570 .into_iter()
3571 .map(|arg| self.replace_lambda_params_with_cast(arg, param_types))
3572 .collect();
3573 Expression::Function(f)
3574 }
3575
3576 Expression::Eq(op) => Expression::Eq(Box::new(BinaryOp::new(
3578 self.replace_lambda_params_with_cast(op.left, param_types),
3579 self.replace_lambda_params_with_cast(op.right, param_types),
3580 ))),
3581 Expression::Neq(op) => Expression::Neq(Box::new(BinaryOp::new(
3582 self.replace_lambda_params_with_cast(op.left, param_types),
3583 self.replace_lambda_params_with_cast(op.right, param_types),
3584 ))),
3585 Expression::Lt(op) => Expression::Lt(Box::new(BinaryOp::new(
3586 self.replace_lambda_params_with_cast(op.left, param_types),
3587 self.replace_lambda_params_with_cast(op.right, param_types),
3588 ))),
3589 Expression::Lte(op) => Expression::Lte(Box::new(BinaryOp::new(
3590 self.replace_lambda_params_with_cast(op.left, param_types),
3591 self.replace_lambda_params_with_cast(op.right, param_types),
3592 ))),
3593 Expression::Gt(op) => Expression::Gt(Box::new(BinaryOp::new(
3594 self.replace_lambda_params_with_cast(op.left, param_types),
3595 self.replace_lambda_params_with_cast(op.right, param_types),
3596 ))),
3597 Expression::Gte(op) => Expression::Gte(Box::new(BinaryOp::new(
3598 self.replace_lambda_params_with_cast(op.left, param_types),
3599 self.replace_lambda_params_with_cast(op.right, param_types),
3600 ))),
3601
3602 Expression::And(op) => Expression::And(Box::new(BinaryOp::new(
3604 self.replace_lambda_params_with_cast(op.left, param_types),
3605 self.replace_lambda_params_with_cast(op.right, param_types),
3606 ))),
3607 Expression::Or(op) => Expression::Or(Box::new(BinaryOp::new(
3608 self.replace_lambda_params_with_cast(op.left, param_types),
3609 self.replace_lambda_params_with_cast(op.right, param_types),
3610 ))),
3611
3612 other => other,
3614 }
3615 }
3616
3617 fn transform_aggregate_function(
3618 &self,
3619 f: Box<crate::expressions::AggregateFunction>,
3620 ) -> Result<Expression> {
3621 let name_upper = f.name.to_uppercase();
3622 match name_upper.as_str() {
3623 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3625 Function::new("LISTAGG".to_string(), f.args),
3626 ))),
3627
3628 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3630 Function::new("LISTAGG".to_string(), f.args),
3631 ))),
3632
3633 "APPROX_DISTINCT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3635 Function::new("APPROX_COUNT_DISTINCT".to_string(), f.args),
3636 ))),
3637
3638 "BIT_AND" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3640 "BITAND_AGG".to_string(),
3641 f.args,
3642 )))),
3643
3644 "BIT_OR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3646 "BITOR_AGG".to_string(),
3647 f.args,
3648 )))),
3649
3650 "BIT_XOR" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3652 "BITXOR_AGG".to_string(),
3653 f.args,
3654 )))),
3655
3656 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" if !f.args.is_empty() => {
3658 let arg = f.args.into_iter().next().unwrap();
3659 Ok(Expression::LogicalAnd(Box::new(AggFunc {
3660 this: arg,
3661 distinct: f.distinct,
3662 filter: f.filter,
3663 order_by: Vec::new(),
3664 name: Some("BOOLAND_AGG".to_string()),
3665 ignore_nulls: None,
3666 having_max: None,
3667 limit: None,
3668 inferred_type: None,
3669 })))
3670 }
3671
3672 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if !f.args.is_empty() => {
3674 let arg = f.args.into_iter().next().unwrap();
3675 Ok(Expression::LogicalOr(Box::new(AggFunc {
3676 this: arg,
3677 distinct: f.distinct,
3678 filter: f.filter,
3679 order_by: Vec::new(),
3680 name: Some("BOOLOR_AGG".to_string()),
3681 ignore_nulls: None,
3682 having_max: None,
3683 limit: None,
3684 inferred_type: None,
3685 })))
3686 }
3687
3688 "APPROX_TOP_K" if f.args.len() == 1 => {
3690 let mut args = f.args;
3691 args.push(Expression::number(1));
3692 Ok(Expression::AggregateFunction(Box::new(
3693 crate::expressions::AggregateFunction {
3694 name: "APPROX_TOP_K".to_string(),
3695 args,
3696 distinct: f.distinct,
3697 filter: f.filter,
3698 order_by: Vec::new(),
3699 limit: None,
3700 ignore_nulls: None,
3701 inferred_type: None,
3702 },
3703 )))
3704 }
3705
3706 "SKEW" | "SKEWNESS" if !f.args.is_empty() => {
3708 let arg = f.args.into_iter().next().unwrap();
3709 Ok(Expression::Skewness(Box::new(AggFunc {
3710 this: arg,
3711 distinct: f.distinct,
3712 filter: f.filter,
3713 order_by: Vec::new(),
3714 name: Some("SKEW".to_string()),
3715 ignore_nulls: None,
3716 having_max: None,
3717 limit: None,
3718 inferred_type: None,
3719 })))
3720 }
3721
3722 _ => Ok(Expression::AggregateFunction(f)),
3724 }
3725 }
3726}
3727
3728fn strftime_to_snowflake_format(fmt: &str) -> String {
3730 let mut result = String::new();
3731 let chars: Vec<char> = fmt.chars().collect();
3732 let mut i = 0;
3733 while i < chars.len() {
3734 if chars[i] == '%' && i + 1 < chars.len() {
3735 match chars[i + 1] {
3736 'Y' => {
3737 result.push_str("yyyy");
3738 i += 2;
3739 }
3740 'y' => {
3741 result.push_str("yy");
3742 i += 2;
3743 }
3744 'm' => {
3745 result.push_str("mm");
3746 i += 2;
3747 }
3748 'd' => {
3749 result.push_str("DD");
3750 i += 2;
3751 }
3752 'H' => {
3753 result.push_str("hh24");
3754 i += 2;
3755 }
3756 'M' => {
3757 result.push_str("mmmm");
3758 i += 2;
3759 } 'i' => {
3761 result.push_str("mi");
3762 i += 2;
3763 }
3764 'S' | 's' => {
3765 result.push_str("ss");
3766 i += 2;
3767 }
3768 'f' => {
3769 result.push_str("ff");
3770 i += 2;
3771 }
3772 'w' => {
3773 result.push_str("dy");
3774 i += 2;
3775 } 'a' => {
3777 result.push_str("DY");
3778 i += 2;
3779 } 'b' => {
3781 result.push_str("mon");
3782 i += 2;
3783 } 'T' => {
3785 result.push_str("hh24:mi:ss");
3786 i += 2;
3787 } _ => {
3789 result.push(chars[i]);
3790 result.push(chars[i + 1]);
3791 i += 2;
3792 }
3793 }
3794 } else {
3795 result.push(chars[i]);
3796 i += 1;
3797 }
3798 }
3799 result
3800}
3801
3802#[cfg(test)]
3803mod tests {
3804 use super::*;
3805 use crate::dialects::Dialect;
3806
3807 fn transpile_to_snowflake(sql: &str) -> String {
3808 let dialect = Dialect::get(DialectType::Generic);
3809 let result = dialect
3810 .transpile_to(sql, DialectType::Snowflake)
3811 .expect("Transpile failed");
3812 result[0].clone()
3813 }
3814
3815 #[test]
3816 fn test_ifnull_to_coalesce() {
3817 let result = transpile_to_snowflake("SELECT IFNULL(a, b)");
3818 assert!(
3819 result.contains("COALESCE"),
3820 "Expected COALESCE, got: {}",
3821 result
3822 );
3823 }
3824
3825 #[test]
3826 fn test_basic_select() {
3827 let result = transpile_to_snowflake("SELECT a, b FROM users WHERE id = 1");
3828 assert!(result.contains("SELECT"));
3829 assert!(result.contains("FROM users"));
3830 }
3831
3832 #[test]
3833 fn test_group_concat_to_listagg() {
3834 let result = transpile_to_snowflake("SELECT GROUP_CONCAT(name)");
3835 assert!(
3836 result.contains("LISTAGG"),
3837 "Expected LISTAGG, got: {}",
3838 result
3839 );
3840 }
3841
3842 #[test]
3843 fn test_string_agg_to_listagg() {
3844 let result = transpile_to_snowflake("SELECT STRING_AGG(name)");
3845 assert!(
3846 result.contains("LISTAGG"),
3847 "Expected LISTAGG, got: {}",
3848 result
3849 );
3850 }
3851
3852 #[test]
3853 fn test_array_to_array_construct() {
3854 let result = transpile_to_snowflake("SELECT ARRAY(1, 2, 3)");
3855 assert!(
3857 result.contains("[1, 2, 3]"),
3858 "Expected [1, 2, 3], got: {}",
3859 result
3860 );
3861 }
3862
3863 #[test]
3864 fn test_double_quote_identifiers() {
3865 let dialect = SnowflakeDialect;
3867 let config = dialect.generator_config();
3868 assert_eq!(config.identifier_quote, '"');
3869 }
3870}