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 this: *e.this,
184 path,
185 returning: None,
186 arrow_syntax: false,
187 hash_arrow_syntax: false,
188 wrapper_option: None,
189 quotes_option: None,
190 on_scalar_string: false,
191 on_error: None,
192 })))
193 }
194
195 Expression::Function(f) => self.transform_function(*f),
197
198 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
200
201 Expression::Cast(c) => self.transform_cast(*c),
203
204 Expression::Div(mut op) => {
207 if !Self::is_float_cast(&op.left) {
208 op.left = Expression::Cast(Box::new(crate::expressions::Cast {
209 this: op.left,
210 to: DataType::Double {
211 precision: None,
212 scale: None,
213 },
214 trailing_comments: Vec::new(),
215 double_colon_syntax: false,
216 format: None,
217 default: None,
218 inferred_type: None,
219 }));
220 }
221 Ok(Expression::Div(op))
222 }
223
224 Expression::IntDiv(f) => {
226 let cast_x = Expression::Cast(Box::new(Cast {
227 this: f.this,
228 to: crate::expressions::DataType::Double {
229 precision: None,
230 scale: None,
231 },
232 trailing_comments: Vec::new(),
233 double_colon_syntax: false,
234 format: None,
235 default: None,
236 inferred_type: None,
237 }));
238 let div_expr = Expression::Div(Box::new(BinaryOp::new(cast_x, f.expression)));
239 Ok(Expression::Cast(Box::new(Cast {
240 this: div_expr,
241 to: crate::expressions::DataType::Int {
242 length: None,
243 integer_spelling: true,
244 },
245 trailing_comments: Vec::new(),
246 double_colon_syntax: false,
247 format: None,
248 default: None,
249 inferred_type: None,
250 })))
251 }
252
253 Expression::Delete(mut d) => {
255 if d.alias.is_some() {
256 d.alias = None;
257 d.alias_explicit_as = false;
258 if let Some(ref mut where_clause) = d.where_clause {
260 where_clause.this = Self::unqualify_columns(where_clause.this.clone());
261 }
262 }
263 Ok(Expression::Delete(d))
264 }
265
266 _ => Ok(expr),
268 }
269 }
270}
271
272#[cfg(feature = "transpile")]
273impl PrestoDialect {
274 fn unqualify_columns(expr: Expression) -> Expression {
276 match expr {
277 Expression::Column(c) => {
278 if c.table.is_some() {
279 Expression::boxed_column(Column {
280 name: c.name,
281 table: None,
282 join_mark: c.join_mark,
283 trailing_comments: c.trailing_comments,
284 span: None,
285 inferred_type: None,
286 })
287 } else {
288 Expression::Column(c)
289 }
290 }
291 Expression::Dot(d) => Expression::boxed_column(Column {
293 name: d.field,
294 table: None,
295 join_mark: false,
296 trailing_comments: Vec::new(),
297 span: None,
298 inferred_type: None,
299 }),
300 Expression::And(mut op) => {
302 op.left = Self::unqualify_columns(op.left);
303 op.right = Self::unqualify_columns(op.right);
304 Expression::And(op)
305 }
306 Expression::Or(mut op) => {
307 op.left = Self::unqualify_columns(op.left);
308 op.right = Self::unqualify_columns(op.right);
309 Expression::Or(op)
310 }
311 Expression::Eq(mut op) => {
312 op.left = Self::unqualify_columns(op.left);
313 op.right = Self::unqualify_columns(op.right);
314 Expression::Eq(op)
315 }
316 Expression::Neq(mut op) => {
317 op.left = Self::unqualify_columns(op.left);
318 op.right = Self::unqualify_columns(op.right);
319 Expression::Neq(op)
320 }
321 Expression::Gt(mut op) => {
322 op.left = Self::unqualify_columns(op.left);
323 op.right = Self::unqualify_columns(op.right);
324 Expression::Gt(op)
325 }
326 Expression::Lt(mut op) => {
327 op.left = Self::unqualify_columns(op.left);
328 op.right = Self::unqualify_columns(op.right);
329 Expression::Lt(op)
330 }
331 Expression::Gte(mut op) => {
332 op.left = Self::unqualify_columns(op.left);
333 op.right = Self::unqualify_columns(op.right);
334 Expression::Gte(op)
335 }
336 Expression::Lte(mut op) => {
337 op.left = Self::unqualify_columns(op.left);
338 op.right = Self::unqualify_columns(op.right);
339 Expression::Lte(op)
340 }
341 Expression::Not(mut e) => {
343 e.this = Self::unqualify_columns(e.this);
344 Expression::Not(e)
345 }
346 Expression::In(mut i) => {
348 i.this = Self::unqualify_columns(i.this);
349 i.expressions = i
350 .expressions
351 .into_iter()
352 .map(Self::unqualify_columns)
353 .collect();
354 if let Some(q) = i.query {
356 i.query = Some(Self::unqualify_columns(q));
357 }
358 Expression::In(i)
359 }
360 Expression::IsNull(mut f) => {
361 f.this = Self::unqualify_columns(f.this);
362 Expression::IsNull(f)
363 }
364 Expression::Paren(mut p) => {
365 p.this = Self::unqualify_columns(p.this);
366 Expression::Paren(p)
367 }
368 Expression::Function(mut f) => {
369 f.args = f.args.into_iter().map(Self::unqualify_columns).collect();
370 Expression::Function(f)
371 }
372 Expression::Select(mut s) => {
374 s.expressions = s
375 .expressions
376 .into_iter()
377 .map(Self::unqualify_columns)
378 .collect();
379 if let Some(ref mut w) = s.where_clause {
380 w.this = Self::unqualify_columns(w.this.clone());
381 }
382 Expression::Select(s)
383 }
384 Expression::Subquery(mut sq) => {
385 sq.this = Self::unqualify_columns(sq.this);
386 Expression::Subquery(sq)
387 }
388 Expression::Alias(mut a) => {
389 a.this = Self::unqualify_columns(a.this);
390 Expression::Alias(a)
391 }
392 other => other,
394 }
395 }
396
397 fn is_float_cast(expr: &Expression) -> bool {
399 if let Expression::Cast(cast) = expr {
400 matches!(&cast.to, DataType::Double { .. } | DataType::Float { .. })
401 } else {
402 false
403 }
404 }
405
406 pub fn oracle_to_presto_format(fmt: &str) -> String {
410 let mut cursor = crate::format_tokens::FormatTokenCursor::new(fmt);
412 let mut result = String::new();
413 while let Some(ch) = cursor.peek() {
414 if cursor.consume_prefix("yyyy", false) {
415 result.push_str("%Y");
416 } else if cursor.consume_prefix("yy", false) {
417 result.push_str("%y");
418 } else if cursor.consume_prefix("hh24", false) {
419 result.push_str("%H");
420 } else if cursor.consume_prefix("hh", false) {
421 result.push_str("%H");
422 } else if cursor.consume_prefix("mi", false) {
423 result.push_str("%i");
424 } else if cursor.consume_prefix("mm", false) {
425 result.push_str("%m");
426 } else if cursor.consume_prefix("dd", false) {
427 result.push_str("%d");
428 } else if cursor.consume_prefix("ss", false) {
429 result.push_str("%s");
430 } else {
431 result.push(ch);
432 cursor.next_char();
433 }
434 }
435 result
436 }
437
438 pub fn presto_to_java_format(fmt: &str) -> String {
442 fmt.replace("%Y", "yyyy")
443 .replace("%m", "M")
444 .replace("%d", "d")
445 .replace("%H", "H")
446 .replace("%i", "m")
447 .replace("%S", "s")
448 .replace("%s", "s")
449 .replace("%y", "yy")
450 .replace("%T", "H:m:s")
451 .replace("%F", "yyyy-M-d")
452 .replace("%M", "MMMM")
453 }
454
455 pub fn normalize_presto_format(fmt: &str) -> String {
457 fmt.replace("%H:%i:%S", "%T").replace("%H:%i:%s", "%T")
458 }
459
460 pub fn presto_to_duckdb_format(fmt: &str) -> String {
462 fmt.replace("%i", "%M")
463 .replace("%s", "%S")
464 .replace("%T", "%H:%M:%S")
465 }
466
467 pub fn presto_to_bigquery_format(fmt: &str) -> String {
469 let result = fmt
472 .replace("%Y-%m-%d", "%F")
473 .replace("%H:%i:%S", "%T")
474 .replace("%H:%i:%s", "%T")
475 .replace("%i", "%M")
476 .replace("%s", "%S");
477 result
478 }
479
480 pub fn is_default_timestamp_format(fmt: &str) -> bool {
482 let normalized = Self::normalize_presto_format(fmt);
483 normalized == "%Y-%m-%d %T"
484 || normalized == "%Y-%m-%d %H:%i:%S"
485 || fmt == "%Y-%m-%d %H:%i:%S"
486 || fmt == "%Y-%m-%d %T"
487 }
488
489 pub fn is_default_date_format(fmt: &str) -> bool {
491 fmt == "%Y-%m-%d" || fmt == "%F"
492 }
493
494 fn transform_function(&self, f: Function) -> Result<Expression> {
495 let name_upper = f.name.to_uppercase();
496 match name_upper.as_str() {
497 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
499 original_name: None,
500 expressions: f.args,
501 inferred_type: None,
502 }))),
503
504 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
506 original_name: None,
507 expressions: f.args,
508 inferred_type: None,
509 }))),
510
511 "ISNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc {
513 original_name: None,
514 expressions: f.args,
515 inferred_type: None,
516 }))),
517
518 "GETDATE" => Ok(Expression::CurrentTimestamp(
520 crate::expressions::CurrentTimestamp {
521 precision: None,
522 sysdate: false,
523 },
524 )),
525
526 "NOW" => Ok(Expression::CurrentTimestamp(
528 crate::expressions::CurrentTimestamp {
529 precision: None,
530 sysdate: false,
531 },
532 )),
533
534 "RAND" => Ok(Expression::Function(Box::new(Function::new(
536 "RANDOM".to_string(),
537 vec![],
538 )))),
539
540 "GROUP_CONCAT" if !f.args.is_empty() => {
542 let mut args = f.args;
543 let first = args.remove(0);
544 let separator = args.pop();
545 let array_agg = Expression::Function(Box::new(Function::new(
546 "ARRAY_AGG".to_string(),
547 vec![first],
548 )));
549 let mut join_args = vec![array_agg];
550 if let Some(sep) = separator {
551 join_args.push(sep);
552 }
553 Ok(Expression::Function(Box::new(Function::new(
554 "ARRAY_JOIN".to_string(),
555 join_args,
556 ))))
557 }
558
559 "STRING_AGG" if !f.args.is_empty() => {
561 let mut args = f.args;
562 let first = args.remove(0);
563 let separator = args.pop();
564 let array_agg = Expression::Function(Box::new(Function::new(
565 "ARRAY_AGG".to_string(),
566 vec![first],
567 )));
568 let mut join_args = vec![array_agg];
569 if let Some(sep) = separator {
570 join_args.push(sep);
571 }
572 Ok(Expression::Function(Box::new(Function::new(
573 "ARRAY_JOIN".to_string(),
574 join_args,
575 ))))
576 }
577
578 "LISTAGG" if !f.args.is_empty() => {
580 let mut args = f.args;
581 let first = args.remove(0);
582 let separator = args.pop();
583 let array_agg = Expression::Function(Box::new(Function::new(
584 "ARRAY_AGG".to_string(),
585 vec![first],
586 )));
587 let mut join_args = vec![array_agg];
588 if let Some(sep) = separator {
589 join_args.push(sep);
590 }
591 Ok(Expression::Function(Box::new(Function::new(
592 "ARRAY_JOIN".to_string(),
593 join_args,
594 ))))
595 }
596
597 "SUBSTR" => Ok(Expression::Function(Box::new(f))),
599
600 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
602 f.args.into_iter().next().unwrap(),
603 )))),
604
605 "CHARINDEX" if f.args.len() >= 2 => {
607 let mut args = f.args;
608 let substring = args.remove(0);
609 let string = args.remove(0);
610 Ok(Expression::Function(Box::new(Function::new(
612 "STRPOS".to_string(),
613 vec![string, substring],
614 ))))
615 }
616
617 "INSTR" if f.args.len() >= 2 => {
619 let args = f.args;
620 Ok(Expression::Function(Box::new(Function::new(
622 "STRPOS".to_string(),
623 args,
624 ))))
625 }
626
627 "LOCATE" if f.args.len() >= 2 => {
629 let mut args = f.args;
630 let substring = args.remove(0);
631 let string = args.remove(0);
632 Ok(Expression::Function(Box::new(Function::new(
634 "STRPOS".to_string(),
635 vec![string, substring],
636 ))))
637 }
638
639 "ARRAY_LENGTH" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
641 Function::new("CARDINALITY".to_string(), f.args),
642 ))),
643
644 "SIZE" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
646 "CARDINALITY".to_string(),
647 f.args,
648 )))),
649
650 "ARRAY_CONTAINS" if f.args.len() == 2 => Ok(Expression::Function(Box::new(
652 Function::new("CONTAINS".to_string(), f.args),
653 ))),
654
655 "TO_DATE" if !f.args.is_empty() => {
657 if f.args.len() == 1 {
658 Ok(Expression::Cast(Box::new(Cast {
660 this: f.args.into_iter().next().unwrap(),
661 to: DataType::Date,
662 trailing_comments: Vec::new(),
663 double_colon_syntax: false,
664 format: None,
665 default: None,
666 inferred_type: None,
667 })))
668 } else {
669 Ok(Expression::Function(Box::new(Function::new(
671 "DATE_PARSE".to_string(),
672 f.args,
673 ))))
674 }
675 }
676
677 "TO_TIMESTAMP" if !f.args.is_empty() => {
679 if f.args.len() == 1 {
680 Ok(Expression::Cast(Box::new(Cast {
681 this: f.args.into_iter().next().unwrap(),
682 to: DataType::Timestamp {
683 precision: None,
684 timezone: false,
685 },
686 trailing_comments: Vec::new(),
687 double_colon_syntax: false,
688 format: None,
689 default: None,
690 inferred_type: None,
691 })))
692 } else {
693 Ok(Expression::Function(Box::new(Function::new(
694 "DATE_PARSE".to_string(),
695 f.args,
696 ))))
697 }
698 }
699
700 "DATE_FORMAT" => Ok(Expression::Function(Box::new(f))),
702
703 "STRFTIME" if f.args.len() >= 2 => {
705 let mut args = f.args;
706 let format = args.remove(0);
708 let date = args.remove(0);
709 Ok(Expression::Function(Box::new(Function::new(
710 "DATE_FORMAT".to_string(),
711 vec![date, format],
712 ))))
713 }
714
715 "TO_CHAR" if f.args.len() >= 2 => {
717 let mut args = f.args;
718 if let Expression::Literal(ref lit) = args[1] {
720 if let Literal::String(ref s) = lit.as_ref() {
721 let converted = Self::oracle_to_presto_format(s);
722 args[1] = Expression::Literal(Box::new(Literal::String(converted)));
723 }
724 }
725 Ok(Expression::Function(Box::new(Function::new(
726 "DATE_FORMAT".to_string(),
727 args,
728 ))))
729 }
730
731 "LEVENSHTEIN" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
733 Function::new("LEVENSHTEIN_DISTANCE".to_string(), f.args),
734 ))),
735
736 "FLATTEN" => Ok(Expression::Function(Box::new(f))),
738
739 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(f))),
741
742 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(f))),
744
745 "GET_JSON_OBJECT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(
747 Function::new("JSON_EXTRACT_SCALAR".to_string(), f.args),
748 ))),
749
750 "COLLECT_LIST" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
752 Function::new("ARRAY_AGG".to_string(), f.args),
753 ))),
754
755 "COLLECT_SET" if !f.args.is_empty() => {
757 let array_agg =
758 Expression::Function(Box::new(Function::new("ARRAY_AGG".to_string(), f.args)));
759 Ok(Expression::Function(Box::new(Function::new(
760 "ARRAY_DISTINCT".to_string(),
761 vec![array_agg],
762 ))))
763 }
764
765 "RLIKE" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
767 "REGEXP_LIKE".to_string(),
768 f.args,
769 )))),
770
771 "REGEXP" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
773 "REGEXP_LIKE".to_string(),
774 f.args,
775 )))),
776
777 "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new(
779 "JSON_PARSE".to_string(),
780 f.args,
781 )))),
782
783 "GET_PATH" if f.args.len() == 2 => {
785 let mut args = f.args;
786 let this = args.remove(0);
787 let path = args.remove(0);
788 let json_path = match &path {
789 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
790 let Literal::String(s) = lit.as_ref() else {
791 unreachable!()
792 };
793 let normalized = if s.starts_with('$') {
794 s.clone()
795 } else if s.starts_with('[') {
796 format!("${}", s)
797 } else {
798 format!("$.{}", s)
799 };
800 Expression::Literal(Box::new(Literal::String(normalized)))
801 }
802 _ => path,
803 };
804 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
805 this,
806 path: json_path,
807 returning: None,
808 arrow_syntax: false,
809 hash_arrow_syntax: false,
810 wrapper_option: None,
811 quotes_option: None,
812 on_scalar_string: false,
813 on_error: None,
814 })))
815 }
816
817 "REGEXP_SUBSTR" if f.args.len() >= 2 => {
819 let mut args = f.args;
820 let subject = args.remove(0);
821 let pattern = args.remove(0);
822 if args.len() >= 4 {
824 let _pos = args.remove(0);
825 let _occ = args.remove(0);
826 let _params = args.remove(0);
827 let group = args.remove(0);
828 Ok(Expression::Function(Box::new(Function::new(
829 "REGEXP_EXTRACT".to_string(),
830 vec![subject, pattern, group],
831 ))))
832 } else {
833 Ok(Expression::Function(Box::new(Function::new(
834 "REGEXP_EXTRACT".to_string(),
835 vec![subject, pattern],
836 ))))
837 }
838 }
839
840 "DATE_PART" if f.args.len() == 2 => {
843 let part_name = match &f.args[0] {
844 Expression::Identifier(id) => Some(id.name.to_uppercase()),
845 Expression::Var(v) => Some(v.this.to_uppercase()),
846 Expression::Column(c) => Some(c.name.name.to_uppercase()),
847 _ => None,
848 };
849 match part_name.as_deref() {
850 Some("EPOCH_SECOND" | "EPOCH_SECONDS") => {
851 let mut args = f.args;
852 let value = args.remove(1);
853 let cast_expr = Expression::Cast(Box::new(Cast {
854 this: value,
855 to: DataType::Timestamp {
856 precision: None,
857 timezone: false,
858 },
859 trailing_comments: Vec::new(),
860 double_colon_syntax: false,
861 format: None,
862 default: None,
863 inferred_type: None,
864 }));
865 Ok(Expression::Function(Box::new(Function::new(
866 "TO_UNIXTIME".to_string(),
867 vec![cast_expr],
868 ))))
869 }
870 Some("EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS") => {
871 let mut args = f.args;
872 let value = args.remove(1);
873 let cast_expr = Expression::Cast(Box::new(Cast {
874 this: value,
875 to: DataType::Timestamp {
876 precision: None,
877 timezone: false,
878 },
879 trailing_comments: Vec::new(),
880 double_colon_syntax: false,
881 format: None,
882 default: None,
883 inferred_type: None,
884 }));
885 let unixtime = Expression::Function(Box::new(Function::new(
886 "TO_UNIXTIME".to_string(),
887 vec![cast_expr],
888 )));
889 Ok(Expression::Mul(Box::new(BinaryOp {
890 left: unixtime,
891 right: Expression::Literal(Box::new(Literal::Number(
892 "1000".to_string(),
893 ))),
894 left_comments: Vec::new(),
895 operator_comments: Vec::new(),
896 trailing_comments: Vec::new(),
897 inferred_type: None,
898 })))
899 }
900 _ => Ok(Expression::Function(Box::new(f))),
901 }
902 }
903
904 "REPLACE" if f.args.len() == 2 => {
906 let mut args = f.args;
907 args.push(Expression::string(""));
908 Ok(Expression::Function(Box::new(Function::new(
909 "REPLACE".to_string(),
910 args,
911 ))))
912 }
913
914 "REGEXP_REPLACE" if f.args.len() == 2 => {
916 let mut args = f.args;
917 args.push(Expression::string(""));
918 Ok(Expression::Function(Box::new(Function::new(
919 "REGEXP_REPLACE".to_string(),
920 args,
921 ))))
922 }
923
924 _ => Ok(Expression::Function(Box::new(f))),
926 }
927 }
928
929 fn transform_aggregate_function(
930 &self,
931 f: Box<crate::expressions::AggregateFunction>,
932 ) -> Result<Expression> {
933 let name_upper = f.name.to_uppercase();
934 match name_upper.as_str() {
935 "COUNT_IF" if !f.args.is_empty() => {
937 let condition = f.args.into_iter().next().unwrap();
938 let case_expr = Expression::Case(Box::new(Case {
939 operand: None,
940 whens: vec![(condition, Expression::number(1))],
941 else_: Some(Expression::number(0)),
942 comments: Vec::new(),
943 inferred_type: None,
944 }));
945 Ok(Expression::Sum(Box::new(AggFunc {
946 ignore_nulls: None,
947 having_max: None,
948 this: case_expr,
949 distinct: f.distinct,
950 filter: f.filter,
951 order_by: Vec::new(),
952 name: None,
953 limit: None,
954 inferred_type: None,
955 })))
956 }
957
958 "ANY_VALUE" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
960 "ARBITRARY".to_string(),
961 f.args,
962 )))),
963
964 "GROUP_CONCAT" if !f.args.is_empty() => {
966 let mut args = f.args;
967 let first = args.remove(0);
968 let separator = args.pop();
969 let array_agg = Expression::Function(Box::new(Function::new(
970 "ARRAY_AGG".to_string(),
971 vec![first],
972 )));
973 let mut join_args = vec![array_agg];
974 if let Some(sep) = separator {
975 join_args.push(sep);
976 }
977 Ok(Expression::Function(Box::new(Function::new(
978 "ARRAY_JOIN".to_string(),
979 join_args,
980 ))))
981 }
982
983 "STRING_AGG" if !f.args.is_empty() => {
985 let mut args = f.args;
986 let first = args.remove(0);
987 let separator = args.pop();
988 let array_agg = Expression::Function(Box::new(Function::new(
989 "ARRAY_AGG".to_string(),
990 vec![first],
991 )));
992 let mut join_args = vec![array_agg];
993 if let Some(sep) = separator {
994 join_args.push(sep);
995 }
996 Ok(Expression::Function(Box::new(Function::new(
997 "ARRAY_JOIN".to_string(),
998 join_args,
999 ))))
1000 }
1001
1002 "LISTAGG" if !f.args.is_empty() => {
1004 let mut args = f.args;
1005 let first = args.remove(0);
1006 let separator = args.pop();
1007 let array_agg = Expression::Function(Box::new(Function::new(
1008 "ARRAY_AGG".to_string(),
1009 vec![first],
1010 )));
1011 let mut join_args = vec![array_agg];
1012 if let Some(sep) = separator {
1013 join_args.push(sep);
1014 }
1015 Ok(Expression::Function(Box::new(Function::new(
1016 "ARRAY_JOIN".to_string(),
1017 join_args,
1018 ))))
1019 }
1020
1021 "VAR" if !f.args.is_empty() => {
1023 Ok(Expression::AggregateFunction(Box::new(AggregateFunction {
1024 name: "VAR_POP".to_string(),
1025 args: f.args,
1026 distinct: f.distinct,
1027 filter: f.filter,
1028 order_by: Vec::new(),
1029 limit: None,
1030 ignore_nulls: None,
1031 inferred_type: None,
1032 })))
1033 }
1034
1035 "VARIANCE" if !f.args.is_empty() => {
1037 Ok(Expression::AggregateFunction(Box::new(AggregateFunction {
1038 name: "VAR_SAMP".to_string(),
1039 args: f.args,
1040 distinct: f.distinct,
1041 filter: f.filter,
1042 order_by: Vec::new(),
1043 limit: None,
1044 ignore_nulls: None,
1045 inferred_type: None,
1046 })))
1047 }
1048
1049 _ => Ok(Expression::AggregateFunction(f)),
1051 }
1052 }
1053
1054 fn transform_cast(&self, c: Cast) -> Result<Expression> {
1055 Ok(Expression::Cast(Box::new(c)))
1057 }
1058}