1use super::{DialectImpl, DialectType};
7use crate::error::Result;
8use crate::expressions::{
9 AggFunc, AggregateFunction, BinaryOp, Case, Cast, Column, DataType, Expression, Function,
10 JsonExtractFunc, LikeOp, Literal, UnaryFunc, VarArgFunc,
11};
12#[cfg(feature = "generate")]
13use crate::generator::GeneratorConfig;
14use crate::tokens::TokenizerConfig;
15
16pub struct PrestoDialect;
18
19impl DialectImpl for PrestoDialect {
20 fn dialect_type(&self) -> DialectType {
21 DialectType::Presto
22 }
23
24 fn tokenizer_config(&self) -> TokenizerConfig {
25 let mut config = TokenizerConfig::default();
26 config.identifiers.insert('"', '"');
28 config.nested_comments = false;
30 config.keywords.remove("QUALIFY");
33 config
34 }
35
36 #[cfg(feature = "generate")]
37
38 fn generator_config(&self) -> GeneratorConfig {
39 use crate::generator::IdentifierQuoteStyle;
40 GeneratorConfig {
41 identifier_quote: '"',
42 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
43 dialect: Some(DialectType::Presto),
44 limit_only_literals: true,
45 tz_to_with_time_zone: true,
46 ..Default::default()
47 }
48 }
49
50 #[cfg(feature = "transpile")]
51
52 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
53 match expr {
54 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
56 original_name: None,
57 expressions: vec![f.this, f.expression],
58 inferred_type: None,
59 }))),
60
61 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc {
63 original_name: None,
64 expressions: vec![f.this, f.expression],
65 inferred_type: None,
66 }))),
67
68 Expression::TryCast(c) => Ok(Expression::TryCast(c)),
70
71 Expression::SafeCast(c) => Ok(Expression::TryCast(c)),
73
74 Expression::ILike(op) => {
76 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left.clone())));
77 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right.clone())));
78 Ok(Expression::Like(Box::new(LikeOp {
79 left: lower_left,
80 right: lower_right,
81 escape: op.escape,
82 quantifier: op.quantifier.clone(),
83 inferred_type: None,
84 })))
85 }
86
87 Expression::CountIf(f) => Ok(Expression::CountIf(f)),
89
90 Expression::Explode(f) => Ok(Expression::Unnest(Box::new(
92 crate::expressions::UnnestFunc {
93 this: f.this,
94 expressions: Vec::new(),
95 with_ordinality: false,
96 alias: None,
97 offset_alias: None,
98 inferred_type: None,
99 },
100 ))),
101
102 Expression::ExplodeOuter(f) => Ok(Expression::Unnest(Box::new(
104 crate::expressions::UnnestFunc {
105 this: f.this,
106 expressions: Vec::new(),
107 with_ordinality: false,
108 alias: None,
109 offset_alias: None,
110 inferred_type: None,
111 },
112 ))),
113
114 Expression::StringAgg(f) => {
116 let array_agg = Expression::Function(Box::new(Function::new(
117 "ARRAY_AGG".to_string(),
118 vec![f.this.clone()],
119 )));
120 let mut join_args = vec![array_agg];
121 if let Some(sep) = f.separator {
122 join_args.push(sep);
123 }
124 Ok(Expression::Function(Box::new(Function::new(
125 "ARRAY_JOIN".to_string(),
126 join_args,
127 ))))
128 }
129
130 Expression::GroupConcat(f) => {
132 let array_agg = Expression::Function(Box::new(Function::new(
133 "ARRAY_AGG".to_string(),
134 vec![f.this.clone()],
135 )));
136 let mut join_args = vec![array_agg];
137 if let Some(sep) = f.separator {
138 join_args.push(sep);
139 }
140 Ok(Expression::Function(Box::new(Function::new(
141 "ARRAY_JOIN".to_string(),
142 join_args,
143 ))))
144 }
145
146 Expression::ListAgg(f) => {
148 let array_agg = Expression::Function(Box::new(Function::new(
149 "ARRAY_AGG".to_string(),
150 vec![f.this.clone()],
151 )));
152 let mut join_args = vec![array_agg];
153 if let Some(sep) = f.separator {
154 join_args.push(sep);
155 }
156 Ok(Expression::Function(Box::new(Function::new(
157 "ARRAY_JOIN".to_string(),
158 join_args,
159 ))))
160 }
161
162 Expression::JSONExtract(e) if e.variant_extract.is_some() => {
166 let path = match *e.expression {
167 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
168 let Literal::String(s) = lit.as_ref() else {
169 unreachable!()
170 };
171 let normalized = if s.starts_with('$') {
172 s.clone()
173 } else if s.starts_with('[') {
174 format!("${}", s)
175 } else {
176 format!("$.{}", s)
177 };
178 Expression::Literal(Box::new(Literal::String(normalized)))
179 }
180 other => other,
181 };
182 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
183 options: None,
184 source_dialect: None,
185
186 this: *e.this,
187 path,
188 returning: None,
189 arrow_syntax: false,
190 hash_arrow_syntax: false,
191 wrapper_option: None,
192 quotes_option: None,
193 on_scalar_string: false,
194 on_error: None,
195 })))
196 }
197
198 Expression::Function(f) => self.transform_function(*f),
200
201 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
203
204 Expression::Cast(c) => self.transform_cast(*c),
206
207 Expression::Div(mut op) => {
210 if !Self::is_float_cast(&op.left) {
211 op.left = Expression::Cast(Box::new(crate::expressions::Cast {
212 this: op.left,
213 to: DataType::Double {
214 precision: None,
215 scale: None,
216 },
217 trailing_comments: Vec::new(),
218 double_colon_syntax: false,
219 format: None,
220 default: None,
221 inferred_type: None,
222 }));
223 }
224 Ok(Expression::Div(op))
225 }
226
227 Expression::IntDiv(f) => {
229 let cast_x = Expression::Cast(Box::new(Cast {
230 this: f.this,
231 to: crate::expressions::DataType::Double {
232 precision: None,
233 scale: None,
234 },
235 trailing_comments: Vec::new(),
236 double_colon_syntax: false,
237 format: None,
238 default: None,
239 inferred_type: None,
240 }));
241 let div_expr = Expression::Div(Box::new(BinaryOp::new(cast_x, f.expression)));
242 Ok(Expression::Cast(Box::new(Cast {
243 this: div_expr,
244 to: crate::expressions::DataType::Int {
245 length: None,
246 integer_spelling: true,
247 },
248 trailing_comments: Vec::new(),
249 double_colon_syntax: false,
250 format: None,
251 default: None,
252 inferred_type: None,
253 })))
254 }
255
256 Expression::Delete(mut d) => {
258 if d.alias.is_some() {
259 d.alias = None;
260 d.alias_explicit_as = false;
261 if let Some(ref mut where_clause) = d.where_clause {
263 where_clause.this = Self::unqualify_columns(where_clause.this.clone());
264 }
265 }
266 Ok(Expression::Delete(d))
267 }
268
269 _ => Ok(expr),
271 }
272 }
273}
274
275#[cfg(feature = "transpile")]
276impl PrestoDialect {
277 fn unqualify_columns(expr: Expression) -> Expression {
279 match expr {
280 Expression::Column(c) => {
281 if c.table.is_some() {
282 Expression::boxed_column(Column {
283 name: c.name,
284 table: None,
285 join_mark: c.join_mark,
286 trailing_comments: c.trailing_comments,
287 span: None,
288 inferred_type: None,
289 })
290 } else {
291 Expression::Column(c)
292 }
293 }
294 Expression::Dot(d) => Expression::boxed_column(Column {
296 name: d.field,
297 table: None,
298 join_mark: false,
299 trailing_comments: Vec::new(),
300 span: None,
301 inferred_type: None,
302 }),
303 Expression::And(mut op) => {
305 op.left = Self::unqualify_columns(op.left);
306 op.right = Self::unqualify_columns(op.right);
307 Expression::And(op)
308 }
309 Expression::Or(mut op) => {
310 op.left = Self::unqualify_columns(op.left);
311 op.right = Self::unqualify_columns(op.right);
312 Expression::Or(op)
313 }
314 Expression::Eq(mut op) => {
315 op.left = Self::unqualify_columns(op.left);
316 op.right = Self::unqualify_columns(op.right);
317 Expression::Eq(op)
318 }
319 Expression::Neq(mut op) => {
320 op.left = Self::unqualify_columns(op.left);
321 op.right = Self::unqualify_columns(op.right);
322 Expression::Neq(op)
323 }
324 Expression::Gt(mut op) => {
325 op.left = Self::unqualify_columns(op.left);
326 op.right = Self::unqualify_columns(op.right);
327 Expression::Gt(op)
328 }
329 Expression::Lt(mut op) => {
330 op.left = Self::unqualify_columns(op.left);
331 op.right = Self::unqualify_columns(op.right);
332 Expression::Lt(op)
333 }
334 Expression::Gte(mut op) => {
335 op.left = Self::unqualify_columns(op.left);
336 op.right = Self::unqualify_columns(op.right);
337 Expression::Gte(op)
338 }
339 Expression::Lte(mut op) => {
340 op.left = Self::unqualify_columns(op.left);
341 op.right = Self::unqualify_columns(op.right);
342 Expression::Lte(op)
343 }
344 Expression::Not(mut e) => {
346 e.this = Self::unqualify_columns(e.this);
347 Expression::Not(e)
348 }
349 Expression::In(mut i) => {
351 i.this = Self::unqualify_columns(i.this);
352 i.expressions = i
353 .expressions
354 .into_iter()
355 .map(Self::unqualify_columns)
356 .collect();
357 if let Some(q) = i.query {
359 i.query = Some(Self::unqualify_columns(q));
360 }
361 Expression::In(i)
362 }
363 Expression::IsNull(mut f) => {
364 f.this = Self::unqualify_columns(f.this);
365 Expression::IsNull(f)
366 }
367 Expression::Paren(mut p) => {
368 p.this = Self::unqualify_columns(p.this);
369 Expression::Paren(p)
370 }
371 Expression::Function(mut f) => {
372 f.args = f.args.into_iter().map(Self::unqualify_columns).collect();
373 Expression::Function(f)
374 }
375 Expression::Select(mut s) => {
377 s.expressions = s
378 .expressions
379 .into_iter()
380 .map(Self::unqualify_columns)
381 .collect();
382 if let Some(ref mut w) = s.where_clause {
383 w.this = Self::unqualify_columns(w.this.clone());
384 }
385 Expression::Select(s)
386 }
387 Expression::Subquery(mut sq) => {
388 sq.this = Self::unqualify_columns(sq.this);
389 Expression::Subquery(sq)
390 }
391 Expression::Alias(mut a) => {
392 a.this = Self::unqualify_columns(a.this);
393 Expression::Alias(a)
394 }
395 other => other,
397 }
398 }
399
400 fn is_float_cast(expr: &Expression) -> bool {
402 if let Expression::Cast(cast) = expr {
403 matches!(&cast.to, DataType::Double { .. } | DataType::Float { .. })
404 } else {
405 false
406 }
407 }
408
409 pub fn oracle_to_presto_format(fmt: &str) -> String {
413 let mut cursor = crate::format_tokens::FormatTokenCursor::new(fmt);
415 let mut result = String::new();
416 while let Some(ch) = cursor.peek() {
417 if cursor.consume_prefix("yyyy", false) {
418 result.push_str("%Y");
419 } else if cursor.consume_prefix("yy", false) {
420 result.push_str("%y");
421 } else if cursor.consume_prefix("hh24", false) {
422 result.push_str("%H");
423 } else if cursor.consume_prefix("hh", false) {
424 result.push_str("%H");
425 } else if cursor.consume_prefix("mi", false) {
426 result.push_str("%i");
427 } else if cursor.consume_prefix("mm", false) {
428 result.push_str("%m");
429 } else if cursor.consume_prefix("dd", false) {
430 result.push_str("%d");
431 } else if cursor.consume_prefix("ss", false) {
432 result.push_str("%s");
433 } else {
434 result.push(ch);
435 cursor.next_char();
436 }
437 }
438 result
439 }
440
441 pub fn presto_to_java_format(fmt: &str) -> String {
445 fmt.replace("%Y", "yyyy")
446 .replace("%m", "M")
447 .replace("%d", "d")
448 .replace("%H", "H")
449 .replace("%i", "m")
450 .replace("%S", "s")
451 .replace("%s", "s")
452 .replace("%y", "yy")
453 .replace("%T", "H:m:s")
454 .replace("%F", "yyyy-M-d")
455 .replace("%M", "MMMM")
456 }
457
458 pub fn normalize_presto_format(fmt: &str) -> String {
460 fmt.replace("%H:%i:%S", "%T").replace("%H:%i:%s", "%T")
461 }
462
463 pub fn presto_to_duckdb_format(fmt: &str) -> String {
465 fmt.replace("%i", "%M")
466 .replace("%s", "%S")
467 .replace("%T", "%H:%M:%S")
468 }
469
470 pub fn presto_to_bigquery_format(fmt: &str) -> String {
472 let result = fmt
475 .replace("%Y-%m-%d", "%F")
476 .replace("%H:%i:%S", "%T")
477 .replace("%H:%i:%s", "%T")
478 .replace("%i", "%M")
479 .replace("%s", "%S");
480 result
481 }
482
483 pub fn is_default_timestamp_format(fmt: &str) -> bool {
485 let normalized = Self::normalize_presto_format(fmt);
486 normalized == "%Y-%m-%d %T"
487 || normalized == "%Y-%m-%d %H:%i:%S"
488 || fmt == "%Y-%m-%d %H:%i:%S"
489 || fmt == "%Y-%m-%d %T"
490 }
491
492 pub fn is_default_date_format(fmt: &str) -> bool {
494 fmt == "%Y-%m-%d" || fmt == "%F"
495 }
496
497 fn transform_function(&self, f: Function) -> Result<Expression> {
498 let name_upper = f.name.to_uppercase();
499 match name_upper.as_str() {
500 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
502 original_name: None,
503 expressions: f.args,
504 inferred_type: None,
505 }))),
506
507 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
509 original_name: None,
510 expressions: f.args,
511 inferred_type: None,
512 }))),
513
514 "ISNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
516 original_name: None,
517 expressions: f.args,
518 inferred_type: None,
519 }))),
520
521 "GETDATE" => Ok(Expression::CurrentTimestamp(
523 crate::expressions::CurrentTimestamp {
524 precision: None,
525 sysdate: false,
526 },
527 )),
528
529 "NOW" => Ok(Expression::CurrentTimestamp(
531 crate::expressions::CurrentTimestamp {
532 precision: None,
533 sysdate: false,
534 },
535 )),
536
537 "RAND" => Ok(Expression::Function(Box::new(Function::new(
539 "RANDOM".to_string(),
540 vec![],
541 )))),
542
543 "GROUP_CONCAT" if !f.args.is_empty() => {
545 let mut args = f.args;
546 let first = args.remove(0);
547 let separator = args.pop();
548 let array_agg = Expression::Function(Box::new(Function::new(
549 "ARRAY_AGG".to_string(),
550 vec![first],
551 )));
552 let mut join_args = vec![array_agg];
553 if let Some(sep) = separator {
554 join_args.push(sep);
555 }
556 Ok(Expression::Function(Box::new(Function::new(
557 "ARRAY_JOIN".to_string(),
558 join_args,
559 ))))
560 }
561
562 "STRING_AGG" if !f.args.is_empty() => {
564 let mut args = f.args;
565 let first = args.remove(0);
566 let separator = args.pop();
567 let array_agg = Expression::Function(Box::new(Function::new(
568 "ARRAY_AGG".to_string(),
569 vec![first],
570 )));
571 let mut join_args = vec![array_agg];
572 if let Some(sep) = separator {
573 join_args.push(sep);
574 }
575 Ok(Expression::Function(Box::new(Function::new(
576 "ARRAY_JOIN".to_string(),
577 join_args,
578 ))))
579 }
580
581 "LISTAGG" if !f.args.is_empty() => {
583 let mut args = f.args;
584 let first = args.remove(0);
585 let separator = args.pop();
586 let array_agg = Expression::Function(Box::new(Function::new(
587 "ARRAY_AGG".to_string(),
588 vec![first],
589 )));
590 let mut join_args = vec![array_agg];
591 if let Some(sep) = separator {
592 join_args.push(sep);
593 }
594 Ok(Expression::Function(Box::new(Function::new(
595 "ARRAY_JOIN".to_string(),
596 join_args,
597 ))))
598 }
599
600 "SUBSTR" => Ok(Expression::Function(Box::new(f))),
602
603 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
605 f.args.into_iter().next().unwrap(),
606 )))),
607
608 "CHARINDEX" if f.args.len() >= 2 => {
610 let mut args = f.args;
611 let substring = args.remove(0);
612 let string = args.remove(0);
613 Ok(Expression::Function(Box::new(Function::new(
615 "STRPOS".to_string(),
616 vec![string, substring],
617 ))))
618 }
619
620 "INSTR" if f.args.len() >= 2 => {
622 let args = f.args;
623 Ok(Expression::Function(Box::new(Function::new(
625 "STRPOS".to_string(),
626 args,
627 ))))
628 }
629
630 "LOCATE" if f.args.len() >= 2 => {
632 let mut args = f.args;
633 let substring = args.remove(0);
634 let string = args.remove(0);
635 Ok(Expression::Function(Box::new(Function::new(
637 "STRPOS".to_string(),
638 vec![string, substring],
639 ))))
640 }
641
642 "ARRAY_LENGTH" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
644 Function::new("CARDINALITY".to_string(), f.args),
645 ))),
646
647 "SIZE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
649 "CARDINALITY".to_string(),
650 f.args,
651 )))),
652
653 "ARRAY_CONTAINS" if f.args.len() == 2 => Ok(Expression::Function(Box::new(
655 Function::new("CONTAINS".to_string(), f.args),
656 ))),
657
658 "TO_DATE" if !f.args.is_empty() => {
660 if f.args.len() == 1 {
661 Ok(Expression::Cast(Box::new(Cast {
663 this: f.args.into_iter().next().unwrap(),
664 to: DataType::Date,
665 trailing_comments: Vec::new(),
666 double_colon_syntax: false,
667 format: None,
668 default: None,
669 inferred_type: None,
670 })))
671 } else {
672 Ok(Expression::Function(Box::new(Function::new(
674 "DATE_PARSE".to_string(),
675 f.args,
676 ))))
677 }
678 }
679
680 "TO_TIMESTAMP" if !f.args.is_empty() => {
682 if f.args.len() == 1 {
683 Ok(Expression::Cast(Box::new(Cast {
684 this: f.args.into_iter().next().unwrap(),
685 to: DataType::Timestamp {
686 precision: None,
687 timezone: false,
688 },
689 trailing_comments: Vec::new(),
690 double_colon_syntax: false,
691 format: None,
692 default: None,
693 inferred_type: None,
694 })))
695 } else {
696 Ok(Expression::Function(Box::new(Function::new(
697 "DATE_PARSE".to_string(),
698 f.args,
699 ))))
700 }
701 }
702
703 "DATE_FORMAT" => Ok(Expression::Function(Box::new(f))),
705
706 "STRFTIME" if f.args.len() >= 2 => {
708 let mut args = f.args;
709 let format = args.remove(0);
711 let date = args.remove(0);
712 Ok(Expression::Function(Box::new(Function::new(
713 "DATE_FORMAT".to_string(),
714 vec![date, format],
715 ))))
716 }
717
718 "TO_CHAR" if f.args.len() >= 2 => {
720 let mut args = f.args;
721 if let Expression::Literal(ref lit) = args[1] {
723 if let Literal::String(ref s) = lit.as_ref() {
724 let converted = Self::oracle_to_presto_format(s);
725 args[1] = Expression::Literal(Box::new(Literal::String(converted)));
726 }
727 }
728 Ok(Expression::Function(Box::new(Function::new(
729 "DATE_FORMAT".to_string(),
730 args,
731 ))))
732 }
733
734 "LEVENSHTEIN" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
736 Function::new("LEVENSHTEIN_DISTANCE".to_string(), f.args),
737 ))),
738
739 "FLATTEN" => Ok(Expression::Function(Box::new(f))),
741
742 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(f))),
744
745 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(f))),
747
748 "GET_JSON_OBJECT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(
750 Function::new("JSON_EXTRACT_SCALAR".to_string(), f.args),
751 ))),
752
753 "COLLECT_LIST" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
755 Function::new("ARRAY_AGG".to_string(), f.args),
756 ))),
757
758 "COLLECT_SET" if !f.args.is_empty() => {
760 let array_agg =
761 Expression::Function(Box::new(Function::new("ARRAY_AGG".to_string(), f.args)));
762 Ok(Expression::Function(Box::new(Function::new(
763 "ARRAY_DISTINCT".to_string(),
764 vec![array_agg],
765 ))))
766 }
767
768 "RLIKE" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
770 "REGEXP_LIKE".to_string(),
771 f.args,
772 )))),
773
774 "REGEXP" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
776 "REGEXP_LIKE".to_string(),
777 f.args,
778 )))),
779
780 "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
782 "JSON_PARSE".to_string(),
783 f.args,
784 )))),
785
786 "GET_PATH" if f.args.len() == 2 => {
788 let mut args = f.args;
789 let this = args.remove(0);
790 let path = args.remove(0);
791 let json_path = match &path {
792 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
793 let Literal::String(s) = lit.as_ref() else {
794 unreachable!()
795 };
796 let normalized = if s.starts_with('$') {
797 s.clone()
798 } else if s.starts_with('[') {
799 format!("${}", s)
800 } else {
801 format!("$.{}", s)
802 };
803 Expression::Literal(Box::new(Literal::String(normalized)))
804 }
805 _ => path,
806 };
807 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
808 options: None,
809 source_dialect: None,
810
811 this,
812 path: json_path,
813 returning: None,
814 arrow_syntax: false,
815 hash_arrow_syntax: false,
816 wrapper_option: None,
817 quotes_option: None,
818 on_scalar_string: false,
819 on_error: None,
820 })))
821 }
822
823 "REGEXP_SUBSTR" if f.args.len() >= 2 => {
825 let mut args = f.args;
826 let subject = args.remove(0);
827 let pattern = args.remove(0);
828 if args.len() >= 4 {
830 let _pos = args.remove(0);
831 let _occ = args.remove(0);
832 let _params = args.remove(0);
833 let group = args.remove(0);
834 Ok(Expression::Function(Box::new(Function::new(
835 "REGEXP_EXTRACT".to_string(),
836 vec![subject, pattern, group],
837 ))))
838 } else {
839 Ok(Expression::Function(Box::new(Function::new(
840 "REGEXP_EXTRACT".to_string(),
841 vec![subject, pattern],
842 ))))
843 }
844 }
845
846 "DATE_PART" if f.args.len() == 2 => {
849 let part_name = match &f.args[0] {
850 Expression::Identifier(id) => Some(id.name.to_uppercase()),
851 Expression::Var(v) => Some(v.this.to_uppercase()),
852 Expression::Column(c) => Some(c.name.name.to_uppercase()),
853 _ => None,
854 };
855 match part_name.as_deref() {
856 Some("EPOCH_SECOND" | "EPOCH_SECONDS") => {
857 let mut args = f.args;
858 let value = args.remove(1);
859 let cast_expr = Expression::Cast(Box::new(Cast {
860 this: value,
861 to: DataType::Timestamp {
862 precision: None,
863 timezone: false,
864 },
865 trailing_comments: Vec::new(),
866 double_colon_syntax: false,
867 format: None,
868 default: None,
869 inferred_type: None,
870 }));
871 Ok(Expression::Function(Box::new(Function::new(
872 "TO_UNIXTIME".to_string(),
873 vec![cast_expr],
874 ))))
875 }
876 Some("EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS") => {
877 let mut args = f.args;
878 let value = args.remove(1);
879 let cast_expr = Expression::Cast(Box::new(Cast {
880 this: value,
881 to: DataType::Timestamp {
882 precision: None,
883 timezone: false,
884 },
885 trailing_comments: Vec::new(),
886 double_colon_syntax: false,
887 format: None,
888 default: None,
889 inferred_type: None,
890 }));
891 let unixtime = Expression::Function(Box::new(Function::new(
892 "TO_UNIXTIME".to_string(),
893 vec![cast_expr],
894 )));
895 Ok(Expression::Mul(Box::new(BinaryOp {
896 left: unixtime,
897 right: Expression::Literal(Box::new(Literal::Number(
898 "1000".to_string(),
899 ))),
900 left_comments: Vec::new(),
901 operator_comments: Vec::new(),
902 trailing_comments: Vec::new(),
903 inferred_type: None,
904 })))
905 }
906 _ => Ok(Expression::Function(Box::new(f))),
907 }
908 }
909
910 "REPLACE" if f.args.len() == 2 => {
912 let mut args = f.args;
913 args.push(Expression::string(""));
914 Ok(Expression::Function(Box::new(Function::new(
915 "REPLACE".to_string(),
916 args,
917 ))))
918 }
919
920 "REGEXP_REPLACE" if f.args.len() == 2 => {
922 let mut args = f.args;
923 args.push(Expression::string(""));
924 Ok(Expression::Function(Box::new(Function::new(
925 "REGEXP_REPLACE".to_string(),
926 args,
927 ))))
928 }
929
930 _ => Ok(Expression::Function(Box::new(f))),
932 }
933 }
934
935 fn transform_aggregate_function(
936 &self,
937 f: Box<crate::expressions::AggregateFunction>,
938 ) -> Result<Expression> {
939 let name_upper = f.name.to_uppercase();
940 match name_upper.as_str() {
941 "COUNT_IF" if !f.args.is_empty() => {
943 let condition = f.args.into_iter().next().unwrap();
944 let case_expr = Expression::Case(Box::new(Case {
945 operand: None,
946 whens: vec![(condition, Expression::number(1))],
947 else_: Some(Expression::number(0)),
948 comments: Vec::new(),
949 inferred_type: None,
950 }));
951 Ok(Expression::Sum(Box::new(AggFunc {
952 ignore_nulls: None,
953 having_max: None,
954 this: case_expr,
955 distinct: f.distinct,
956 filter: f.filter,
957 order_by: Vec::new(),
958 name: None,
959 limit: None,
960 inferred_type: None,
961 })))
962 }
963
964 "ANY_VALUE" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
966 "ARBITRARY".to_string(),
967 f.args,
968 )))),
969
970 "GROUP_CONCAT" if !f.args.is_empty() => {
972 let mut args = f.args;
973 let first = args.remove(0);
974 let separator = args.pop();
975 let array_agg = Expression::Function(Box::new(Function::new(
976 "ARRAY_AGG".to_string(),
977 vec![first],
978 )));
979 let mut join_args = vec![array_agg];
980 if let Some(sep) = separator {
981 join_args.push(sep);
982 }
983 Ok(Expression::Function(Box::new(Function::new(
984 "ARRAY_JOIN".to_string(),
985 join_args,
986 ))))
987 }
988
989 "STRING_AGG" if !f.args.is_empty() => {
991 let mut args = f.args;
992 let first = args.remove(0);
993 let separator = args.pop();
994 let array_agg = Expression::Function(Box::new(Function::new(
995 "ARRAY_AGG".to_string(),
996 vec![first],
997 )));
998 let mut join_args = vec![array_agg];
999 if let Some(sep) = separator {
1000 join_args.push(sep);
1001 }
1002 Ok(Expression::Function(Box::new(Function::new(
1003 "ARRAY_JOIN".to_string(),
1004 join_args,
1005 ))))
1006 }
1007
1008 "LISTAGG" if !f.args.is_empty() => {
1010 let mut args = f.args;
1011 let first = args.remove(0);
1012 let separator = args.pop();
1013 let array_agg = Expression::Function(Box::new(Function::new(
1014 "ARRAY_AGG".to_string(),
1015 vec![first],
1016 )));
1017 let mut join_args = vec![array_agg];
1018 if let Some(sep) = separator {
1019 join_args.push(sep);
1020 }
1021 Ok(Expression::Function(Box::new(Function::new(
1022 "ARRAY_JOIN".to_string(),
1023 join_args,
1024 ))))
1025 }
1026
1027 "VAR" if !f.args.is_empty() => {
1029 Ok(Expression::AggregateFunction(Box::new(AggregateFunction {
1030 source_dialect: None,
1031
1032 name: "VAR_POP".to_string(),
1033 args: f.args,
1034 distinct: f.distinct,
1035 filter: f.filter,
1036 order_by: Vec::new(),
1037 limit: None,
1038 ignore_nulls: None,
1039 inferred_type: None,
1040 })))
1041 }
1042
1043 "VARIANCE" if !f.args.is_empty() => {
1045 Ok(Expression::AggregateFunction(Box::new(AggregateFunction {
1046 source_dialect: None,
1047
1048 name: "VAR_SAMP".to_string(),
1049 args: f.args,
1050 distinct: f.distinct,
1051 filter: f.filter,
1052 order_by: Vec::new(),
1053 limit: None,
1054 ignore_nulls: None,
1055 inferred_type: None,
1056 })))
1057 }
1058
1059 _ => Ok(Expression::AggregateFunction(f)),
1061 }
1062 }
1063
1064 fn transform_cast(&self, c: Cast) -> Result<Expression> {
1065 Ok(Expression::Cast(Box::new(c)))
1067 }
1068}