1use super::{DialectImpl, DialectType};
13use crate::error::Result;
14use crate::expressions::{Alias, BinaryOp, Case, Cast, CeilFunc, Column, DataType, Expression, Function, FunctionParameter, Identifier, Interval, IntervalUnit, IntervalUnitSpec, JsonExtractFunc, JSONPath, JSONPathKey, JSONPathRoot, JSONPathSubscript, Literal, Paren, Struct, Subquery, UnaryFunc, VarArgFunc, WindowFunction};
15use crate::generator::GeneratorConfig;
16use crate::tokens::TokenizerConfig;
17
18fn normalize_json_path(path: Expression) -> Expression {
22 match &path {
23 Expression::Literal(Literal::String(s)) => {
25 if s.starts_with('$') || s.starts_with('/') || s.contains("[#") {
28 return path;
29 }
30 Expression::JSONPath(Box::new(JSONPath {
32 expressions: vec![
33 Expression::JSONPathRoot(JSONPathRoot),
34 Expression::JSONPathKey(Box::new(JSONPathKey {
35 this: Box::new(Expression::Literal(Literal::String(s.clone()))),
36 })),
37 ],
38 escape: None,
39 }))
40 }
41 Expression::Literal(Literal::Number(n)) => {
43 Expression::JSONPath(Box::new(JSONPath {
45 expressions: vec![
46 Expression::JSONPathRoot(JSONPathRoot),
47 Expression::JSONPathSubscript(Box::new(JSONPathSubscript {
48 this: Box::new(Expression::Literal(Literal::Number(n.clone()))),
49 })),
50 ],
51 escape: None,
52 }))
53 }
54 _ => path,
56 }
57}
58
59fn wrap_if_json_arrow(expr: Expression) -> Expression {
63 match &expr {
64 Expression::JsonExtract(f) if f.arrow_syntax => {
65 Expression::Paren(Box::new(Paren {
66 this: expr,
67 trailing_comments: Vec::new(),
68 }))
69 }
70 Expression::JsonExtractScalar(f) if f.arrow_syntax => {
71 Expression::Paren(Box::new(Paren {
72 this: expr,
73 trailing_comments: Vec::new(),
74 }))
75 }
76 _ => expr,
77 }
78}
79
80pub struct DuckDBDialect;
82
83impl DialectImpl for DuckDBDialect {
84 fn dialect_type(&self) -> DialectType {
85 DialectType::DuckDB
86 }
87
88 fn tokenizer_config(&self) -> TokenizerConfig {
89 let mut config = TokenizerConfig::default();
90 config.identifiers.insert('"', '"');
92 config.nested_comments = true;
94 config
95 }
96
97 fn generator_config(&self) -> GeneratorConfig {
98 use crate::generator::IdentifierQuoteStyle;
99 GeneratorConfig {
100 identifier_quote: '"',
101 identifier_quote_style: IdentifierQuoteStyle::DOUBLE_QUOTE,
102 dialect: Some(DialectType::DuckDB),
103 parameter_token: "$",
105 named_placeholder_token: "$",
106 join_hints: false,
107 table_hints: false,
108 query_hints: false,
109 limit_fetch_style: crate::generator::LimitFetchStyle::Limit,
110 struct_delimiter: ("(", ")"),
111 rename_table_with_db: false,
112 nvl2_supported: false,
113 semi_anti_join_with_side: false,
114 tablesample_keywords: "TABLESAMPLE",
115 tablesample_seed_keyword: "REPEATABLE",
116 last_day_supports_date_part: false,
117 json_key_value_pair_sep: ",",
118 ignore_nulls_in_func: true,
119 json_path_bracketed_key_supported: false,
120 supports_create_table_like: false,
121 multi_arg_distinct: false,
122 quantified_no_paren_space: true,
123 can_implement_array_any: true,
124 supports_to_number: false,
125 supports_window_exclude: true,
126 copy_has_into_keyword: false,
127 star_except: "EXCLUDE",
128 pad_fill_pattern_is_required: true,
129 array_concat_is_var_len: false,
130 array_size_dim_required: None,
131 normalize_extract_date_parts: true,
132 supports_like_quantifiers: false,
133 try_supported: true,
135 struct_curly_brace_notation: true,
137 array_bracket_only: true,
139 ..Default::default()
140 }
141 }
142
143 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
144 match expr {
145 Expression::DataType(dt) => self.transform_data_type(dt),
147
148 Expression::BitwiseXor(op) => Ok(Expression::Function(Box::new(crate::expressions::Function::new(
151 "XOR",
152 vec![op.left, op.right],
153 )))),
154
155 Expression::ArrayFunc(mut f) => {
158 f.bracket_notation = true;
159 Ok(Expression::ArrayFunc(f))
160 }
161
162 Expression::IfNull(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
164 expressions: vec![f.this, f.expression],
165 }))),
166
167 Expression::Nvl(f) => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
169 expressions: vec![f.this, f.expression],
170 }))),
171
172 Expression::Coalesce(mut f) => {
174 f.original_name = None;
175 Ok(Expression::Coalesce(f))
176 }
177
178 Expression::GroupConcat(f) => Ok(Expression::ListAgg(Box::new(crate::expressions::ListAggFunc {
180 this: f.this,
181 separator: f.separator,
182 on_overflow: None,
183 order_by: f.order_by,
184 distinct: f.distinct,
185 filter: f.filter,
186 }))),
187
188 Expression::ListAgg(f) => Ok(Expression::ListAgg(f)),
190
191 Expression::StringAgg(f) => Ok(Expression::ListAgg(Box::new(crate::expressions::ListAggFunc {
193 this: f.this,
194 separator: f.separator,
195 on_overflow: None,
196 order_by: f.order_by,
197 distinct: f.distinct,
198 filter: f.filter,
199 }))),
200
201 Expression::TryCast(c) => Ok(Expression::TryCast(c)),
203
204 Expression::SafeCast(c) => Ok(Expression::TryCast(c)),
206
207 Expression::ILike(op) => Ok(Expression::ILike(op)),
209
210 Expression::Explode(f) => Ok(Expression::Unnest(Box::new(
212 crate::expressions::UnnestFunc {
213 this: f.this,
214 expressions: Vec::new(),
215 with_ordinality: false,
216 alias: None,
217 offset_alias: None,
218 },
219 ))),
220
221 Expression::Unnest(f) => Ok(Expression::Unnest(f)),
223
224 Expression::ArrayContainedBy(op) => Ok(Expression::ArrayContainsAll(Box::new(BinaryOp {
227 left: op.right,
228 right: op.left,
229 left_comments: Vec::new(),
230 operator_comments: Vec::new(),
231 trailing_comments: Vec::new(),
232 }))),
233
234 Expression::DateAdd(f) => {
236 let interval_expr = if matches!(&f.interval, Expression::Interval(_)) {
238 f.interval
239 } else {
240 Expression::Interval(Box::new(Interval {
241 this: Some(f.interval),
242 unit: Some(IntervalUnitSpec::Simple { unit: f.unit, use_plural: false }),
243 }))
244 };
245 Ok(Expression::Add(Box::new(BinaryOp {
246 left: f.this,
247 right: interval_expr,
248 left_comments: Vec::new(),
249 operator_comments: Vec::new(),
250 trailing_comments: Vec::new(),
251 })))
252 }
253
254 Expression::DateSub(f) => {
256 let interval_expr = if matches!(&f.interval, Expression::Interval(_)) {
258 f.interval
259 } else {
260 Expression::Interval(Box::new(Interval {
261 this: Some(f.interval),
262 unit: Some(IntervalUnitSpec::Simple { unit: f.unit, use_plural: false }),
263 }))
264 };
265 Ok(Expression::Sub(Box::new(BinaryOp {
266 left: f.this,
267 right: interval_expr,
268 left_comments: Vec::new(),
269 operator_comments: Vec::new(),
270 trailing_comments: Vec::new(),
271 })))
272 }
273
274 Expression::GenerateSeries(mut f) => {
276 if f.start.is_none() && f.end.is_some() {
278 f.start = Some(Box::new(Expression::number(0)));
279 }
280 Ok(Expression::GenerateSeries(f))
281 }
282
283 Expression::ArrayAppend(f) => Ok(Expression::Function(Box::new(Function::new(
286 "LIST_APPEND".to_string(),
287 vec![f.this, f.expression],
288 )))),
289
290 Expression::ArrayPrepend(f) => Ok(Expression::Function(Box::new(Function::new(
292 "LIST_PREPEND".to_string(),
293 vec![f.this, f.expression],
294 )))),
295
296 Expression::ArrayUniqueAgg(f) => Ok(Expression::Function(Box::new(Function::new(
298 "LIST".to_string(),
299 vec![f.this],
300 )))),
301
302 Expression::Split(f) => Ok(Expression::Function(Box::new(Function::new(
304 "STR_SPLIT".to_string(),
305 vec![f.this, f.delimiter],
306 )))),
307
308 Expression::Random(_) => Ok(Expression::Random(crate::expressions::Random)),
310
311 Expression::Rand(r) => {
314 if r.seed.is_some() {
315 Ok(Expression::Rand(r))
316 } else {
317 Ok(Expression::Random(crate::expressions::Random))
318 }
319 }
320
321 Expression::LogicalAnd(f) => Ok(Expression::Function(Box::new(Function::new(
324 "BOOL_AND".to_string(),
325 vec![Expression::Cast(Box::new(crate::expressions::Cast {
326 this: f.this,
327 to: crate::expressions::DataType::Boolean,
328 trailing_comments: Vec::new(),
329 double_colon_syntax: false,
330 format: None,
331 default: None,
332 }))],
333 )))),
334
335 Expression::LogicalOr(f) => Ok(Expression::Function(Box::new(Function::new(
337 "BOOL_OR".to_string(),
338 vec![Expression::Cast(Box::new(crate::expressions::Cast {
339 this: f.this,
340 to: crate::expressions::DataType::Boolean,
341 trailing_comments: Vec::new(),
342 double_colon_syntax: false,
343 format: None,
344 default: None,
345 }))],
346 )))),
347
348 Expression::ApproxDistinct(f) => Ok(Expression::Function(Box::new(Function::new(
351 "APPROX_COUNT_DISTINCT".to_string(),
352 vec![f.this],
353 )))),
354
355 Expression::VarPop(f) => Ok(Expression::Function(Box::new(Function::new(
358 "VAR_POP".to_string(),
359 vec![f.this],
360 )))),
361
362 Expression::DayOfMonth(f) => Ok(Expression::Function(Box::new(Function::new(
365 "DAYOFMONTH".to_string(),
366 vec![f.this],
367 )))),
368
369 Expression::DayOfWeek(f) => Ok(Expression::Function(Box::new(Function::new(
371 "DAYOFWEEK".to_string(),
372 vec![f.this],
373 )))),
374
375 Expression::DayOfWeekIso(f) => Ok(Expression::Function(Box::new(Function::new(
377 "ISODOW".to_string(),
378 vec![f.this],
379 )))),
380
381 Expression::DayOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
383 "DAYOFYEAR".to_string(),
384 vec![f.this],
385 )))),
386
387 Expression::WeekOfYear(f) => Ok(Expression::Function(Box::new(Function::new(
389 "WEEKOFYEAR".to_string(),
390 vec![f.this],
391 )))),
392
393 Expression::TimeStrToUnix(f) => Ok(Expression::Function(Box::new(Function::new(
396 "EPOCH".to_string(),
397 vec![f.this],
398 )))),
399
400 Expression::TimeToUnix(f) => Ok(Expression::Function(Box::new(Function::new(
402 "EPOCH".to_string(),
403 vec![f.this],
404 )))),
405
406 Expression::UnixMicros(f) => Ok(Expression::Function(Box::new(Function::new(
408 "EPOCH_US".to_string(),
409 vec![f.this],
410 )))),
411
412 Expression::UnixMillis(f) => Ok(Expression::Function(Box::new(Function::new(
414 "EPOCH_MS".to_string(),
415 vec![f.this],
416 )))),
417
418 Expression::TimestampDiff(f) => Ok(Expression::Function(Box::new(Function::new(
420 "DATE_DIFF".to_string(),
421 vec![*f.this, *f.expression],
422 )))),
423
424 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
427 "SHA1".to_string(),
428 vec![f.this],
429 )))),
430
431 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
433 "UNHEX".to_string(),
434 vec![*f.this],
435 )))),
436
437 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
439 "UNHEX".to_string(),
440 vec![f.this],
441 )))),
442
443 Expression::SHA2Digest(f) => Ok(Expression::Function(Box::new(Function::new(
445 "UNHEX".to_string(),
446 vec![*f.this],
447 )))),
448
449 Expression::CosineDistance(f) => Ok(Expression::Function(Box::new(Function::new(
452 "LIST_COSINE_DISTANCE".to_string(),
453 vec![*f.this, *f.expression],
454 )))),
455
456 Expression::EuclideanDistance(f) => Ok(Expression::Function(Box::new(Function::new(
458 "LIST_DISTANCE".to_string(),
459 vec![*f.this, *f.expression],
460 )))),
461
462 Expression::IsInf(f) => Ok(Expression::Function(Box::new(Function::new(
465 "ISINF".to_string(),
466 vec![f.this],
467 )))),
468
469 Expression::IsNan(f) => Ok(Expression::Function(Box::new(Function::new(
471 "ISNAN".to_string(),
472 vec![f.this],
473 )))),
474
475 Expression::RegexpLike(f) => Ok(Expression::Function(Box::new(Function::new(
478 "REGEXP_FULL_MATCH".to_string(),
479 vec![f.this, f.pattern],
480 )))),
481
482
483 Expression::CurrentTime(_) => Ok(Expression::Function(Box::new(Function {
486 name: "CURRENT_TIME".to_string(),
487 args: vec![],
488 distinct: false,
489 trailing_comments: vec![],
490 use_bracket_syntax: false,
491 no_parens: true,
492 quoted: false,
493 }))),
494
495 Expression::ReturnStmt(e) => Ok(*e),
498
499 Expression::CommentColumnConstraint(_) => Ok(Expression::Literal(
502 crate::expressions::Literal::String(String::new()),
503 )),
504
505 Expression::JsonExtract(mut f) => {
507 f.arrow_syntax = true;
508 f.path = normalize_json_path(f.path);
509 Ok(Expression::JsonExtract(f))
510 }
511
512 Expression::JsonExtractScalar(mut f) => {
514 f.arrow_syntax = true;
515 f.path = normalize_json_path(f.path);
516 Ok(Expression::JsonExtractScalar(f))
517 }
518
519 Expression::Cardinality(f) => Ok(Expression::Function(Box::new(Function::new(
521 "ARRAY_LENGTH".to_string(),
522 vec![f.this],
523 )))),
524
525 Expression::AddMonths(f) => {
527 let func = Function::new("ADD_MONTHS".to_string(), vec![f.this, f.expression]);
528 self.transform_function(func)
529 }
530
531 Expression::NextDay(f) => {
533 let func = Function::new("NEXT_DAY".to_string(), vec![f.this, f.expression]);
534 self.transform_function(func)
535 }
536
537 Expression::LastDay(f) => {
539 if let Some(unit) = f.unit {
540 let unit_str = match unit {
541 crate::expressions::DateTimeField::Year => "YEAR",
542 crate::expressions::DateTimeField::Month => "MONTH",
543 crate::expressions::DateTimeField::Quarter => "QUARTER",
544 crate::expressions::DateTimeField::Week => "WEEK",
545 crate::expressions::DateTimeField::Day => "DAY",
546 _ => "MONTH",
547 };
548 let func = Function::new("LAST_DAY".to_string(), vec![f.this, Expression::Identifier(Identifier { name: unit_str.to_string(), quoted: false, trailing_comments: Vec::new() })]);
549 self.transform_function(func)
550 } else {
551 Ok(Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![f.this]))))
553 }
554 }
555
556 Expression::Dayname(d) => {
558 Ok(Expression::Function(Box::new(Function::new("STRFTIME".to_string(), vec![
559 *d.this,
560 Expression::Literal(Literal::String("%a".to_string())),
561 ]))))
562 }
563
564 Expression::Monthname(d) => {
566 Ok(Expression::Function(Box::new(Function::new("STRFTIME".to_string(), vec![
567 *d.this,
568 Expression::Literal(Literal::String("%b".to_string())),
569 ]))))
570 }
571
572 Expression::Floor(f) if f.scale.is_some() => {
574 let x = f.this;
575 let scale = f.scale.unwrap();
576 let needs_cast = match &scale {
577 Expression::Literal(Literal::Number(n)) => n.contains('.'),
578 _ => false,
579 };
580 let int_scale = if needs_cast {
581 Expression::Cast(Box::new(Cast { this: scale.clone(), to: DataType::Int { length: None, integer_spelling: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))
582 } else {
583 scale.clone()
584 };
585 let power_10 = Expression::Function(Box::new(Function::new("POWER".to_string(), vec![Expression::number(10), int_scale.clone()])));
586 let x_paren = match &x { Expression::Add(_) | Expression::Sub(_) | Expression::Mul(_) | Expression::Div(_) => Expression::Paren(Box::new(Paren { this: x, trailing_comments: Vec::new() })), _ => x };
587 let multiplied = Expression::Mul(Box::new(BinaryOp { left: x_paren, right: power_10.clone(), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
588 let floored = Expression::Function(Box::new(Function::new("FLOOR".to_string(), vec![multiplied])));
589 let divided = Expression::Div(Box::new(BinaryOp { left: floored, right: power_10, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
590 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![divided, int_scale]))))
591 }
592
593 Expression::Ceil(f) if f.decimals.is_some() => {
595 let x = f.this;
596 let scale = f.decimals.unwrap();
597 let needs_cast = match &scale {
598 Expression::Literal(Literal::Number(n)) => n.contains('.'),
599 _ => false,
600 };
601 let int_scale = if needs_cast {
602 Expression::Cast(Box::new(Cast { this: scale.clone(), to: DataType::Int { length: None, integer_spelling: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))
603 } else {
604 scale.clone()
605 };
606 let power_10 = Expression::Function(Box::new(Function::new("POWER".to_string(), vec![Expression::number(10), int_scale.clone()])));
607 let x_paren = match &x { Expression::Add(_) | Expression::Sub(_) | Expression::Mul(_) | Expression::Div(_) => Expression::Paren(Box::new(Paren { this: x, trailing_comments: Vec::new() })), _ => x };
608 let multiplied = Expression::Mul(Box::new(BinaryOp { left: x_paren, right: power_10.clone(), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
609 let ceiled = Expression::Function(Box::new(Function::new("CEIL".to_string(), vec![multiplied])));
610 let divided = Expression::Div(Box::new(BinaryOp { left: ceiled, right: power_10, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
611 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![divided, int_scale]))))
612 }
613
614 Expression::TableArgument(ta) if ta.prefix.to_uppercase() == "TABLE" => {
619 match ta.this {
621 Expression::Function(ref f) if f.name.to_uppercase() == "RANGE" => {
622 Ok(ta.this)
624 }
625 Expression::Function(ref f) if f.name.to_uppercase() == "GENERATOR" => {
626 let mut rowcount = None;
628 for arg in &f.args {
629 if let Expression::NamedArgument(na) = arg {
630 if na.name.name.to_uppercase() == "ROWCOUNT" {
631 rowcount = Some(na.value.clone());
632 }
633 }
634 }
635 if let Some(n) = rowcount {
636 Ok(Expression::Function(Box::new(Function::new("RANGE".to_string(), vec![n]))))
637 } else {
638 Ok(Expression::TableArgument(ta))
639 }
640 }
641 _ => Ok(Expression::TableArgument(ta)),
642 }
643 }
644
645 Expression::JSONExtract(e) if e.variant_extract.is_some() => {
647 let path = match *e.expression {
648 Expression::Literal(Literal::String(s)) => {
649 let s = Self::convert_bracket_to_quoted_path(&s);
651 let normalized = if s.starts_with('$') {
652 s
653 } else if s.starts_with('[') {
654 format!("${}", s)
655 } else {
656 format!("$.{}", s)
657 };
658 Expression::Literal(Literal::String(normalized))
659 }
660 other => other,
661 };
662 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
663 this: *e.this,
664 path,
665 returning: None,
666 arrow_syntax: true,
667 hash_arrow_syntax: false,
668 wrapper_option: None,
669 quotes_option: None,
670 on_scalar_string: false,
671 on_error: None,
672 })))
673 }
674
675 Expression::Literal(Literal::HexString(s)) => {
677 Ok(Expression::Function(Box::new(Function::new(
678 "UNHEX".to_string(),
679 vec![Expression::Literal(Literal::String(s))],
680 ))))
681 }
682
683 Expression::Literal(Literal::ByteString(s)) => {
685 Ok(Expression::Cast(Box::new(Cast {
686 this: Expression::Literal(Literal::EscapeString(s)),
687 to: DataType::VarBinary { length: None },
688 trailing_comments: Vec::new(),
689 double_colon_syntax: false,
690 format: None,
691 default: None,
692 })))
693 }
694
695 Expression::Cast(mut c) => {
698 if matches!(&c.to, DataType::Decimal { precision: None, .. })
699 && !matches!(&c.this, Expression::IntDiv(_))
700 {
701 c.to = DataType::Decimal {
702 precision: Some(18),
703 scale: Some(3),
704 };
705 }
706 let transformed_this = self.transform_expr(c.this)?;
707 c.this = transformed_this;
708 Ok(Expression::Cast(c))
709 }
710
711 Expression::Function(f) => self.transform_function(*f),
713
714 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
716
717 Expression::WindowFunction(wf) => {
721 if let Expression::Case(case_box) = wf.this {
722 let case = *case_box;
723 if case.whens.len() == 1 && matches!(&case.else_, Some(Expression::AggregateFunction(ref af)) if af.name.to_uppercase() == "CORR") {
725 let over = wf.over;
727 let new_else = case.else_.map(|e| {
728 Expression::WindowFunction(Box::new(WindowFunction { this: e, over: over.clone(), keep: None }))
729 });
730 let new_whens = case.whens.into_iter().map(|(when_cond, when_result)| {
731 let new_cond = if let Expression::Function(func) = when_cond {
733 if func.name.to_uppercase() == "ISNAN" && func.args.len() == 1 {
734 let inner = func.args.into_iter().next().unwrap();
735 let windowed = Expression::WindowFunction(Box::new(WindowFunction { this: inner, over: over.clone(), keep: None }));
736 Expression::Function(Box::new(Function::new("ISNAN".to_string(), vec![windowed])))
737 } else {
738 Expression::Function(func)
739 }
740 } else {
741 when_cond
742 };
743 (new_cond, when_result)
744 }).collect();
745 Ok(Expression::Case(Box::new(Case { operand: None, whens: new_whens, else_: new_else })))
746 } else {
747 Ok(Expression::WindowFunction(Box::new(WindowFunction { this: Expression::Case(Box::new(case)), over: wf.over, keep: wf.keep })))
748 }
749 } else {
750 Ok(Expression::WindowFunction(wf))
751 }
752 }
753
754 Expression::Eq(op) => Ok(Expression::Eq(Box::new(BinaryOp {
761 left: wrap_if_json_arrow(op.left),
762 right: wrap_if_json_arrow(op.right),
763 ..*op
764 }))),
765 Expression::Neq(op) => Ok(Expression::Neq(Box::new(BinaryOp {
766 left: wrap_if_json_arrow(op.left),
767 right: wrap_if_json_arrow(op.right),
768 ..*op
769 }))),
770 Expression::Lt(op) => Ok(Expression::Lt(Box::new(BinaryOp {
771 left: wrap_if_json_arrow(op.left),
772 right: wrap_if_json_arrow(op.right),
773 ..*op
774 }))),
775 Expression::Lte(op) => Ok(Expression::Lte(Box::new(BinaryOp {
776 left: wrap_if_json_arrow(op.left),
777 right: wrap_if_json_arrow(op.right),
778 ..*op
779 }))),
780 Expression::Gt(op) => Ok(Expression::Gt(Box::new(BinaryOp {
781 left: wrap_if_json_arrow(op.left),
782 right: wrap_if_json_arrow(op.right),
783 ..*op
784 }))),
785 Expression::Gte(op) => Ok(Expression::Gte(Box::new(BinaryOp {
786 left: wrap_if_json_arrow(op.left),
787 right: wrap_if_json_arrow(op.right),
788 ..*op
789 }))),
790 Expression::And(op) => Ok(Expression::And(Box::new(BinaryOp {
791 left: wrap_if_json_arrow(op.left),
792 right: wrap_if_json_arrow(op.right),
793 ..*op
794 }))),
795 Expression::Or(op) => Ok(Expression::Or(Box::new(BinaryOp {
796 left: wrap_if_json_arrow(op.left),
797 right: wrap_if_json_arrow(op.right),
798 ..*op
799 }))),
800 Expression::Add(op) => Ok(Expression::Add(Box::new(BinaryOp {
801 left: wrap_if_json_arrow(op.left),
802 right: wrap_if_json_arrow(op.right),
803 ..*op
804 }))),
805 Expression::Sub(op) => Ok(Expression::Sub(Box::new(BinaryOp {
806 left: wrap_if_json_arrow(op.left),
807 right: wrap_if_json_arrow(op.right),
808 ..*op
809 }))),
810 Expression::Mul(op) => Ok(Expression::Mul(Box::new(BinaryOp {
811 left: wrap_if_json_arrow(op.left),
812 right: wrap_if_json_arrow(op.right),
813 ..*op
814 }))),
815 Expression::Div(op) => Ok(Expression::Div(Box::new(BinaryOp {
816 left: wrap_if_json_arrow(op.left),
817 right: wrap_if_json_arrow(op.right),
818 ..*op
819 }))),
820 Expression::Mod(op) => Ok(Expression::Mod(Box::new(BinaryOp {
821 left: wrap_if_json_arrow(op.left),
822 right: wrap_if_json_arrow(op.right),
823 ..*op
824 }))),
825 Expression::Concat(op) => Ok(Expression::Concat(Box::new(BinaryOp {
826 left: wrap_if_json_arrow(op.left),
827 right: wrap_if_json_arrow(op.right),
828 ..*op
829 }))),
830
831 Expression::In(mut i) => {
834 i.this = wrap_if_json_arrow(i.this);
835 if i.not {
836 i.not = false;
838 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
839 this: Expression::In(i),
840 })))
841 } else {
842 Ok(Expression::In(i))
843 }
844 }
845
846 Expression::Not(mut n) => {
848 n.this = wrap_if_json_arrow(n.this);
849 Ok(Expression::Not(n))
850 }
851
852 Expression::WithinGroup(wg) => {
854 match &wg.this {
855 Expression::PercentileCont(p) => {
856 let column = wg.order_by.first().map(|o| o.this.clone()).unwrap_or_else(|| p.this.clone());
857 let percentile = p.percentile.clone();
858 let filter = p.filter.clone();
859 Ok(Expression::AggregateFunction(Box::new(crate::expressions::AggregateFunction {
860 name: "QUANTILE_CONT".to_string(),
861 args: vec![column, percentile],
862 distinct: false,
863 filter,
864 order_by: wg.order_by,
865 limit: None,
866 ignore_nulls: None,
867 })))
868 }
869 Expression::PercentileDisc(p) => {
870 let column = wg.order_by.first().map(|o| o.this.clone()).unwrap_or_else(|| p.this.clone());
871 let percentile = p.percentile.clone();
872 let filter = p.filter.clone();
873 Ok(Expression::AggregateFunction(Box::new(crate::expressions::AggregateFunction {
874 name: "QUANTILE_DISC".to_string(),
875 args: vec![column, percentile],
876 distinct: false,
877 filter,
878 order_by: wg.order_by,
879 limit: None,
880 ignore_nulls: None,
881 })))
882 }
883 Expression::AggregateFunction(af) if af.name == "PERCENTILE_CONT" || af.name == "PERCENTILE_DISC" => {
885 let new_name = if af.name == "PERCENTILE_CONT" { "QUANTILE_CONT" } else { "QUANTILE_DISC" };
886 let column = wg.order_by.first().map(|o| o.this.clone());
887 let quantile = af.args.first().cloned();
888 match (column, quantile) {
889 (Some(col), Some(q)) => {
890 Ok(Expression::AggregateFunction(Box::new(crate::expressions::AggregateFunction {
891 name: new_name.to_string(),
892 args: vec![col, q],
893 distinct: false,
894 filter: af.filter.clone(),
895 order_by: wg.order_by,
896 limit: None,
897 ignore_nulls: None,
898 })))
899 }
900 _ => Ok(Expression::WithinGroup(wg)),
901 }
902 }
903 _ => Ok(Expression::WithinGroup(wg)),
904 }
905 }
906
907 Expression::Column(ref c) if c.name.name.starts_with('@') && c.table.is_none() => {
911 let col_name = &c.name.name[1..]; Ok(Expression::Abs(Box::new(UnaryFunc {
913 this: Expression::Column(Column {
914 name: Identifier::new(col_name),
915 table: None,
916 join_mark: false,
917 trailing_comments: Vec::new(),
918 }),
919 original_name: None,
920 })))
921 }
922
923 Expression::Select(mut select) => {
928 select.expressions = select.expressions.into_iter().map(|e| {
929 match e {
930 Expression::JSONExtract(ref je) if je.variant_extract.is_some() => {
931 let alias_ident = match je.this.as_ref() {
933 Expression::Identifier(ident) => Some(ident.clone()),
934 Expression::Column(col) if col.table.is_none() => Some(col.name.clone()),
935 _ => None,
936 };
937 let value_expr = match je.expression.as_ref() {
938 Expression::Literal(Literal::String(s)) => {
939 if s.contains('.') {
941 let parts: Vec<&str> = s.splitn(2, '.').collect();
943 Some(Expression::Column(Column {
944 name: Identifier::new(parts[1]),
945 table: Some(Identifier::new(parts[0])),
946 join_mark: false,
947 trailing_comments: Vec::new(),
948 }))
949 } else {
950 Some(Expression::Column(Column {
951 name: Identifier::new(s.as_str()),
952 table: None,
953 join_mark: false,
954 trailing_comments: Vec::new(),
955 }))
956 }
957 }
958 _ => None,
959 };
960
961 if let (Some(alias), Some(value)) = (alias_ident, value_expr) {
962 Expression::Alias(Box::new(Alias {
963 this: value,
964 alias,
965 column_aliases: Vec::new(),
966 pre_alias_comments: Vec::new(),
967 trailing_comments: Vec::new(),
968 }))
969 } else {
970 e
971 }
972 }
973 _ => e,
974 }
975 }).collect();
976
977 if let Some(ref mut from) = select.from {
980 if from.expressions.len() > 1 {
981 let mut new_from_exprs = Vec::new();
983 let mut new_joins = Vec::new();
984
985 for (idx, expr) in from.expressions.drain(..).enumerate() {
986 if idx == 0 {
987 new_from_exprs.push(expr);
989 } else {
990 let is_unnest = match &expr {
992 Expression::Unnest(_) => true,
993 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
994 _ => false,
995 };
996
997 if is_unnest {
998 new_joins.push(crate::expressions::Join {
1000 this: expr,
1001 on: Some(Expression::Boolean(crate::expressions::BooleanLiteral { value: true })),
1002 using: Vec::new(),
1003 kind: crate::expressions::JoinKind::Inner,
1004 use_inner_keyword: false,
1005 use_outer_keyword: false,
1006 deferred_condition: false,
1007 join_hint: None,
1008 match_condition: None,
1009 pivots: Vec::new(),
1010 });
1011 } else {
1012 new_from_exprs.push(expr);
1014 }
1015 }
1016 }
1017
1018 from.expressions = new_from_exprs;
1019
1020 new_joins.append(&mut select.joins);
1022 select.joins = new_joins;
1023 }
1024 }
1025
1026 Ok(Expression::Select(select))
1027 }
1028
1029 Expression::Interval(interval) => {
1034 self.transform_interval(*interval)
1035 }
1036
1037 Expression::CreateFunction(mut cf) => {
1039 cf.parameters = cf.parameters.into_iter().map(|p| {
1041 FunctionParameter {
1042 name: p.name,
1043 data_type: DataType::Custom { name: String::new() },
1044 mode: None,
1045 default: p.default,
1046 }
1047 }).collect();
1048
1049 let was_table_return = cf.returns_table_body.is_some()
1052 || matches!(&cf.return_type, Some(DataType::Custom { ref name }) if name == "TABLE");
1053 cf.return_type = None;
1054 if was_table_return {
1055 cf.returns_table_body = Some(String::new());
1057 } else {
1058 cf.returns_table_body = None;
1059 }
1060
1061 Ok(Expression::CreateFunction(cf))
1062 }
1063
1064 Expression::IfFunc(f) => {
1068 Ok(Expression::Case(Box::new(Case {
1069 operand: None,
1070 whens: vec![(f.condition, f.true_value)],
1071 else_: f.false_value,
1072 })))
1073 }
1074
1075 Expression::VarSamp(f) => Ok(Expression::Function(Box::new(Function::new(
1077 "VARIANCE".to_string(),
1078 vec![f.this],
1079 )))),
1080
1081 Expression::Nvl2(f) => {
1083 let condition = Expression::IsNull(Box::new(crate::expressions::IsNull {
1084 this: f.this,
1085 not: true,
1086 postfix_form: false,
1087 }));
1088 Ok(Expression::Case(Box::new(Case {
1089 operand: None,
1090 whens: vec![(condition, f.true_value)],
1091 else_: Some(f.false_value),
1092 })))
1093 }
1094
1095 _ => Ok(expr),
1097 }
1098 }
1099}
1100
1101impl DuckDBDialect {
1102 fn extract_number_value(expr: &Expression) -> Option<f64> {
1104 match expr {
1105 Expression::Literal(Literal::Number(n)) => n.parse::<f64>().ok(),
1106 _ => None,
1107 }
1108 }
1109
1110 fn expr_to_sql(expr: &Expression) -> String {
1112 crate::generator::Generator::sql(expr).unwrap_or_default()
1113 }
1114
1115 fn extract_seed_info(gen: &Expression) -> (String, bool) {
1121 match gen {
1122 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
1123 if func.args.is_empty() {
1124 ("RANDOM()".to_string(), true)
1125 } else {
1126 (Self::expr_to_sql(&func.args[0]), false)
1128 }
1129 }
1130 Expression::Rand(r) => {
1131 if let Some(ref seed) = r.seed {
1132 (Self::expr_to_sql(seed), false)
1134 } else {
1135 ("RANDOM()".to_string(), true)
1136 }
1137 }
1138 Expression::Random(_) => {
1139 ("RANDOM()".to_string(), true)
1140 }
1141 _ => (Self::expr_to_sql(gen), false),
1142 }
1143 }
1144
1145 fn parse_as_subquery(sql: &str) -> Result<Expression> {
1148 let sql_owned = sql.to_string();
1149 let handle = std::thread::Builder::new()
1150 .stack_size(16 * 1024 * 1024) .spawn(move || {
1152 match crate::parser::Parser::parse_sql(&sql_owned) {
1153 Ok(stmts) => {
1154 if let Some(stmt) = stmts.into_iter().next() {
1155 Ok(Expression::Subquery(Box::new(Subquery {
1156 this: stmt,
1157 alias: None,
1158 column_aliases: Vec::new(),
1159 order_by: None,
1160 limit: None,
1161 offset: None,
1162 distribute_by: None,
1163 sort_by: None,
1164 cluster_by: None,
1165 lateral: false,
1166 modifiers_inside: false,
1167 trailing_comments: Vec::new(),
1168 })))
1169 } else {
1170 Err(crate::error::Error::Generate("Failed to parse template SQL".to_string()))
1171 }
1172 }
1173 Err(e) => Err(e),
1174 }
1175 })
1176 .map_err(|e| crate::error::Error::Internal(format!("Failed to spawn parser thread: {}", e)))?;
1177
1178 handle.join()
1179 .map_err(|_| crate::error::Error::Internal("Parser thread panicked".to_string()))?
1180 }
1181
1182 fn convert_bracket_to_quoted_path(path: &str) -> String {
1186 let mut result = String::new();
1187 let mut chars = path.chars().peekable();
1188 while let Some(c) = chars.next() {
1189 if c == '[' && chars.peek() == Some(&'"') {
1190 chars.next(); let mut key = String::new();
1193 while let Some(kc) = chars.next() {
1194 if kc == '"' && chars.peek() == Some(&']') {
1195 chars.next(); break;
1197 }
1198 key.push(kc);
1199 }
1200 if !result.is_empty() && !result.ends_with('.') {
1202 result.push('.');
1203 }
1204 result.push('"');
1205 result.push_str(&key);
1206 result.push('"');
1207 } else {
1208 result.push(c);
1209 }
1210 }
1211 result
1212 }
1213
1214 fn transform_data_type(&self, dt: crate::expressions::DataType) -> Result<Expression> {
1216 use crate::expressions::DataType;
1217 let transformed = match dt {
1218 DataType::Binary { .. } => DataType::VarBinary { length: None },
1220 DataType::Blob => DataType::VarBinary { length: None },
1223 DataType::Char { .. } => DataType::Text,
1225 DataType::VarChar { .. } => DataType::Text,
1227 DataType::Float { precision, scale, .. } => DataType::Float {
1229 precision, scale, real_spelling: true,
1230 },
1231 DataType::JsonB => DataType::Json,
1233 DataType::Custom { ref name } => {
1235 let upper = name.to_uppercase();
1236 match upper.as_str() {
1237 "INT64" | "INT8" => DataType::BigInt { length: None },
1239 "INT32" | "INT4" | "SIGNED" => DataType::Int { length: None, integer_spelling: false },
1241 "INT16" => DataType::SmallInt { length: None },
1243 "INT1" => DataType::TinyInt { length: None },
1245 "HUGEINT" => DataType::Custom { name: "INT128".to_string() },
1247 "UHUGEINT" => DataType::Custom { name: "UINT128".to_string() },
1249 "BPCHAR" => DataType::Text,
1251 "CHARACTER VARYING" | "CHAR VARYING" => DataType::Text,
1253 "FLOAT4" => DataType::Custom { name: "REAL".to_string() },
1255 "LOGICAL" => DataType::Boolean,
1257 "TIMESTAMPNTZ" | "TIMESTAMP_NTZ" => DataType::Timestamp { precision: None, timezone: false },
1259 "TIMESTAMP_US" => DataType::Timestamp { precision: None, timezone: false },
1261 "TIMESTAMPLTZ" | "TIMESTAMP_LTZ" | "TIMESTAMPTZ" | "TIMESTAMP_TZ" => DataType::Timestamp { precision: None, timezone: true },
1263 "DECFLOAT" => DataType::Decimal { precision: Some(38), scale: Some(5) },
1265 _ => dt,
1267 }
1268 }
1269 other => other,
1271 };
1272 Ok(Expression::DataType(transformed))
1273 }
1274
1275 fn transform_interval(&self, interval: Interval) -> Result<Expression> {
1278 if interval.unit.is_some() {
1282 return Ok(Expression::Interval(Box::new(interval)));
1284 }
1285
1286 if let Some(Expression::Literal(Literal::String(ref s))) = interval.this {
1287 if let Some((value, unit)) = Self::parse_interval_string(s) {
1289 return Ok(Expression::Interval(Box::new(Interval {
1291 this: Some(Expression::Literal(Literal::String(value.to_string()))),
1292 unit: Some(IntervalUnitSpec::Simple {
1293 unit,
1294 use_plural: false, }),
1296 })));
1297 }
1298 }
1299
1300 Ok(Expression::Interval(Box::new(interval)))
1302 }
1303
1304 fn parse_interval_string(s: &str) -> Option<(&str, IntervalUnit)> {
1307 let s = s.trim();
1308
1309 let mut num_end = 0;
1312 let mut chars = s.chars().peekable();
1313
1314 if chars.peek() == Some(&'-') {
1316 chars.next();
1317 num_end += 1;
1318 }
1319
1320 while let Some(&c) = chars.peek() {
1322 if c.is_ascii_digit() {
1323 chars.next();
1324 num_end += 1;
1325 } else {
1326 break;
1327 }
1328 }
1329
1330 if chars.peek() == Some(&'.') {
1332 chars.next();
1333 num_end += 1;
1334 while let Some(&c) = chars.peek() {
1335 if c.is_ascii_digit() {
1336 chars.next();
1337 num_end += 1;
1338 } else {
1339 break;
1340 }
1341 }
1342 }
1343
1344 if num_end == 0 || (num_end == 1 && s.starts_with('-')) {
1345 return None; }
1347
1348 let value = &s[..num_end];
1349 let rest = s[num_end..].trim();
1350
1351 if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_alphabetic()) {
1353 return None;
1354 }
1355
1356 let unit = match rest.to_uppercase().as_str() {
1358 "YEAR" | "YEARS" | "Y" => IntervalUnit::Year,
1359 "MONTH" | "MONTHS" | "MON" | "MONS" => IntervalUnit::Month,
1360 "DAY" | "DAYS" | "D" => IntervalUnit::Day,
1361 "HOUR" | "HOURS" | "H" | "HR" | "HRS" => IntervalUnit::Hour,
1362 "MINUTE" | "MINUTES" | "MIN" | "MINS" | "M" => IntervalUnit::Minute,
1363 "SECOND" | "SECONDS" | "SEC" | "SECS" | "S" => IntervalUnit::Second,
1364 "MILLISECOND" | "MILLISECONDS" | "MS" => IntervalUnit::Millisecond,
1365 "MICROSECOND" | "MICROSECONDS" | "US" => IntervalUnit::Microsecond,
1366 "QUARTER" | "QUARTERS" | "Q" => IntervalUnit::Quarter,
1367 "WEEK" | "WEEKS" | "W" => IntervalUnit::Week,
1368 _ => return None, };
1370
1371 Some((value, unit))
1372 }
1373
1374 fn transform_function(&self, f: Function) -> Result<Expression> {
1375 let name_upper = f.name.to_uppercase();
1376 match name_upper.as_str() {
1377 "IFNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
1379 expressions: f.args,
1380 }))),
1381
1382 "NVL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
1384 expressions: f.args,
1385 }))),
1386
1387 "ISNULL" if f.args.len() == 2 => Ok(Expression::Coalesce(Box::new(VarArgFunc { original_name: None,
1389 expressions: f.args,
1390 }))),
1391
1392 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1394 Function::new("LISTAGG".to_string(), f.args),
1395 ))),
1396
1397 "LISTAGG" => Ok(Expression::Function(Box::new(f))),
1399
1400 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
1402 Function::new("LISTAGG".to_string(), f.args),
1403 ))),
1404
1405 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
1407 "SUBSTRING".to_string(),
1408 f.args,
1409 )))),
1410
1411 "FLATTEN" => Ok(Expression::Function(Box::new(Function::new(
1413 "UNNEST".to_string(),
1414 f.args,
1415 )))),
1416
1417 "EXPLODE" => Ok(Expression::Function(Box::new(Function::new(
1419 "UNNEST".to_string(),
1420 f.args,
1421 )))),
1422
1423 "NOW" => Ok(Expression::CurrentTimestamp(
1425 crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
1426 )),
1427
1428 "GETDATE" => Ok(Expression::CurrentTimestamp(
1430 crate::expressions::CurrentTimestamp { precision: None, sysdate: false },
1431 )),
1432
1433 "CURRENT_DATE" => Ok(Expression::CurrentDate(crate::expressions::CurrentDate)),
1435
1436 "TO_DATE" if f.args.len() == 1 => {
1438 let arg = f.args.into_iter().next().unwrap();
1439 Ok(Expression::Cast(Box::new(Cast {
1440 this: arg,
1441 to: DataType::Date,
1442 trailing_comments: Vec::new(),
1443 double_colon_syntax: false,
1444 format: None,
1445 default: None,
1446 })))
1447 }
1448
1449 "DATE_FORMAT" if f.args.len() >= 2 => {
1453 let mut args = f.args;
1454 args[1] = Self::convert_format_to_duckdb(&args[1]);
1455 Ok(Expression::Function(Box::new(Function::new(
1456 "STRFTIME".to_string(),
1457 args,
1458 ))))
1459 }
1460
1461 "DATE_PARSE" if f.args.len() >= 2 => {
1463 let mut args = f.args;
1464 args[1] = Self::convert_format_to_duckdb(&args[1]);
1465 Ok(Expression::Function(Box::new(Function::new(
1466 "STRPTIME".to_string(),
1467 args,
1468 ))))
1469 }
1470
1471 "FORMAT_DATE" if f.args.len() >= 2 => {
1473 let mut args = f.args;
1474 args[1] = Self::convert_format_to_duckdb(&args[1]);
1475 Ok(Expression::Function(Box::new(Function::new(
1476 "STRFTIME".to_string(),
1477 args,
1478 ))))
1479 }
1480
1481 "TO_CHAR" if f.args.len() >= 2 => {
1483 let mut args = f.args;
1484 args[1] = Self::convert_format_to_duckdb(&args[1]);
1485 Ok(Expression::Function(Box::new(Function::new(
1486 "STRFTIME".to_string(),
1487 args,
1488 ))))
1489 }
1490
1491 "EPOCH_MS" => Ok(Expression::Function(Box::new(f))),
1493
1494 "EPOCH" => Ok(Expression::Function(Box::new(f))),
1496
1497 "FROM_UNIXTIME" if !f.args.is_empty() => {
1499 Ok(Expression::Function(Box::new(Function::new(
1500 "TO_TIMESTAMP".to_string(),
1501 f.args,
1502 ))))
1503 }
1504
1505 "UNIX_TIMESTAMP" => Ok(Expression::Function(Box::new(Function::new(
1507 "EPOCH".to_string(),
1508 f.args,
1509 )))),
1510
1511 "JSON_EXTRACT" if f.args.len() == 2 => {
1513 let mut args = f.args;
1514 let path = args.pop().unwrap();
1515 let this = args.pop().unwrap();
1516 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
1517 this,
1518 path,
1519 returning: None,
1520 arrow_syntax: true,
1521 hash_arrow_syntax: false,
1522 wrapper_option: None,
1523 quotes_option: None,
1524 on_scalar_string: false,
1525 on_error: None,
1526 })))
1527 }
1528
1529 "JSON_EXTRACT_STRING" if f.args.len() == 2 => {
1531 let mut args = f.args;
1532 let path = args.pop().unwrap();
1533 let this = args.pop().unwrap();
1534 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
1535 this,
1536 path,
1537 returning: None,
1538 arrow_syntax: true,
1539 hash_arrow_syntax: false,
1540 wrapper_option: None,
1541 quotes_option: None,
1542 on_scalar_string: false,
1543 on_error: None,
1544 })))
1545 }
1546
1547 "ARRAY_CONSTRUCT" => Ok(Expression::Function(Box::new(Function::new(
1549 "list_value".to_string(),
1550 f.args,
1551 )))),
1552
1553 "ARRAY" => {
1556 let has_query = f.args.iter().any(|a| matches!(a, Expression::Subquery(_) | Expression::Select(_)));
1558 if has_query {
1559 Ok(Expression::Function(Box::new(Function::new(
1561 "ARRAY".to_string(),
1562 f.args,
1563 ))))
1564 } else {
1565 Ok(Expression::Function(Box::new(Function::new(
1566 "list_value".to_string(),
1567 f.args,
1568 ))))
1569 }
1570 }
1571
1572 "LIST_VALUE" => Ok(Expression::Array(Box::new(crate::expressions::Array {
1574 expressions: f.args,
1575 }))),
1576
1577 "ARRAY_AGG" => Ok(Expression::Function(Box::new(Function::new(
1579 "list".to_string(),
1580 f.args,
1581 )))),
1582
1583 "LIST_CONTAINS" | "ARRAY_CONTAINS" => Ok(Expression::Function(Box::new(Function::new(
1585 "ARRAY_CONTAINS".to_string(),
1586 f.args,
1587 )))),
1588
1589 "ARRAY_SIZE" | "CARDINALITY" => {
1591 Ok(Expression::Function(Box::new(Function::new(
1592 "ARRAY_LENGTH".to_string(),
1593 f.args,
1594 ))))
1595 }
1596
1597 "LEN" if f.args.len() == 1 => Ok(Expression::Length(Box::new(UnaryFunc::new(
1599 f.args.into_iter().next().unwrap(),
1600 )))),
1601
1602 "CEILING" if f.args.len() == 1 => Ok(Expression::Ceil(Box::new(CeilFunc {
1604 this: f.args.into_iter().next().unwrap(),
1605 decimals: None,
1606 to: None,
1607 }))),
1608
1609 "LOGICAL_OR" if f.args.len() == 1 => {
1611 let arg = f.args.into_iter().next().unwrap();
1612 Ok(Expression::Function(Box::new(Function::new(
1613 "BOOL_OR".to_string(),
1614 vec![Expression::Cast(Box::new(crate::expressions::Cast {
1615 this: arg,
1616 to: crate::expressions::DataType::Boolean,
1617 trailing_comments: Vec::new(),
1618 double_colon_syntax: false,
1619 format: None,
1620 default: None,
1621 }))],
1622 ))))
1623 }
1624
1625 "LOGICAL_AND" if f.args.len() == 1 => {
1627 let arg = f.args.into_iter().next().unwrap();
1628 Ok(Expression::Function(Box::new(Function::new(
1629 "BOOL_AND".to_string(),
1630 vec![Expression::Cast(Box::new(crate::expressions::Cast {
1631 this: arg,
1632 to: crate::expressions::DataType::Boolean,
1633 trailing_comments: Vec::new(),
1634 double_colon_syntax: false,
1635 format: None,
1636 default: None,
1637 }))],
1638 ))))
1639 }
1640
1641 "REGEXP_LIKE" => Ok(Expression::Function(Box::new(Function::new(
1643 "REGEXP_MATCHES".to_string(),
1644 f.args,
1645 )))),
1646
1647 "POSITION" => Ok(Expression::Function(Box::new(f))),
1649
1650 "SPLIT" => Ok(Expression::Function(Box::new(Function::new(
1652 "STR_SPLIT".to_string(),
1653 f.args,
1654 )))),
1655
1656 "STRING_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
1658 "STR_SPLIT".to_string(),
1659 f.args,
1660 )))),
1661
1662 "STRTOK_TO_ARRAY" => Ok(Expression::Function(Box::new(Function::new(
1664 "STR_SPLIT".to_string(),
1665 f.args,
1666 )))),
1667
1668 "REGEXP_SPLIT" => Ok(Expression::Function(Box::new(Function::new(
1670 "STR_SPLIT_REGEX".to_string(),
1671 f.args,
1672 )))),
1673
1674 "EDITDIST3" => Ok(Expression::Function(Box::new(Function::new(
1676 "LEVENSHTEIN".to_string(),
1677 f.args,
1678 )))),
1679
1680 "JSON_EXTRACT_PATH" if f.args.len() >= 2 => {
1682 let mut args = f.args;
1683 let this = args.remove(0);
1684 let path = args.remove(0);
1685 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
1686 this,
1687 path,
1688 returning: None,
1689 arrow_syntax: true,
1690 hash_arrow_syntax: false,
1691 wrapper_option: None,
1692 quotes_option: None,
1693 on_scalar_string: false,
1694 on_error: None,
1695 })))
1696 }
1697
1698 "JSON_EXTRACT_PATH_TEXT" if f.args.len() >= 2 => {
1700 let mut args = f.args;
1701 let this = args.remove(0);
1702 let path = args.remove(0);
1703 Ok(Expression::JsonExtractScalar(Box::new(JsonExtractFunc {
1704 this,
1705 path,
1706 returning: None,
1707 arrow_syntax: true,
1708 hash_arrow_syntax: false,
1709 wrapper_option: None,
1710 quotes_option: None,
1711 on_scalar_string: false,
1712 on_error: None,
1713 })))
1714 }
1715
1716 "DATE_ADD" if f.args.len() == 2 => {
1718 let mut args = f.args;
1719 let date = args.remove(0);
1720 let interval = args.remove(0);
1721 Ok(Expression::Add(Box::new(BinaryOp {
1722 left: date,
1723 right: interval,
1724 left_comments: Vec::new(),
1725 operator_comments: Vec::new(),
1726 trailing_comments: Vec::new(),
1727 })))
1728 }
1729
1730 "DATE_SUB" if f.args.len() == 2 => {
1732 let mut args = f.args;
1733 let date = args.remove(0);
1734 let interval = args.remove(0);
1735 Ok(Expression::Sub(Box::new(BinaryOp {
1736 left: date,
1737 right: interval,
1738 left_comments: Vec::new(),
1739 operator_comments: Vec::new(),
1740 trailing_comments: Vec::new(),
1741 })))
1742 }
1743
1744 "RANGE" if f.args.len() == 1 => {
1746 let mut new_args = vec![Expression::number(0)];
1747 new_args.extend(f.args);
1748 Ok(Expression::Function(Box::new(Function::new(
1749 "RANGE".to_string(),
1750 new_args,
1751 ))))
1752 }
1753
1754 "GENERATE_SERIES" if f.args.len() == 1 => {
1756 let mut new_args = vec![Expression::number(0)];
1757 new_args.extend(f.args);
1758 Ok(Expression::Function(Box::new(Function::new(
1759 "GENERATE_SERIES".to_string(),
1760 new_args,
1761 ))))
1762 }
1763
1764 "REGEXP_EXTRACT" if f.args.len() == 3 => {
1767 let drop_group = match &f.args[2] {
1769 Expression::Literal(Literal::Number(n)) => n == "0",
1770 _ => false,
1771 };
1772 if drop_group {
1773 Ok(Expression::Function(Box::new(Function::new(
1774 "REGEXP_EXTRACT".to_string(),
1775 vec![f.args[0].clone(), f.args[1].clone()],
1776 ))))
1777 } else {
1778 Ok(Expression::Function(Box::new(f)))
1779 }
1780 }
1781
1782 "STRUCT_PACK" => {
1784 let mut fields = Vec::new();
1785 for arg in f.args {
1786 match arg {
1787 Expression::NamedArgument(na) => {
1788 fields.push((Some(na.name.name.clone()), na.value));
1789 }
1790 other => {
1792 fields.push((None, other));
1793 }
1794 }
1795 }
1796 Ok(Expression::Struct(Box::new(Struct { fields })))
1797 }
1798
1799 "REPLACE" if f.args.len() == 2 => {
1801 let mut args = f.args;
1802 args.push(Expression::Literal(Literal::String(String::new())));
1803 Ok(Expression::Function(Box::new(Function::new(
1804 "REPLACE".to_string(),
1805 args,
1806 ))))
1807 }
1808
1809 "TO_UNIXTIME" => Ok(Expression::Function(Box::new(Function::new(
1811 "EPOCH".to_string(),
1812 f.args,
1813 )))),
1814
1815 "FROM_ISO8601_TIMESTAMP" if f.args.len() == 1 => {
1817 use crate::expressions::{Cast, DataType};
1818 Ok(Expression::Cast(Box::new(Cast {
1819 this: f.args.into_iter().next().unwrap(),
1820 to: DataType::Timestamp { precision: None, timezone: true },
1821 trailing_comments: Vec::new(),
1822 double_colon_syntax: false,
1823 format: None,
1824 default: None,
1825 })))
1826 }
1827
1828 "APPROX_DISTINCT" => {
1830 let args = if f.args.len() > 1 {
1832 vec![f.args.into_iter().next().unwrap()]
1833 } else {
1834 f.args
1835 };
1836 Ok(Expression::Function(Box::new(Function::new(
1837 "APPROX_COUNT_DISTINCT".to_string(),
1838 args,
1839 ))))
1840 }
1841
1842 "ARRAY_SORT" => {
1844 let args = vec![f.args.into_iter().next().unwrap()];
1845 Ok(Expression::Function(Box::new(Function::new(
1846 "ARRAY_SORT".to_string(),
1847 args,
1848 )))
1849 )
1850 }
1851
1852 "TO_UTF8" => Ok(Expression::Function(Box::new(Function::new(
1854 "ENCODE".to_string(),
1855 f.args,
1856 )))),
1857
1858 "FROM_UTF8" => Ok(Expression::Function(Box::new(Function::new(
1860 "DECODE".to_string(),
1861 f.args,
1862 )))),
1863
1864 "ARBITRARY" => Ok(Expression::Function(Box::new(Function::new(
1866 "ANY_VALUE".to_string(),
1867 f.args,
1868 )))),
1869
1870 "MAX_BY" => Ok(Expression::Function(Box::new(Function::new(
1872 "ARG_MAX".to_string(),
1873 f.args,
1874 )))),
1875
1876 "MIN_BY" => Ok(Expression::Function(Box::new(Function::new(
1878 "ARG_MIN".to_string(),
1879 f.args,
1880 )))),
1881
1882 "IFF" if f.args.len() == 3 => {
1885 let mut args = f.args;
1886 let cond = args.remove(0);
1887 let true_val = args.remove(0);
1888 let false_val = args.remove(0);
1889 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(cond, true_val)], else_: Some(false_val) })))
1890 }
1891 "SKEW" => Ok(Expression::Function(Box::new(Function::new("SKEWNESS".to_string(), f.args)))),
1892 "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new("VARIANCE".to_string(), f.args)))),
1893 "VARIANCE_POP" => Ok(Expression::Function(Box::new(Function::new("VAR_POP".to_string(), f.args)))),
1894 "REGR_VALX" if f.args.len() == 2 => {
1895 let mut args = f.args; let y = args.remove(0); let x = args.remove(0);
1896 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::IsNull(Box::new(crate::expressions::IsNull { this: y, not: false, postfix_form: false })), Expression::Cast(Box::new(Cast { this: Expression::Null(crate::expressions::Null), to: DataType::Double { precision: None, scale: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))], else_: Some(x) })))
1897 }
1898 "REGR_VALY" if f.args.len() == 2 => {
1899 let mut args = f.args; let y = args.remove(0); let x = args.remove(0);
1900 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::IsNull(Box::new(crate::expressions::IsNull { this: x, not: false, postfix_form: false })), Expression::Cast(Box::new(Cast { this: Expression::Null(crate::expressions::Null), to: DataType::Double { precision: None, scale: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))], else_: Some(y) })))
1901 }
1902 "BOOLNOT" if f.args.len() == 1 => {
1903 let arg = f.args.into_iter().next().unwrap();
1904 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp { this: Expression::Paren(Box::new(Paren { this: arg, trailing_comments: Vec::new() })) })))
1905 }
1906 "BITMAP_BIT_POSITION" if f.args.len() == 1 => {
1907 let n = f.args.into_iter().next().unwrap();
1908 let case_expr = Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::Gt(Box::new(BinaryOp { left: n.clone(), right: Expression::number(0), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::Sub(Box::new(BinaryOp { left: n.clone(), right: Expression::number(1), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))], else_: Some(Expression::Abs(Box::new(UnaryFunc { this: n, original_name: None }))) }));
1909 Ok(Expression::Mod(Box::new(BinaryOp { left: Expression::Paren(Box::new(Paren { this: case_expr, trailing_comments: Vec::new() })), right: Expression::number(32768), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
1910 }
1911 "GREATEST" | "LEAST" => Ok(Expression::Function(Box::new(f))),
1913 "GREATEST_IGNORE_NULLS" => Ok(Expression::Greatest(Box::new(VarArgFunc { expressions: f.args, original_name: None }))),
1914 "LEAST_IGNORE_NULLS" => Ok(Expression::Least(Box::new(VarArgFunc { expressions: f.args, original_name: None }))),
1915 "PARSE_JSON" => Ok(Expression::Function(Box::new(Function::new("JSON".to_string(), f.args)))),
1916 "OBJECT_CONSTRUCT_KEEP_NULL" => {
1917 Ok(Expression::Function(Box::new(Function::new("JSON_OBJECT".to_string(), f.args))))
1919 }
1920 "OBJECT_CONSTRUCT" => {
1921 let args = f.args;
1923 if args.is_empty() {
1924 Ok(Expression::Function(Box::new(Function::new("STRUCT_PACK".to_string(), vec![]))))
1926 } else {
1927 let mut fields = Vec::new();
1929 let mut i = 0;
1930 while i + 1 < args.len() {
1931 let key = &args[i];
1932 let value = args[i + 1].clone();
1933 let key_name = match key {
1934 Expression::Literal(Literal::String(s)) => Some(s.clone()),
1935 _ => None,
1936 };
1937 fields.push((key_name, value));
1938 i += 2;
1939 }
1940 Ok(Expression::Struct(Box::new(Struct { fields })))
1941 }
1942 }
1943 "IS_NULL_VALUE" if f.args.len() == 1 => {
1944 let arg = f.args.into_iter().next().unwrap();
1945 Ok(Expression::Eq(Box::new(BinaryOp { left: Expression::Function(Box::new(Function::new("JSON_TYPE".to_string(), vec![arg]))), right: Expression::Literal(Literal::String("NULL".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
1946 }
1947 "TRY_TO_DOUBLE" | "TRY_TO_NUMBER" | "TRY_TO_NUMERIC" | "TRY_TO_DECIMAL" if f.args.len() == 1 => {
1948 let arg = f.args.into_iter().next().unwrap();
1949 Ok(Expression::TryCast(Box::new(Cast { this: arg, to: DataType::Double { precision: None, scale: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
1950 }
1951 "TRY_TO_TIME" if f.args.len() == 1 => {
1952 let arg = f.args.into_iter().next().unwrap();
1953 Ok(Expression::TryCast(Box::new(Cast { this: arg, to: DataType::Time { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
1954 }
1955 "TRY_TO_TIME" if f.args.len() == 2 => {
1956 let mut args = f.args; let value = args.remove(0);
1957 let fmt = self.convert_snowflake_time_format(args.remove(0));
1958 Ok(Expression::TryCast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("TRY_STRPTIME".to_string(), vec![value, fmt]))), to: DataType::Time { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
1959 }
1960 "TRY_TO_TIMESTAMP" if f.args.len() == 1 => {
1961 let arg = f.args.into_iter().next().unwrap();
1962 Ok(Expression::TryCast(Box::new(Cast { this: arg, to: DataType::Timestamp { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
1963 }
1964 "TRY_TO_TIMESTAMP" if f.args.len() == 2 => {
1965 let mut args = f.args; let value = args.remove(0);
1966 let fmt = self.convert_snowflake_time_format(args.remove(0));
1967 Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("TRY_STRPTIME".to_string(), vec![value, fmt]))), to: DataType::Timestamp { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
1968 }
1969 "TRY_TO_DATE" if f.args.len() == 1 => {
1970 let arg = f.args.into_iter().next().unwrap();
1971 Ok(Expression::TryCast(Box::new(Cast { this: arg, to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
1972 }
1973 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Function(Box::new(Function::new("ISODOW".to_string(), f.args)))),
1974 "YEAROFWEEK" | "YEAROFWEEKISO" if f.args.len() == 1 => {
1975 let arg = f.args.into_iter().next().unwrap();
1976 Ok(Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: arg, field: crate::expressions::DateTimeField::Custom("ISOYEAR".to_string()) })))
1977 }
1978 "WEEKISO" => Ok(Expression::Function(Box::new(Function::new("WEEKOFYEAR".to_string(), f.args)))),
1979 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 3 => {
1980 let args_ref = &f.args;
1981 let all_in_range = if let (
1983 Some(h_val), Some(m_val), Some(s_val)
1984 ) = (
1985 Self::extract_number_value(&args_ref[0]),
1986 Self::extract_number_value(&args_ref[1]),
1987 Self::extract_number_value(&args_ref[2]),
1988 ) {
1989 h_val >= 0.0 && h_val < 24.0 && m_val >= 0.0 && m_val < 60.0 && s_val >= 0.0 && s_val < 60.0
1990 } else {
1991 false
1992 };
1993 if all_in_range {
1994 Ok(Expression::Function(Box::new(Function::new("MAKE_TIME".to_string(), f.args))))
1996 } else {
1997 let mut args = f.args; let h = args.remove(0); let m = args.remove(0); let s = args.remove(0);
2000 let seconds_expr = Expression::Add(Box::new(BinaryOp { left: Expression::Add(Box::new(BinaryOp { left: Expression::Paren(Box::new(Paren { this: Expression::Mul(Box::new(BinaryOp { left: h, right: Expression::number(3600), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), trailing_comments: Vec::new() })), right: Expression::Paren(Box::new(Paren { this: Expression::Mul(Box::new(BinaryOp { left: m, right: Expression::number(60), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), trailing_comments: Vec::new() })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), right: s, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2001 let base_time = Expression::Cast(Box::new(Cast { this: Expression::Literal(Literal::String("00:00:00".to_string())), to: DataType::Time { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2002 Ok(Expression::Add(Box::new(BinaryOp { left: base_time, right: Expression::Interval(Box::new(Interval { this: Some(Expression::Paren(Box::new(crate::expressions::Paren { this: seconds_expr, trailing_comments: Vec::new() }))), unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Second, use_plural: false }) })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2003 }
2004 }
2005 "TIME_FROM_PARTS" | "TIMEFROMPARTS" if f.args.len() == 4 => {
2006 let mut args = f.args; let h = args.remove(0); let m = args.remove(0); let s = args.remove(0); let ns = args.remove(0);
2007 let seconds_expr = Expression::Add(Box::new(BinaryOp { left: Expression::Add(Box::new(BinaryOp { left: Expression::Add(Box::new(BinaryOp { left: Expression::Paren(Box::new(Paren { this: Expression::Mul(Box::new(BinaryOp { left: h, right: Expression::number(3600), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), trailing_comments: Vec::new() })), right: Expression::Paren(Box::new(Paren { this: Expression::Mul(Box::new(BinaryOp { left: m, right: Expression::number(60), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), trailing_comments: Vec::new() })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), right: s, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), right: Expression::Paren(Box::new(Paren { this: Expression::Div(Box::new(BinaryOp { left: ns, right: Expression::Literal(Literal::Number("1000000000.0".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), trailing_comments: Vec::new() })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2008 let base_time = Expression::Cast(Box::new(Cast { this: Expression::Literal(Literal::String("00:00:00".to_string())), to: DataType::Time { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2009 Ok(Expression::Add(Box::new(BinaryOp { left: base_time, right: Expression::Interval(Box::new(Interval { this: Some(Expression::Paren(Box::new(crate::expressions::Paren { this: seconds_expr, trailing_comments: Vec::new() }))), unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Second, use_plural: false }) })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2010 }
2011 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" if f.args.len() == 6 => Ok(Expression::Function(Box::new(Function::new("MAKE_TIMESTAMP".to_string(), f.args)))),
2012 "TIMESTAMP_FROM_PARTS" | "TIMESTAMPFROMPARTS" | "TIMESTAMP_NTZ_FROM_PARTS" if f.args.len() == 2 => {
2013 let mut args = f.args; let d = args.remove(0); let t = args.remove(0);
2014 Ok(Expression::Add(Box::new(BinaryOp { left: d, right: t, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2015 }
2016 "TIMESTAMP_LTZ_FROM_PARTS" if f.args.len() == 6 => {
2017 Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("MAKE_TIMESTAMP".to_string(), f.args))), to: DataType::Timestamp { precision: None, timezone: true }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
2018 }
2019 "TIMESTAMP_TZ_FROM_PARTS" if f.args.len() == 8 => {
2020 let mut args = f.args;
2021 let ts_args = vec![args.remove(0), args.remove(0), args.remove(0), args.remove(0), args.remove(0), args.remove(0)];
2022 let _nano = args.remove(0); let tz = args.remove(0);
2023 Ok(Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone { this: Expression::Function(Box::new(Function::new("MAKE_TIMESTAMP".to_string(), ts_args))), zone: tz })))
2024 }
2025 "BOOLAND_AGG" if f.args.len() == 1 => {
2026 let arg = f.args.into_iter().next().unwrap();
2027 Ok(Expression::Function(Box::new(Function::new("BOOL_AND".to_string(), vec![Expression::Cast(Box::new(Cast { this: arg, to: DataType::Boolean, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))]))))
2028 }
2029 "BOOLOR_AGG" if f.args.len() == 1 => {
2030 let arg = f.args.into_iter().next().unwrap();
2031 Ok(Expression::Function(Box::new(Function::new("BOOL_OR".to_string(), vec![Expression::Cast(Box::new(Cast { this: arg, to: DataType::Boolean, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))]))))
2032 }
2033 "NVL2" if f.args.len() == 3 => {
2034 let mut args = f.args; let a = args.remove(0); let b = args.remove(0); let c = args.remove(0);
2035 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::Not(Box::new(crate::expressions::UnaryOp { this: Expression::IsNull(Box::new(crate::expressions::IsNull { this: a, not: false, postfix_form: false })) })), b)], else_: Some(c) })))
2036 }
2037 "EQUAL_NULL" if f.args.len() == 2 => {
2038 let mut args = f.args; let a = args.remove(0); let b = args.remove(0);
2039 Ok(Expression::NullSafeEq(Box::new(BinaryOp { left: a, right: b, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2040 }
2041 "EDITDISTANCE" => Ok(Expression::Function(Box::new(Function::new("LEVENSHTEIN".to_string(), f.args)))),
2042 "BITAND" if f.args.len() == 2 => {
2043 let mut args = f.args;
2044 let left = args.remove(0);
2045 let right = args.remove(0);
2046 let wrap = |e: Expression| -> Expression {
2048 match &e {
2049 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) =>
2050 Expression::Paren(Box::new(Paren { this: e, trailing_comments: Vec::new() })),
2051 _ => e,
2052 }
2053 };
2054 Ok(Expression::BitwiseAnd(Box::new(BinaryOp { left: wrap(left), right: wrap(right), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2055 }
2056 "BITOR" if f.args.len() == 2 => {
2057 let mut args = f.args;
2058 let left = args.remove(0);
2059 let right = args.remove(0);
2060 let wrap = |e: Expression| -> Expression {
2062 match &e {
2063 Expression::BitwiseLeftShift(_) | Expression::BitwiseRightShift(_) =>
2064 Expression::Paren(Box::new(Paren { this: e, trailing_comments: Vec::new() })),
2065 _ => e,
2066 }
2067 };
2068 Ok(Expression::BitwiseOr(Box::new(BinaryOp { left: wrap(left), right: wrap(right), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2069 }
2070 "BITXOR" if f.args.len() == 2 => { let mut args = f.args; Ok(Expression::BitwiseXor(Box::new(BinaryOp { left: args.remove(0), right: args.remove(0), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))) }
2071 "BITNOT" if f.args.len() == 1 => { let arg = f.args.into_iter().next().unwrap(); Ok(Expression::BitwiseNot(Box::new(crate::expressions::UnaryOp { this: Expression::Paren(Box::new(Paren { this: arg, trailing_comments: Vec::new() })) }))) }
2072 "BITSHIFTLEFT" if f.args.len() == 2 => {
2073 let mut args = f.args; let a = args.remove(0); let b = args.remove(0);
2074 let is_binary = if let Expression::Cast(ref c) = a {
2076 matches!(&c.to, DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob)
2077 || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
2078 } else { false };
2079 if is_binary {
2080 let cast_to_bit = Expression::Cast(Box::new(Cast { this: a, to: DataType::Custom { name: "BIT".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2082 let shift = Expression::BitwiseLeftShift(Box::new(BinaryOp { left: cast_to_bit, right: b, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2083 Ok(Expression::Cast(Box::new(Cast { this: shift, to: DataType::Custom { name: "BLOB".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
2084 } else {
2085 Ok(Expression::BitwiseLeftShift(Box::new(BinaryOp { left: Expression::Cast(Box::new(Cast { this: a, to: DataType::Custom { name: "INT128".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })), right: b, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2086 }
2087 }
2088 "BITSHIFTRIGHT" if f.args.len() == 2 => {
2089 let mut args = f.args; let a = args.remove(0); let b = args.remove(0);
2090 let is_binary = if let Expression::Cast(ref c) = a {
2092 matches!(&c.to, DataType::Binary { .. } | DataType::VarBinary { .. } | DataType::Blob)
2093 || matches!(&c.to, DataType::Custom { name } if name == "BLOB")
2094 } else { false };
2095 if is_binary {
2096 let cast_to_bit = Expression::Cast(Box::new(Cast { this: a, to: DataType::Custom { name: "BIT".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2098 let shift = Expression::BitwiseRightShift(Box::new(BinaryOp { left: cast_to_bit, right: b, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2099 Ok(Expression::Cast(Box::new(Cast { this: shift, to: DataType::Custom { name: "BLOB".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
2100 } else {
2101 Ok(Expression::BitwiseRightShift(Box::new(BinaryOp { left: Expression::Cast(Box::new(Cast { this: a, to: DataType::Custom { name: "INT128".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })), right: b, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
2102 }
2103 }
2104 "SQUARE" if f.args.len() == 1 => { let arg = f.args.into_iter().next().unwrap(); Ok(Expression::Function(Box::new(Function::new("POWER".to_string(), vec![arg, Expression::number(2)])))) }
2105 "UUID_STRING" => Ok(Expression::Function(Box::new(Function::new("UUID".to_string(), vec![])))),
2106 "ENDSWITH" => Ok(Expression::Function(Box::new(Function::new("ENDS_WITH".to_string(), f.args)))),
2107 "REGEXP_REPLACE" if f.args.len() == 2 => {
2111 let mut args = f.args; args.push(Expression::Literal(Literal::String(String::new())));
2113 Ok(Expression::Function(Box::new(Function::new("REGEXP_REPLACE".to_string(), args))))
2114 }
2115 "DIV0" if f.args.len() == 2 => {
2116 let mut args = f.args; let a = args.remove(0); let b = args.remove(0);
2117 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::And(Box::new(BinaryOp { left: Expression::Eq(Box::new(BinaryOp { left: b.clone(), right: Expression::number(0), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), right: Expression::Not(Box::new(crate::expressions::UnaryOp { this: Expression::IsNull(Box::new(crate::expressions::IsNull { this: a.clone(), not: false, postfix_form: false })) })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::number(0))], else_: Some(Expression::Div(Box::new(BinaryOp { left: a, right: b, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))) })))
2118 }
2119 "DIV0NULL" if f.args.len() == 2 => {
2120 let mut args = f.args; let a = args.remove(0); let b = args.remove(0);
2121 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::Or(Box::new(BinaryOp { left: Expression::Eq(Box::new(BinaryOp { left: b.clone(), right: Expression::number(0), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), right: Expression::IsNull(Box::new(crate::expressions::IsNull { this: b.clone(), not: false, postfix_form: false })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::number(0))], else_: Some(Expression::Div(Box::new(BinaryOp { left: a, right: b, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))) })))
2122 }
2123 "ZEROIFNULL" if f.args.len() == 1 => {
2124 let x = f.args.into_iter().next().unwrap();
2125 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::IsNull(Box::new(crate::expressions::IsNull { this: x.clone(), not: false, postfix_form: false })), Expression::number(0))], else_: Some(x) })))
2126 }
2127 "NULLIFZERO" if f.args.len() == 1 => {
2128 let x = f.args.into_iter().next().unwrap();
2129 Ok(Expression::Case(Box::new(Case { operand: None, whens: vec![(Expression::Eq(Box::new(BinaryOp { left: x.clone(), right: Expression::number(0), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::Null(crate::expressions::Null))], else_: Some(x) })))
2130 }
2131 "TO_DOUBLE" if f.args.len() == 1 => { let arg = f.args.into_iter().next().unwrap(); Ok(Expression::Cast(Box::new(Cast { this: arg, to: DataType::Double { precision: None, scale: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))) }
2132 "DATE" if f.args.len() == 1 => { let arg = f.args.into_iter().next().unwrap(); Ok(Expression::Cast(Box::new(Cast { this: arg, to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))) }
2133 "DATE" if f.args.len() == 2 => {
2134 let mut args = f.args; let value = args.remove(0); let fmt = self.convert_snowflake_date_format(args.remove(0));
2135 Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("STRPTIME".to_string(), vec![value, fmt]))), to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
2136 }
2137 "SYSDATE" => Ok(Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone { this: Expression::CurrentTimestamp(crate::expressions::CurrentTimestamp { precision: None, sysdate: false }), zone: Expression::Literal(Literal::String("UTC".to_string())) }))),
2138 "HEX_DECODE_BINARY" => Ok(Expression::Function(Box::new(Function::new("UNHEX".to_string(), f.args)))),
2139 "CONVERT_TIMEZONE" if f.args.len() == 3 => {
2140 let mut args = f.args; let src_tz = args.remove(0); let tgt_tz = args.remove(0); let ts = args.remove(0);
2141 let cast_ts = Expression::Cast(Box::new(Cast { this: ts, to: DataType::Timestamp { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2142 Ok(Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone { this: Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone { this: cast_ts, zone: src_tz })), zone: tgt_tz })))
2143 }
2144 "CONVERT_TIMEZONE" if f.args.len() == 2 => {
2145 let mut args = f.args; let tgt_tz = args.remove(0); let ts = args.remove(0);
2146 let cast_ts = Expression::Cast(Box::new(Cast { this: ts, to: DataType::Timestamp { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2147 Ok(Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone { this: cast_ts, zone: tgt_tz })))
2148 }
2149 "DATE_PART" | "DATEPART" if f.args.len() == 2 => self.transform_date_part(f.args),
2150 "DATEADD" | "TIMEADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
2151 "TIMESTAMPADD" if f.args.len() == 3 => self.transform_dateadd(f.args),
2152 "DATEDIFF" | "TIMEDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
2153 "TIMESTAMPDIFF" if f.args.len() == 3 => self.transform_datediff(f.args),
2154 "CORR" if f.args.len() == 2 => {
2155 Ok(Expression::Function(Box::new(f)))
2157 }
2158 "TO_TIMESTAMP" | "TO_TIMESTAMP_NTZ" if f.args.len() == 2 => {
2159 let mut args = f.args; let value = args.remove(0); let second_arg = args.remove(0);
2160 match &second_arg {
2161 Expression::Literal(Literal::Number(_)) => Ok(Expression::AtTimeZone(Box::new(crate::expressions::AtTimeZone { this: Expression::Function(Box::new(Function::new("TO_TIMESTAMP".to_string(), vec![Expression::Div(Box::new(BinaryOp { left: value, right: Expression::Function(Box::new(Function::new("POWER".to_string(), vec![Expression::number(10), second_arg]))), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))]))), zone: Expression::Literal(Literal::String("UTC".to_string())) }))),
2162 _ => { let fmt = self.convert_snowflake_time_format(second_arg); Ok(Expression::Function(Box::new(Function::new("STRPTIME".to_string(), vec![value, fmt])))) }
2163 }
2164 }
2165 "TO_TIME" if f.args.len() == 1 => { let arg = f.args.into_iter().next().unwrap(); Ok(Expression::Cast(Box::new(Cast { this: arg, to: DataType::Time { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))) }
2166 "TO_TIME" if f.args.len() == 2 => {
2167 let mut args = f.args; let value = args.remove(0); let fmt = self.convert_snowflake_time_format(args.remove(0));
2168 Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("STRPTIME".to_string(), vec![value, fmt]))), to: DataType::Time { precision: None, timezone: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
2169 }
2170 "TO_DATE" if f.args.len() == 2 => {
2171 let mut args = f.args; let value = args.remove(0); let fmt = self.convert_snowflake_date_format(args.remove(0));
2172 Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("STRPTIME".to_string(), vec![value, fmt]))), to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
2173 }
2174 "SAFE_DIVIDE" if f.args.len() == 2 => {
2178 let mut args = f.args;
2179 let x = args.remove(0);
2180 let y = args.remove(0);
2181 Ok(Expression::Case(Box::new(Case {
2182 operand: None,
2183 whens: vec![(
2184 Expression::Neq(Box::new(BinaryOp {
2185 left: y.clone(),
2186 right: Expression::number(0),
2187 left_comments: Vec::new(),
2188 operator_comments: Vec::new(),
2189 trailing_comments: Vec::new(),
2190 })),
2191 Expression::Div(Box::new(BinaryOp {
2192 left: x,
2193 right: y,
2194 left_comments: Vec::new(),
2195 operator_comments: Vec::new(),
2196 trailing_comments: Vec::new(),
2197 })),
2198 )],
2199 else_: Some(Expression::Null(crate::expressions::Null)),
2200 })))
2201 }
2202
2203 "TO_HEX" if f.args.len() == 1 => {
2205 let arg = f.args.into_iter().next().unwrap();
2206 Ok(Expression::Lower(Box::new(UnaryFunc::new(
2207 Expression::Function(Box::new(Function::new("HEX".to_string(), vec![arg]))),
2208 ))))
2209 }
2210
2211 "EDIT_DISTANCE" if f.args.len() >= 2 => {
2213 let mut args = f.args;
2215 let a = args.remove(0);
2216 let b = args.remove(0);
2217 Ok(Expression::Function(Box::new(Function::new(
2218 "LEVENSHTEIN".to_string(),
2219 vec![a, b],
2220 ))))
2221 }
2222
2223 "UNIX_DATE" if f.args.len() == 1 => {
2225 let arg = f.args.into_iter().next().unwrap();
2226 Ok(Expression::Function(Box::new(Function::new(
2227 "DATE_DIFF".to_string(),
2228 vec![
2229 Expression::Literal(Literal::String("DAY".to_string())),
2230 Expression::Cast(Box::new(Cast {
2231 this: Expression::Literal(Literal::String("1970-01-01".to_string())),
2232 to: DataType::Date,
2233 trailing_comments: Vec::new(),
2234 double_colon_syntax: false,
2235 format: None,
2236 default: None,
2237 })),
2238 arg,
2239 ],
2240 ))))
2241 }
2242
2243 "TIMESTAMP" if f.args.len() == 1 => {
2245 let arg = f.args.into_iter().next().unwrap();
2246 Ok(Expression::Cast(Box::new(Cast {
2247 this: arg,
2248 to: DataType::Custom { name: "TIMESTAMPTZ".to_string() },
2249 trailing_comments: Vec::new(),
2250 double_colon_syntax: false,
2251 format: None,
2252 default: None,
2253 })))
2254 }
2255
2256 "TIME" if f.args.len() == 3 => {
2258 Ok(Expression::Function(Box::new(Function::new(
2259 "MAKE_TIME".to_string(),
2260 f.args,
2261 ))))
2262 }
2263
2264 "DATE" if f.args.len() == 3 => {
2266 Ok(Expression::Function(Box::new(Function::new(
2267 "MAKE_DATE".to_string(),
2268 f.args,
2269 ))))
2270 }
2271
2272 "DATETIME" if f.args.len() == 6 => {
2274 Ok(Expression::Function(Box::new(Function::new(
2275 "MAKE_TIMESTAMP".to_string(),
2276 f.args,
2277 ))))
2278 }
2279
2280 "PARSE_TIMESTAMP" if f.args.len() >= 2 => {
2282 let mut args = f.args;
2283 let fmt = args.remove(0);
2284 let value = args.remove(0);
2285 let duckdb_fmt = self.convert_bq_to_strptime_format(fmt);
2287 Ok(Expression::Function(Box::new(Function::new(
2288 "STRPTIME".to_string(),
2289 vec![value, duckdb_fmt],
2290 ))))
2291 }
2292
2293 "BOOLAND" if f.args.len() == 2 => {
2295 let mut args = f.args;
2296 let a = args.remove(0);
2297 let b = args.remove(0);
2298 Ok(Expression::Paren(Box::new(Paren {
2299 this: Expression::And(Box::new(BinaryOp {
2300 left: Expression::Paren(Box::new(Paren { this: a, trailing_comments: Vec::new() })),
2301 right: Expression::Paren(Box::new(Paren { this: b, trailing_comments: Vec::new() })),
2302 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2303 })),
2304 trailing_comments: Vec::new(),
2305 })))
2306 }
2307
2308 "BOOLOR" if f.args.len() == 2 => {
2310 let mut args = f.args;
2311 let a = args.remove(0);
2312 let b = args.remove(0);
2313 Ok(Expression::Paren(Box::new(Paren {
2314 this: Expression::Or(Box::new(BinaryOp {
2315 left: Expression::Paren(Box::new(Paren { this: a, trailing_comments: Vec::new() })),
2316 right: Expression::Paren(Box::new(Paren { this: b, trailing_comments: Vec::new() })),
2317 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2318 })),
2319 trailing_comments: Vec::new(),
2320 })))
2321 }
2322
2323 "DECODE" if f.args.len() >= 3 => {
2325 let mut args = f.args;
2326 let expr = args.remove(0);
2327 let mut whens = Vec::new();
2328 let mut else_expr = None;
2329 while args.len() >= 2 {
2330 let search = args.remove(0);
2331 let result = args.remove(0);
2332 let needs_paren_expr = matches!(&expr, Expression::Eq(_) | Expression::Neq(_) | Expression::Gt(_) | Expression::Lt(_) | Expression::Gte(_) | Expression::Lte(_) | Expression::And(_) | Expression::Or(_));
2334 let needs_paren_search = matches!(&search, Expression::Eq(_) | Expression::Neq(_) | Expression::Gt(_) | Expression::Lt(_) | Expression::Gte(_) | Expression::Lte(_) | Expression::And(_) | Expression::Or(_));
2335 let eq_left = if needs_paren_expr { Expression::Paren(Box::new(Paren { this: expr.clone(), trailing_comments: Vec::new() })) } else { expr.clone() };
2336 let eq_right = if needs_paren_search { Expression::Paren(Box::new(Paren { this: search.clone(), trailing_comments: Vec::new() })) } else { search.clone() };
2337 let is_null_expr = if needs_paren_expr { Expression::Paren(Box::new(Paren { this: expr.clone(), trailing_comments: Vec::new() })) } else { expr.clone() };
2338 let is_null_search = if needs_paren_search { Expression::Paren(Box::new(Paren { this: search.clone(), trailing_comments: Vec::new() })) } else { search.clone() };
2339 let condition = Expression::Or(Box::new(BinaryOp {
2340 left: Expression::Eq(Box::new(BinaryOp { left: eq_left, right: eq_right, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })),
2341 right: Expression::Paren(Box::new(Paren {
2342 this: Expression::And(Box::new(BinaryOp {
2343 left: Expression::IsNull(Box::new(crate::expressions::IsNull { this: is_null_expr, not: false, postfix_form: false })),
2344 right: Expression::IsNull(Box::new(crate::expressions::IsNull { this: is_null_search, not: false, postfix_form: false })),
2345 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2346 })),
2347 trailing_comments: Vec::new(),
2348 })),
2349 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2350 }));
2351 whens.push((condition, result));
2352 }
2353 if !args.is_empty() {
2354 else_expr = Some(args.remove(0));
2355 }
2356 Ok(Expression::Case(Box::new(Case { operand: None, whens, else_: else_expr })))
2357 }
2358
2359 "TRY_TO_BOOLEAN" if f.args.len() == 1 => {
2361 let arg = f.args.into_iter().next().unwrap();
2362 let cast_text = Expression::Cast(Box::new(Cast { this: arg.clone(), to: DataType::Text, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2363 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
2364 Ok(Expression::Case(Box::new(Case {
2365 operand: None,
2366 whens: vec![
2367 (Expression::Eq(Box::new(BinaryOp { left: upper_text.clone(), right: Expression::Literal(Literal::String("ON".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::Boolean(crate::expressions::BooleanLiteral { value: true })),
2368 (Expression::Eq(Box::new(BinaryOp { left: upper_text, right: Expression::Literal(Literal::String("OFF".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::Boolean(crate::expressions::BooleanLiteral { value: false })),
2369 ],
2370 else_: Some(Expression::TryCast(Box::new(Cast { this: arg, to: DataType::Boolean, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))),
2371 })))
2372 }
2373
2374 "TO_BOOLEAN" if f.args.len() == 1 => {
2376 let arg = f.args.into_iter().next().unwrap();
2377 let cast_text = Expression::Cast(Box::new(Cast { this: arg.clone(), to: DataType::Text, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }));
2378 let upper_text = Expression::Upper(Box::new(UnaryFunc::new(cast_text)));
2379 Ok(Expression::Case(Box::new(Case {
2380 operand: None,
2381 whens: vec![
2382 (Expression::Eq(Box::new(BinaryOp { left: upper_text.clone(), right: Expression::Literal(Literal::String("ON".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::Boolean(crate::expressions::BooleanLiteral { value: true })),
2383 (Expression::Eq(Box::new(BinaryOp { left: upper_text, right: Expression::Literal(Literal::String("OFF".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })), Expression::Boolean(crate::expressions::BooleanLiteral { value: false })),
2384 (Expression::Or(Box::new(BinaryOp {
2385 left: Expression::Function(Box::new(Function::new("ISNAN".to_string(), vec![Expression::TryCast(Box::new(Cast { this: arg.clone(), to: DataType::Custom { name: "REAL".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))]))),
2386 right: Expression::Function(Box::new(Function::new("ISINF".to_string(), vec![Expression::TryCast(Box::new(Cast { this: arg.clone(), to: DataType::Custom { name: "REAL".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))]))),
2387 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2388 })), Expression::Function(Box::new(Function::new("ERROR".to_string(), vec![Expression::Literal(Literal::String("TO_BOOLEAN: Non-numeric values NaN and INF are not supported".to_string()))])))),
2389 ],
2390 else_: Some(Expression::Cast(Box::new(Cast { this: arg, to: DataType::Boolean, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))),
2391 })))
2392 }
2393
2394 "OBJECT_INSERT" if f.args.len() == 3 => {
2397 let mut args = f.args;
2398 let obj = args.remove(0);
2399 let key = args.remove(0);
2400 let value = args.remove(0);
2401 let key_name = match &key {
2403 Expression::Literal(Literal::String(s)) => s.clone(),
2404 _ => "key".to_string(),
2405 };
2406 let named_arg = Expression::NamedArgument(Box::new(crate::expressions::NamedArgument {
2407 name: Identifier::new(&key_name),
2408 value,
2409 separator: crate::expressions::NamedArgSeparator::ColonEq,
2410 }));
2411 let is_empty_struct = match &obj {
2413 Expression::Struct(s) if s.fields.is_empty() => true,
2414 Expression::Function(f) => {
2415 let n = f.name.to_uppercase();
2416 (n == "STRUCT_PACK" || n == "OBJECT_CONSTRUCT") && f.args.is_empty()
2417 }
2418 _ => false,
2419 };
2420 if is_empty_struct {
2421 Ok(Expression::Function(Box::new(Function::new(
2423 "STRUCT_PACK".to_string(),
2424 vec![named_arg],
2425 ))))
2426 } else {
2427 Ok(Expression::Function(Box::new(Function::new(
2428 "STRUCT_INSERT".to_string(),
2429 vec![obj, named_arg],
2430 ))))
2431 }
2432 }
2433
2434 "GET" if f.args.len() == 2 => {
2436 let mut args = f.args;
2437 let this = args.remove(0);
2438 let key = args.remove(0);
2439 match &key {
2440 Expression::Literal(Literal::String(s)) => {
2442 let json_path = format!("$.{}", s);
2443 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2444 this,
2445 path: Expression::Literal(Literal::String(json_path)),
2446 returning: None,
2447 arrow_syntax: true,
2448 hash_arrow_syntax: false,
2449 wrapper_option: None,
2450 quotes_option: None,
2451 on_scalar_string: false,
2452 on_error: None,
2453 })))
2454 }
2455 Expression::Literal(Literal::Number(n)) => {
2459 let idx: i64 = n.parse().unwrap_or(0);
2460 let is_map = matches!(&this, Expression::Cast(c) if matches!(c.to, DataType::Map { .. }));
2461 let index_val = if is_map { idx } else { idx + 1 };
2462 Ok(Expression::Subscript(Box::new(crate::expressions::Subscript {
2463 this,
2464 index: Expression::number(index_val),
2465 })))
2466 }
2467 _ => {
2468 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2470 this,
2471 path: Expression::JSONPath(Box::new(JSONPath { expressions: vec![Expression::JSONPathRoot(JSONPathRoot), Expression::JSONPathKey(Box::new(JSONPathKey { this: Box::new(key) }))], escape: None })),
2472 returning: None,
2473 arrow_syntax: true,
2474 hash_arrow_syntax: false,
2475 wrapper_option: None,
2476 quotes_option: None,
2477 on_scalar_string: false,
2478 on_error: None,
2479 })))
2480 }
2481 }
2482 }
2483
2484 "GET_PATH" if f.args.len() == 2 => {
2486 let mut args = f.args;
2487 let this = args.remove(0);
2488 let path = args.remove(0);
2489 let json_path = match &path {
2491 Expression::Literal(Literal::String(s)) => {
2492 let s = Self::convert_bracket_to_quoted_path(s);
2494 let normalized = if s.starts_with('$') {
2496 s
2497 } else if s.starts_with('[') {
2498 format!("${}", s)
2499 } else {
2500 format!("$.{}", s)
2501 };
2502 Expression::Literal(Literal::String(normalized))
2503 }
2504 _ => path,
2505 };
2506 Ok(Expression::JsonExtract(Box::new(JsonExtractFunc {
2507 this,
2508 path: json_path,
2509 returning: None,
2510 arrow_syntax: true,
2511 hash_arrow_syntax: false,
2512 wrapper_option: None,
2513 quotes_option: None,
2514 on_scalar_string: false,
2515 on_error: None,
2516 })))
2517 }
2518
2519 "BASE64_ENCODE" if f.args.len() == 1 => {
2521 Ok(Expression::Function(Box::new(Function::new("TO_BASE64".to_string(), f.args))))
2522 }
2523
2524 "BASE64_ENCODE" if f.args.len() >= 2 => {
2526 let mut args = f.args;
2527 let x = args.remove(0);
2528 let line_len = args.remove(0);
2529 let line_len_str = match &line_len {
2530 Expression::Literal(Literal::Number(n)) => n.clone(),
2531 _ => "76".to_string(),
2532 };
2533 let to_base64 = Expression::Function(Box::new(Function::new("TO_BASE64".to_string(), vec![x])));
2534 let pattern = format!("(.{{{}}})", line_len_str);
2535 let chr_10 = Expression::Function(Box::new(Function::new("CHR".to_string(), vec![Expression::number(10)])));
2536 let replacement = Expression::Concat(Box::new(BinaryOp {
2537 left: Expression::Literal(Literal::String("\\1".to_string())),
2538 right: chr_10.clone(),
2539 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2540 }));
2541 let regexp_replace = Expression::Function(Box::new(Function::new("REGEXP_REPLACE".to_string(), vec![
2542 to_base64,
2543 Expression::Literal(Literal::String(pattern)),
2544 replacement,
2545 Expression::Literal(Literal::String("g".to_string())),
2546 ])));
2547 Ok(Expression::Function(Box::new(Function::new("RTRIM".to_string(), vec![regexp_replace, chr_10]))))
2548 }
2549
2550 "TRY_TO_DATE" if f.args.len() == 2 => {
2552 let mut args = f.args;
2553 let value = args.remove(0);
2554 let fmt = self.convert_snowflake_date_format(args.remove(0));
2555 Ok(Expression::Cast(Box::new(Cast {
2556 this: Expression::Cast(Box::new(Cast {
2557 this: Expression::Function(Box::new(Function::new("TRY_STRPTIME".to_string(), vec![value, fmt]))),
2558 to: DataType::Timestamp { precision: None, timezone: false },
2559 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
2560 })),
2561 to: DataType::Date,
2562 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
2563 })))
2564 }
2565
2566 "REGEXP_REPLACE" if f.args.len() == 4 => {
2569 let is_snowflake_position = matches!(&f.args[3], Expression::Literal(Literal::Number(_)));
2570 if is_snowflake_position {
2571 let mut args = f.args;
2573 let subject = args.remove(0);
2574 let pattern = args.remove(0);
2575 let replacement = args.remove(0);
2576 Ok(Expression::Function(Box::new(Function::new(
2577 "REGEXP_REPLACE".to_string(),
2578 vec![subject, pattern, replacement, Expression::Literal(Literal::String("g".to_string()))],
2579 ))))
2580 } else {
2581 Ok(Expression::Function(Box::new(f)))
2583 }
2584 }
2585
2586 "REGEXP_REPLACE" if f.args.len() >= 5 => {
2588 let mut args = f.args;
2589 let subject = args.remove(0);
2590 let pattern = args.remove(0);
2591 let replacement = args.remove(0);
2592 let _position = args.remove(0);
2593 let occurrence = if !args.is_empty() { Some(args.remove(0)) } else { None };
2594 let params = if !args.is_empty() { Some(args.remove(0)) } else { None };
2595
2596 let mut flags = String::new();
2597 if let Some(Expression::Literal(Literal::String(p))) = ¶ms {
2598 flags = p.clone();
2599 }
2600 let is_global = match &occurrence {
2601 Some(Expression::Literal(Literal::Number(n))) => n == "0",
2602 None => true,
2603 _ => false,
2604 };
2605 if is_global && !flags.contains('g') {
2606 flags.push('g');
2607 }
2608
2609 Ok(Expression::Function(Box::new(Function::new(
2610 "REGEXP_REPLACE".to_string(),
2611 vec![subject, pattern, replacement, Expression::Literal(Literal::String(flags))],
2612 ))))
2613 }
2614
2615 "ROUND" if f.args.iter().any(|a| matches!(a, Expression::NamedArgument(_))) => {
2617 let mut expr_val = None;
2618 let mut scale_val = None;
2619 let mut rounding_mode = None;
2620 for arg in &f.args {
2621 if let Expression::NamedArgument(na) = arg {
2622 match na.name.name.to_uppercase().as_str() {
2623 "EXPR" => expr_val = Some(na.value.clone()),
2624 "SCALE" => scale_val = Some(na.value.clone()),
2625 "ROUNDING_MODE" => rounding_mode = Some(na.value.clone()),
2626 _ => {}
2627 }
2628 }
2629 }
2630 if let Some(expr) = expr_val {
2631 let scale = scale_val.unwrap_or(Expression::number(0));
2632 let is_half_to_even = match &rounding_mode {
2633 Some(Expression::Literal(Literal::String(s))) => s == "HALF_TO_EVEN",
2634 _ => false,
2635 };
2636 if is_half_to_even {
2637 Ok(Expression::Function(Box::new(Function::new("ROUND_EVEN".to_string(), vec![expr, scale]))))
2638 } else {
2639 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![expr, scale]))))
2640 }
2641 } else {
2642 Ok(Expression::Function(Box::new(f)))
2643 }
2644 }
2645
2646 "ROUND" if f.args.len() == 3 => {
2649 let mut args = f.args;
2650 let x = args.remove(0);
2651 let scale = args.remove(0);
2652 let mode = args.remove(0);
2653 let is_half_to_even = match &mode {
2654 Expression::Literal(Literal::String(s)) => s == "HALF_TO_EVEN",
2655 _ => false,
2656 };
2657 if is_half_to_even {
2658 Ok(Expression::Function(Box::new(Function::new("ROUND_EVEN".to_string(), vec![x, scale]))))
2659 } else {
2660 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![x, scale]))))
2662 }
2663 }
2664
2665 "ROUND" if f.args.len() == 2 => {
2667 let mut args = f.args;
2668 let x = args.remove(0);
2669 let scale = args.remove(0);
2670 let needs_cast = match &scale {
2671 Expression::Literal(Literal::Number(n)) => n.contains('.'),
2672 Expression::Cast(_) => {
2673 true
2675 }
2676 _ => false,
2677 };
2678 if needs_cast {
2679 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![x, Expression::Cast(Box::new(Cast { this: scale, to: DataType::Int { length: None, integer_spelling: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))]))))
2680 } else {
2681 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![x, scale]))))
2682 }
2683 }
2684
2685 "FLOOR" if f.args.len() == 2 => {
2687 let mut args = f.args;
2688 let x = args.remove(0);
2689 let scale = args.remove(0);
2690 let needs_cast = match &scale {
2692 Expression::Literal(Literal::Number(n)) => n.contains('.'),
2693 _ => false,
2694 };
2695 let int_scale = if needs_cast {
2696 Expression::Cast(Box::new(Cast { this: scale.clone(), to: DataType::Int { length: None, integer_spelling: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))
2697 } else {
2698 scale.clone()
2699 };
2700 let power_10 = Expression::Function(Box::new(Function::new("POWER".to_string(), vec![Expression::number(10), int_scale.clone()])));
2701 let x_paren = match &x { Expression::Add(_) | Expression::Sub(_) | Expression::Mul(_) | Expression::Div(_) => Expression::Paren(Box::new(Paren { this: x, trailing_comments: Vec::new() })), _ => x };
2702 let multiplied = Expression::Mul(Box::new(BinaryOp { left: x_paren, right: power_10.clone(), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2703 let floored = Expression::Function(Box::new(Function::new("FLOOR".to_string(), vec![multiplied])));
2704 let divided = Expression::Div(Box::new(BinaryOp { left: floored, right: power_10, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2705 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![divided, int_scale]))))
2706 }
2707
2708 "CEIL" | "CEILING" if f.args.len() == 2 => {
2710 let mut args = f.args;
2711 let x = args.remove(0);
2712 let scale = args.remove(0);
2713 let needs_cast = match &scale {
2714 Expression::Literal(Literal::Number(n)) => n.contains('.'),
2715 _ => false,
2716 };
2717 let int_scale = if needs_cast {
2718 Expression::Cast(Box::new(Cast { this: scale.clone(), to: DataType::Int { length: None, integer_spelling: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))
2719 } else {
2720 scale.clone()
2721 };
2722 let power_10 = Expression::Function(Box::new(Function::new("POWER".to_string(), vec![Expression::number(10), int_scale.clone()])));
2723 let x_paren = match &x { Expression::Add(_) | Expression::Sub(_) | Expression::Mul(_) | Expression::Div(_) => Expression::Paren(Box::new(Paren { this: x, trailing_comments: Vec::new() })), _ => x };
2724 let multiplied = Expression::Mul(Box::new(BinaryOp { left: x_paren, right: power_10.clone(), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2725 let ceiled = Expression::Function(Box::new(Function::new("CEIL".to_string(), vec![multiplied])));
2726 let divided = Expression::Div(Box::new(BinaryOp { left: ceiled, right: power_10, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2727 Ok(Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![divided, int_scale]))))
2728 }
2729
2730 "ADD_MONTHS" if f.args.len() == 2 => {
2732 let mut args = f.args;
2733 let date_expr_raw = args.remove(0);
2734 let months_expr = args.remove(0);
2735
2736 let was_string_literal = matches!(&date_expr_raw, Expression::Literal(Literal::String(_)));
2738
2739 let date_expr = match &date_expr_raw {
2741 Expression::Literal(Literal::String(_)) => {
2742 Expression::Cast(Box::new(Cast {
2743 this: date_expr_raw,
2744 to: DataType::Timestamp { precision: None, timezone: false },
2745 trailing_comments: Vec::new(),
2746 double_colon_syntax: false,
2747 format: None,
2748 default: None,
2749 }))
2750 }
2751 _ => date_expr_raw,
2752 };
2753
2754 let date_type = if was_string_literal {
2757 None
2758 } else {
2759 match &date_expr {
2760 Expression::Cast(c) => Some(c.to.clone()),
2761 _ => None,
2762 }
2763 };
2764
2765 let is_non_integer_months = match &months_expr {
2767 Expression::Literal(Literal::Number(n)) => n.contains('.'),
2768 Expression::Neg(_) => {
2769 if let Expression::Neg(um) = &months_expr {
2770 matches!(&um.this, Expression::Literal(Literal::Number(n)) if n.contains('.'))
2771 } else { false }
2772 }
2773 Expression::Cast(c) => matches!(&c.to, DataType::Decimal { .. }),
2775 _ => false,
2776 };
2777
2778 let is_negative = match &months_expr {
2779 Expression::Neg(_) => true,
2780 Expression::Literal(Literal::Number(n)) => n.starts_with('-'),
2781 _ => false,
2782 };
2783 let is_null = matches!(&months_expr, Expression::Null(_));
2784
2785 let interval_expr = if is_non_integer_months {
2786 Expression::Function(Box::new(Function::new("TO_MONTHS".to_string(), vec![
2788 Expression::Cast(Box::new(Cast {
2789 this: Expression::Function(Box::new(Function::new("ROUND".to_string(), vec![months_expr.clone()]))),
2790 to: DataType::Int { length: None, integer_spelling: false },
2791 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
2792 }))
2793 ])))
2794 } else if is_negative || is_null {
2795 Expression::Interval(Box::new(Interval {
2797 this: Some(Expression::Paren(Box::new(Paren { this: months_expr.clone(), trailing_comments: Vec::new() }))),
2798 unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Month, use_plural: false }),
2799 }))
2800 } else {
2801 Expression::Interval(Box::new(Interval {
2803 this: Some(months_expr.clone()),
2804 unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Month, use_plural: false }),
2805 }))
2806 };
2807
2808 let date_plus_interval = Expression::Add(Box::new(BinaryOp {
2809 left: date_expr.clone(),
2810 right: interval_expr.clone(),
2811 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2812 }));
2813
2814 let case_expr = Expression::Case(Box::new(Case {
2815 operand: None,
2816 whens: vec![(
2817 Expression::Eq(Box::new(BinaryOp {
2818 left: Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![date_expr.clone()]))),
2819 right: date_expr.clone(),
2820 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2821 })),
2822 Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![date_plus_interval.clone()]))),
2823 )],
2824 else_: Some(date_plus_interval),
2825 }));
2826
2827 if let Some(dt) = date_type {
2829 Ok(Expression::Cast(Box::new(Cast {
2830 this: case_expr,
2831 to: dt,
2832 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
2833 })))
2834 } else {
2835 Ok(case_expr)
2836 }
2837 }
2838
2839 "TIME_SLICE" if f.args.len() >= 3 => {
2842 let mut args = f.args;
2843 let date_expr = args.remove(0);
2844 let n = args.remove(0);
2845 let unit_str = args.remove(0);
2846 let alignment = if !args.is_empty() { Some(args.remove(0)) } else { None };
2847
2848 let unit = match &unit_str {
2850 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
2851 Expression::Column(c) => c.name.name.to_uppercase(),
2852 Expression::Identifier(i) => i.name.to_uppercase(),
2853 _ => "DAY".to_string(),
2854 };
2855
2856 let interval_unit = match unit.as_str() {
2857 "YEAR" => IntervalUnit::Year,
2858 "QUARTER" => IntervalUnit::Quarter,
2859 "MONTH" => IntervalUnit::Month,
2860 "WEEK" => IntervalUnit::Week,
2861 "DAY" => IntervalUnit::Day,
2862 "HOUR" => IntervalUnit::Hour,
2863 "MINUTE" => IntervalUnit::Minute,
2864 "SECOND" => IntervalUnit::Second,
2865 _ => IntervalUnit::Day,
2866 };
2867
2868 let interval = Expression::Interval(Box::new(Interval {
2869 this: Some(n.clone()),
2870 unit: Some(IntervalUnitSpec::Simple { unit: interval_unit.clone(), use_plural: false }),
2871 }));
2872
2873 let time_bucket = Expression::Function(Box::new(Function::new("TIME_BUCKET".to_string(), vec![interval.clone(), date_expr.clone()])));
2874
2875 let is_end = match &alignment {
2876 Some(Expression::Literal(Literal::String(s))) => s.to_uppercase() == "END",
2877 _ => false,
2878 };
2879
2880 let is_date_type = match &date_expr {
2882 Expression::Cast(c) => matches!(&c.to, DataType::Date),
2883 _ => false,
2884 };
2885
2886 if is_end {
2887 let bucket_plus = Expression::Add(Box::new(BinaryOp {
2888 left: time_bucket,
2889 right: Expression::Interval(Box::new(Interval {
2890 this: Some(n),
2891 unit: Some(IntervalUnitSpec::Simple { unit: interval_unit, use_plural: false }),
2892 })),
2893 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2894 }));
2895 if is_date_type {
2896 Ok(Expression::Cast(Box::new(Cast {
2897 this: bucket_plus,
2898 to: DataType::Date,
2899 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
2900 })))
2901 } else {
2902 Ok(bucket_plus)
2903 }
2904 } else {
2905 Ok(time_bucket)
2906 }
2907 }
2908
2909 "DATE_FROM_PARTS" | "DATEFROMPARTS" if f.args.len() == 3 => {
2911 let mut args = f.args;
2912 let year = args.remove(0);
2913 let month = args.remove(0);
2914 let day = args.remove(0);
2915
2916 let make_date = Expression::Function(Box::new(Function::new("MAKE_DATE".to_string(), vec![year, Expression::number(1), Expression::number(1)])));
2917
2918 let month_wrapped = match &month {
2920 Expression::Add(_) | Expression::Sub(_) | Expression::Mul(_) | Expression::Div(_) => {
2921 Expression::Paren(Box::new(Paren { this: month, trailing_comments: Vec::new() }))
2922 }
2923 _ => month,
2924 };
2925 let day_wrapped = match &day {
2926 Expression::Add(_) | Expression::Sub(_) | Expression::Mul(_) | Expression::Div(_) => {
2927 Expression::Paren(Box::new(Paren { this: day, trailing_comments: Vec::new() }))
2928 }
2929 _ => day,
2930 };
2931 let month_minus_1 = Expression::Sub(Box::new(BinaryOp { left: month_wrapped, right: Expression::number(1), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2932 let month_interval = Expression::Interval(Box::new(Interval {
2933 this: Some(Expression::Paren(Box::new(Paren { this: month_minus_1, trailing_comments: Vec::new() }))),
2934 unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Month, use_plural: false }),
2935 }));
2936
2937 let day_minus_1 = Expression::Sub(Box::new(BinaryOp { left: day_wrapped, right: Expression::number(1), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
2938 let day_interval = Expression::Interval(Box::new(Interval {
2939 this: Some(Expression::Paren(Box::new(Paren { this: day_minus_1, trailing_comments: Vec::new() }))),
2940 unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Day, use_plural: false }),
2941 }));
2942
2943 let result = Expression::Add(Box::new(BinaryOp {
2944 left: Expression::Add(Box::new(BinaryOp {
2945 left: make_date,
2946 right: month_interval,
2947 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2948 })),
2949 right: day_interval,
2950 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
2951 }));
2952
2953 Ok(Expression::Cast(Box::new(Cast {
2954 this: result,
2955 to: DataType::Date,
2956 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
2957 })))
2958 }
2959
2960 "NEXT_DAY" if f.args.len() == 2 => {
2962 let mut args = f.args;
2963 let date = args.remove(0);
2964 let day_name = args.remove(0);
2965
2966 let day_num = match &day_name {
2968 Expression::Literal(Literal::String(s)) => {
2969 let upper = s.to_uppercase();
2970 if upper.starts_with("MO") { Some(1) }
2971 else if upper.starts_with("TU") { Some(2) }
2972 else if upper.starts_with("WE") { Some(3) }
2973 else if upper.starts_with("TH") { Some(4) }
2974 else if upper.starts_with("FR") { Some(5) }
2975 else if upper.starts_with("SA") { Some(6) }
2976 else if upper.starts_with("SU") { Some(7) }
2977 else { None }
2978 }
2979 _ => None,
2980 };
2981
2982 let target_day_expr = if let Some(n) = day_num {
2983 Expression::number(n)
2984 } else {
2985 Expression::Case(Box::new(Case {
2987 operand: None,
2988 whens: vec![
2989 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("MO".to_string()))]))), Expression::number(1)),
2990 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("TU".to_string()))]))), Expression::number(2)),
2991 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("WE".to_string()))]))), Expression::number(3)),
2992 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("TH".to_string()))]))), Expression::number(4)),
2993 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("FR".to_string()))]))), Expression::number(5)),
2994 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("SA".to_string()))]))), Expression::number(6)),
2995 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name))), Expression::Literal(Literal::String("SU".to_string()))]))), Expression::number(7)),
2996 ],
2997 else_: None,
2998 }))
2999 };
3000
3001 let isodow = Expression::Function(Box::new(Function::new("ISODOW".to_string(), vec![date.clone()])));
3002 let diff = Expression::Add(Box::new(BinaryOp {
3004 left: Expression::Paren(Box::new(Paren {
3005 this: Expression::Mod(Box::new(BinaryOp {
3006 left: Expression::Paren(Box::new(Paren {
3007 this: Expression::Add(Box::new(BinaryOp {
3008 left: Expression::Paren(Box::new(Paren {
3009 this: Expression::Sub(Box::new(BinaryOp { left: target_day_expr, right: isodow, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })),
3010 trailing_comments: Vec::new(),
3011 })),
3012 right: Expression::number(6),
3013 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3014 })),
3015 trailing_comments: Vec::new(),
3016 })),
3017 right: Expression::number(7),
3018 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3019 })),
3020 trailing_comments: Vec::new(),
3021 })),
3022 right: Expression::number(1),
3023 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3024 }));
3025
3026 let result = Expression::Add(Box::new(BinaryOp {
3027 left: date,
3028 right: Expression::Interval(Box::new(Interval {
3029 this: Some(Expression::Paren(Box::new(Paren { this: diff, trailing_comments: Vec::new() }))),
3030 unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Day, use_plural: false }),
3031 })),
3032 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3033 }));
3034
3035 Ok(Expression::Cast(Box::new(Cast {
3036 this: result,
3037 to: DataType::Date,
3038 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
3039 })))
3040 }
3041
3042 "PREVIOUS_DAY" if f.args.len() == 2 => {
3044 let mut args = f.args;
3045 let date = args.remove(0);
3046 let day_name = args.remove(0);
3047
3048 let day_num = match &day_name {
3049 Expression::Literal(Literal::String(s)) => {
3050 let upper = s.to_uppercase();
3051 if upper.starts_with("MO") { Some(1) }
3052 else if upper.starts_with("TU") { Some(2) }
3053 else if upper.starts_with("WE") { Some(3) }
3054 else if upper.starts_with("TH") { Some(4) }
3055 else if upper.starts_with("FR") { Some(5) }
3056 else if upper.starts_with("SA") { Some(6) }
3057 else if upper.starts_with("SU") { Some(7) }
3058 else { None }
3059 }
3060 _ => None,
3061 };
3062
3063 let target_day_expr = if let Some(n) = day_num {
3064 Expression::number(n)
3065 } else {
3066 Expression::Case(Box::new(Case {
3067 operand: None,
3068 whens: vec![
3069 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("MO".to_string()))]))), Expression::number(1)),
3070 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("TU".to_string()))]))), Expression::number(2)),
3071 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("WE".to_string()))]))), Expression::number(3)),
3072 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("TH".to_string()))]))), Expression::number(4)),
3073 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("FR".to_string()))]))), Expression::number(5)),
3074 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name.clone()))), Expression::Literal(Literal::String("SA".to_string()))]))), Expression::number(6)),
3075 (Expression::Function(Box::new(Function::new("STARTS_WITH".to_string(), vec![Expression::Upper(Box::new(UnaryFunc::new(day_name))), Expression::Literal(Literal::String("SU".to_string()))]))), Expression::number(7)),
3076 ],
3077 else_: None,
3078 }))
3079 };
3080
3081 let isodow = Expression::Function(Box::new(Function::new("ISODOW".to_string(), vec![date.clone()])));
3082 let diff = Expression::Add(Box::new(BinaryOp {
3084 left: Expression::Paren(Box::new(Paren {
3085 this: Expression::Mod(Box::new(BinaryOp {
3086 left: Expression::Paren(Box::new(Paren {
3087 this: Expression::Add(Box::new(BinaryOp {
3088 left: Expression::Paren(Box::new(Paren {
3089 this: Expression::Sub(Box::new(BinaryOp { left: isodow, right: target_day_expr, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })),
3090 trailing_comments: Vec::new(),
3091 })),
3092 right: Expression::number(6),
3093 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3094 })),
3095 trailing_comments: Vec::new(),
3096 })),
3097 right: Expression::number(7),
3098 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3099 })),
3100 trailing_comments: Vec::new(),
3101 })),
3102 right: Expression::number(1),
3103 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3104 }));
3105
3106 let result = Expression::Sub(Box::new(BinaryOp {
3107 left: date,
3108 right: Expression::Interval(Box::new(Interval {
3109 this: Some(Expression::Paren(Box::new(Paren { this: diff, trailing_comments: Vec::new() }))),
3110 unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Day, use_plural: false }),
3111 })),
3112 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3113 }));
3114
3115 Ok(Expression::Cast(Box::new(Cast {
3116 this: result,
3117 to: DataType::Date,
3118 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
3119 })))
3120 }
3121
3122 "LAST_DAY" if f.args.len() == 2 => {
3126 let mut args = f.args;
3127 let date = args.remove(0);
3128 let unit = args.remove(0);
3129 let unit_str = match &unit {
3130 Expression::Column(c) => c.name.name.to_uppercase(),
3131 Expression::Identifier(i) => i.name.to_uppercase(),
3132 _ => String::new(),
3133 };
3134
3135 match unit_str.as_str() {
3136 "MONTH" => Ok(Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![date])))),
3137 "YEAR" => {
3138 Ok(Expression::Function(Box::new(Function::new("MAKE_DATE".to_string(), vec![
3139 Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: date, field: crate::expressions::DateTimeField::Year })),
3140 Expression::number(12),
3141 Expression::number(31),
3142 ]))))
3143 }
3144 "QUARTER" => {
3145 let year = Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: date.clone(), field: crate::expressions::DateTimeField::Year }));
3146 let quarter_month = Expression::Mul(Box::new(BinaryOp {
3147 left: Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: date, field: crate::expressions::DateTimeField::Custom("QUARTER".to_string()) })),
3148 right: Expression::number(3),
3149 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3150 }));
3151 let make_date = Expression::Function(Box::new(Function::new("MAKE_DATE".to_string(), vec![year, quarter_month, Expression::number(1)])));
3152 Ok(Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![make_date]))))
3153 }
3154 "WEEK" => {
3155 let dow = Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: date.clone(), field: crate::expressions::DateTimeField::Custom("DAYOFWEEK".to_string()) }));
3156 let diff = Expression::Mod(Box::new(BinaryOp {
3157 left: Expression::Paren(Box::new(Paren {
3158 this: Expression::Sub(Box::new(BinaryOp { left: Expression::number(7), right: dow, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })),
3159 trailing_comments: Vec::new(),
3160 })),
3161 right: Expression::number(7),
3162 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3163 }));
3164 let result = Expression::Add(Box::new(BinaryOp {
3165 left: date,
3166 right: Expression::Interval(Box::new(Interval {
3167 this: Some(Expression::Paren(Box::new(Paren { this: diff, trailing_comments: Vec::new() }))),
3168 unit: Some(IntervalUnitSpec::Simple { unit: IntervalUnit::Day, use_plural: false }),
3169 })),
3170 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3171 }));
3172 Ok(Expression::Cast(Box::new(Cast { this: result, to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })))
3173 }
3174 _ => Ok(Expression::Function(Box::new(Function::new("LAST_DAY".to_string(), vec![date, unit])))),
3175 }
3176 }
3177
3178 "SEQ1" | "SEQ2" | "SEQ4" | "SEQ8" => {
3180 let (range, half): (u128, u128) = match name_upper.as_str() {
3181 "SEQ1" => (256, 128),
3182 "SEQ2" => (65536, 32768),
3183 "SEQ4" => (4294967296, 2147483648),
3184 "SEQ8" => (18446744073709551616, 9223372036854775808),
3185 _ => unreachable!("sequence type already matched in caller"),
3186 };
3187
3188 let is_signed = match f.args.first() {
3189 Some(Expression::Literal(Literal::Number(n))) => n == "1",
3190 _ => false,
3191 };
3192
3193 let row_num = Expression::Sub(Box::new(BinaryOp {
3194 left: Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
3195 this: Expression::Function(Box::new(Function::new("ROW_NUMBER".to_string(), vec![]))),
3196 over: crate::expressions::Over {
3197 window_name: None,
3198 partition_by: vec![],
3199 order_by: vec![crate::expressions::Ordered {
3200 this: Expression::number(1),
3201 desc: false,
3202 nulls_first: Some(true),
3203 explicit_asc: false,
3204 with_fill: None,
3205 }],
3206 frame: None,
3207 alias: None,
3208 },
3209 keep: None,
3210 })),
3211 right: Expression::number(1),
3212 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3213 }));
3214
3215 let modded = Expression::Mod(Box::new(BinaryOp {
3216 left: Expression::Paren(Box::new(Paren { this: row_num, trailing_comments: Vec::new() })),
3217 right: Expression::Literal(Literal::Number(range.to_string())),
3218 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3219 }));
3220
3221 if is_signed {
3222 let cond = Expression::Gte(Box::new(BinaryOp {
3224 left: modded.clone(),
3225 right: Expression::Literal(Literal::Number(half.to_string())),
3226 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3227 }));
3228 let signed_val = Expression::Sub(Box::new(BinaryOp {
3229 left: modded.clone(),
3230 right: Expression::Literal(Literal::Number(range.to_string())),
3231 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3232 }));
3233 Ok(Expression::Paren(Box::new(Paren {
3234 this: Expression::Case(Box::new(Case {
3235 operand: None,
3236 whens: vec![(cond, signed_val)],
3237 else_: Some(modded),
3238 })),
3239 trailing_comments: Vec::new(),
3240 })))
3241 } else {
3242 Ok(modded)
3243 }
3244 }
3245
3246 "TABLE" if f.args.len() == 1 => {
3249 let inner = f.args.into_iter().next().unwrap();
3250 if let Expression::Function(ref gen_f) = inner {
3252 if gen_f.name.to_uppercase() == "GENERATOR" {
3253 let mut rowcount = None;
3254 for arg in &gen_f.args {
3255 if let Expression::NamedArgument(na) = arg {
3256 if na.name.name.to_uppercase() == "ROWCOUNT" {
3257 rowcount = Some(na.value.clone());
3258 }
3259 }
3260 }
3261 if let Some(n) = rowcount {
3262 return Ok(Expression::Function(Box::new(Function::new("RANGE".to_string(), vec![n]))));
3263 }
3264 }
3265 }
3266 Ok(inner)
3267 }
3268
3269 "GENERATOR" => {
3271 let mut rowcount = None;
3272 for arg in &f.args {
3273 if let Expression::NamedArgument(na) = arg {
3274 if na.name.name.to_uppercase() == "ROWCOUNT" {
3275 rowcount = Some(na.value.clone());
3276 }
3277 }
3278 }
3279 if let Some(n) = rowcount {
3280 Ok(Expression::Function(Box::new(Function::new("RANGE".to_string(), vec![n]))))
3281 } else {
3282 Ok(Expression::Function(Box::new(f)))
3283 }
3284 }
3285
3286 "UNIFORM" if f.args.len() == 3 => {
3289 let mut args = f.args;
3290 let low = args.remove(0);
3291 let high = args.remove(0);
3292 let gen = args.remove(0);
3293
3294 let range = Expression::Add(Box::new(BinaryOp {
3295 left: Expression::Sub(Box::new(BinaryOp { left: high, right: low.clone(), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })),
3296 right: Expression::number(1),
3297 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3298 }));
3299
3300 let random_val = match &gen {
3302 Expression::Rand(_) | Expression::Random(_) => {
3303 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
3305 }
3306 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
3307 Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])))
3309 }
3310 _ => {
3311 let hash = Expression::Function(Box::new(Function::new("HASH".to_string(), vec![gen])));
3313 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
3314 let modded = Expression::Mod(Box::new(BinaryOp { left: abs_hash, right: Expression::number(1000000), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
3315 let paren_modded = Expression::Paren(Box::new(Paren { this: modded, trailing_comments: Vec::new() }));
3316 Expression::Div(Box::new(BinaryOp { left: paren_modded, right: Expression::Literal(Literal::Number("1000000.0".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))
3317 }
3318 };
3319
3320 let inner = Expression::Function(Box::new(Function::new("FLOOR".to_string(), vec![
3321 Expression::Add(Box::new(BinaryOp {
3322 left: low,
3323 right: Expression::Mul(Box::new(BinaryOp { left: random_val, right: Expression::Paren(Box::new(Paren { this: range, trailing_comments: Vec::new() })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })),
3324 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3325 }))
3326 ])));
3327
3328 Ok(Expression::Cast(Box::new(Cast {
3329 this: inner,
3330 to: DataType::BigInt { length: None },
3331 trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None,
3332 })))
3333 }
3334
3335 "NORMAL" if f.args.len() == 3 => {
3339 let mut args = f.args;
3340 let mean = args.remove(0);
3341 let stddev = args.remove(0);
3342 let gen = args.remove(0);
3343
3344 let make_seed_random = |seed: Expression| -> Expression {
3346 let hash = Expression::Function(Box::new(Function::new("HASH".to_string(), vec![seed])));
3347 let abs_hash = Expression::Abs(Box::new(UnaryFunc::new(hash)));
3348 let modded = Expression::Mod(Box::new(BinaryOp { left: abs_hash, right: Expression::number(1000000), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
3349 let paren_modded = Expression::Paren(Box::new(Paren { this: modded, trailing_comments: Vec::new() }));
3350 Expression::Div(Box::new(BinaryOp { left: paren_modded, right: Expression::Literal(Literal::Number("1000000.0".to_string())), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))
3351 };
3352
3353 let is_random_no_seed = match &gen {
3355 Expression::Random(_) => true,
3356 Expression::Rand(r) => r.seed.is_none(),
3357 _ => false,
3358 };
3359 let (u1, u2) = if is_random_no_seed {
3360 let u1 = Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
3362 let u2 = Expression::Function(Box::new(Function::new("RANDOM".to_string(), vec![])));
3363 (u1, u2)
3364 } else {
3365 let seed = match gen {
3367 Expression::Rand(r) => r.seed.map(|s| *s).unwrap_or(Expression::number(0)),
3368 Expression::Function(func) if func.name.to_uppercase() == "RANDOM" => {
3369 if func.args.len() == 1 {
3370 func.args.into_iter().next().unwrap()
3371 } else {
3372 Expression::number(0)
3373 }
3374 }
3375 other => other,
3376 };
3377 let u1 = make_seed_random(seed.clone());
3378 let seed_plus_1 = Expression::Add(Box::new(BinaryOp { left: seed, right: Expression::number(1), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }));
3379 let u2 = make_seed_random(seed_plus_1);
3380 (u1, u2)
3381 };
3382
3383 let greatest = Expression::Greatest(Box::new(VarArgFunc {
3385 expressions: vec![u1, Expression::Literal(Literal::Number("1e-10".to_string()))],
3386 original_name: None,
3387 }));
3388
3389 let neg2 = Expression::Neg(Box::new(crate::expressions::UnaryOp { this: Expression::number(2) }));
3391 let ln_greatest = Expression::Function(Box::new(Function::new("LN".to_string(), vec![greatest])));
3392 let neg2_times_ln = Expression::Mul(Box::new(BinaryOp {
3393 left: neg2,
3394 right: ln_greatest,
3395 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3396 }));
3397 let sqrt_part = Expression::Function(Box::new(Function::new("SQRT".to_string(), vec![neg2_times_ln])));
3398
3399 let pi = Expression::Function(Box::new(Function::new("PI".to_string(), vec![])));
3401 let two_pi = Expression::Mul(Box::new(BinaryOp {
3402 left: Expression::number(2),
3403 right: pi,
3404 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3405 }));
3406 let two_pi_u2 = Expression::Mul(Box::new(BinaryOp {
3407 left: two_pi,
3408 right: u2,
3409 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3410 }));
3411 let cos_part = Expression::Function(Box::new(Function::new("COS".to_string(), vec![two_pi_u2])));
3412
3413 let stddev_times_sqrt = Expression::Mul(Box::new(BinaryOp {
3415 left: stddev,
3416 right: sqrt_part,
3417 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3418 }));
3419 let inner = Expression::Mul(Box::new(BinaryOp {
3420 left: stddev_times_sqrt,
3421 right: cos_part,
3422 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3423 }));
3424 let paren_inner = Expression::Paren(Box::new(Paren { this: inner, trailing_comments: Vec::new() }));
3425
3426 Ok(Expression::Add(Box::new(BinaryOp {
3428 left: mean,
3429 right: paren_inner,
3430 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3431 })))
3432 }
3433
3434 "ZIPF" if f.args.len() == 3 => {
3444 let mut args = f.args;
3445 let s_expr = args.remove(0);
3446 let n_expr = args.remove(0);
3447 let gen_expr = args.remove(0);
3448
3449 let s_sql = Self::expr_to_sql(&s_expr);
3450 let n_sql = Self::expr_to_sql(&n_expr);
3451 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
3452
3453 let rand_sql = if is_random {
3454 format!("SELECT {} AS r", seed_sql)
3455 } else {
3456 format!("SELECT (ABS(HASH({})) % 1000000) / 1000000.0 AS r", seed_sql)
3457 };
3458
3459 let template = format!(
3460 "WITH rand AS ({}), weights AS (SELECT i, 1.0 / POWER(i, {}) AS w FROM RANGE(1, {} + 1) AS t(i)), cdf AS (SELECT i, SUM(w) OVER (ORDER BY i NULLS FIRST) / SUM(w) OVER () AS p FROM weights) SELECT MIN(i) FROM cdf WHERE p >= (SELECT r FROM rand)",
3461 rand_sql, s_sql, n_sql
3462 );
3463
3464 Self::parse_as_subquery(&template)
3465 }
3466
3467 "RANDSTR" if f.args.len() == 2 => {
3469 let mut args = f.args;
3470 let len_expr = args.remove(0);
3471 let gen_expr = args.remove(0);
3472
3473 let len_sql = Self::expr_to_sql(&len_expr);
3474 let (seed_sql, is_random) = Self::extract_seed_info(&gen_expr);
3475
3476 let random_value_sql = if is_random {
3477 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
3478 } else {
3479 format!("(ABS(HASH(i + {})) % 1000) / 1000.0", seed_sql)
3480 };
3481
3482 let template = format!(
3483 "SELECT LISTAGG(SUBSTRING('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 1 + CAST(FLOOR(random_value * 62) AS INT), 1), '') FROM (SELECT {} AS random_value FROM RANGE({}) AS t(i))",
3484 random_value_sql, len_sql
3485 );
3486
3487 Self::parse_as_subquery(&template)
3488 }
3489
3490 _ => Ok(Expression::Function(Box::new(f))),
3492 }
3493 }
3494
3495 fn convert_snowflake_date_format(&self, fmt: Expression) -> Expression {
3497 match fmt {
3498 Expression::Literal(Literal::String(s)) => {
3499 let converted = Self::snowflake_to_strptime(&s);
3500 Expression::Literal(Literal::String(converted))
3501 }
3502 _ => fmt,
3503 }
3504 }
3505
3506 fn convert_snowflake_time_format(&self, fmt: Expression) -> Expression {
3508 match fmt {
3509 Expression::Literal(Literal::String(s)) => {
3510 let converted = Self::snowflake_to_strptime(&s);
3511 Expression::Literal(Literal::String(converted))
3512 }
3513 _ => fmt,
3514 }
3515 }
3516
3517 fn snowflake_to_strptime(s: &str) -> String {
3520 let mut result = String::new();
3521 let chars: Vec<char> = s.chars().collect();
3522 let len = chars.len();
3523 let mut i = 0;
3524 while i < len {
3525 let remaining = &s[i..];
3526 let remaining_upper: String = remaining.chars().take(8).collect::<String>().to_uppercase();
3527
3528 if remaining_upper.starts_with("HH24MISS") {
3530 result.push_str("%H%M%S");
3531 i += 8;
3532 } else if remaining_upper.starts_with("MMMM") {
3533 result.push_str("%B");
3534 i += 4;
3535 } else if remaining_upper.starts_with("YYYY") {
3536 result.push_str("%Y");
3537 i += 4;
3538 } else if remaining_upper.starts_with("YY") {
3539 result.push_str("%y");
3540 i += 2;
3541 } else if remaining_upper.starts_with("MON") {
3542 result.push_str("%b");
3543 i += 3;
3544 } else if remaining_upper.starts_with("HH24") {
3545 result.push_str("%H");
3546 i += 4;
3547 } else if remaining_upper.starts_with("HH12") {
3548 result.push_str("%I");
3549 i += 4;
3550 } else if remaining_upper.starts_with("HH") {
3551 result.push_str("%I");
3552 i += 2;
3553 } else if remaining_upper.starts_with("MISS") {
3554 result.push_str("%M%S");
3555 i += 4;
3556 } else if remaining_upper.starts_with("MI") {
3557 result.push_str("%M");
3558 i += 2;
3559 } else if remaining_upper.starts_with("MM") {
3560 result.push_str("%m");
3561 i += 2;
3562 } else if remaining_upper.starts_with("DD") {
3563 result.push_str("%d");
3564 i += 2;
3565 } else if remaining_upper.starts_with("DY") {
3566 result.push_str("%a");
3567 i += 2;
3568 } else if remaining_upper.starts_with("SS") {
3569 result.push_str("%S");
3570 i += 2;
3571 } else if remaining_upper.starts_with("FF") {
3572 let ff_pos = i + 2;
3575 if ff_pos < len && chars[ff_pos].is_ascii_digit() {
3576 let digit = chars[ff_pos].to_digit(10).unwrap_or(6);
3577 if digit >= 7 {
3578 result.push_str("%n");
3579 } else {
3580 result.push_str("%f");
3581 }
3582 i += 3; } else {
3584 result.push_str("%f");
3585 i += 2;
3586 }
3587 } else if remaining_upper.starts_with("PM") || remaining_upper.starts_with("AM") {
3588 result.push_str("%p");
3589 i += 2;
3590 } else if remaining_upper.starts_with("TZH") {
3591 result.push_str("%z");
3592 i += 3;
3593 } else if remaining_upper.starts_with("TZM") {
3594 i += 3;
3596 } else {
3597 result.push(chars[i]);
3598 i += 1;
3599 }
3600 }
3601 result
3602 }
3603
3604 fn convert_bq_to_strptime_format(&self, fmt: Expression) -> Expression {
3607 match fmt {
3608 Expression::Literal(Literal::String(s)) => {
3609 let converted = s
3610 .replace("%E6S", "%S.%f")
3611 .replace("%E*S", "%S.%f");
3612 Expression::Literal(Literal::String(converted))
3613 }
3614 _ => fmt,
3615 }
3616 }
3617
3618 fn transform_date_part(&self, args: Vec<Expression>) -> Result<Expression> {
3620 let mut args = args;
3621 let unit_expr = args.remove(0);
3622 let date_expr = args.remove(0);
3623 let unit_name = match &unit_expr {
3624 Expression::Column(c) => c.name.name.to_uppercase(),
3625 Expression::Identifier(i) => i.name.to_uppercase(),
3626 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
3627 _ => return Ok(Expression::Function(Box::new(Function::new("DATE_PART".to_string(), vec![unit_expr, date_expr])))),
3628 };
3629 match unit_name.as_str() {
3630 "EPOCH_SECOND" | "EPOCH" => Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("EPOCH".to_string(), vec![date_expr]))), to: DataType::BigInt { length: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))),
3631 "EPOCH_MILLISECOND" | "EPOCH_MILLISECONDS" => Ok(Expression::Function(Box::new(Function::new("EPOCH_MS".to_string(), vec![date_expr])))),
3632 "EPOCH_MICROSECOND" | "EPOCH_MICROSECONDS" => Ok(Expression::Function(Box::new(Function::new("EPOCH_US".to_string(), vec![date_expr])))),
3633 "EPOCH_NANOSECOND" | "EPOCH_NANOSECONDS" => Ok(Expression::Function(Box::new(Function::new("EPOCH_NS".to_string(), vec![date_expr])))),
3634 "DAYOFWEEKISO" | "DAYOFWEEK_ISO" => Ok(Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: date_expr, field: crate::expressions::DateTimeField::Custom("ISODOW".to_string()) }))),
3635 "YEAROFWEEK" | "YEAROFWEEKISO" => Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("STRFTIME".to_string(), vec![date_expr, Expression::Literal(Literal::String("%G".to_string()))]))), to: DataType::Int { length: None, integer_spelling: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))),
3636 "WEEKISO" => Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("STRFTIME".to_string(), vec![date_expr, Expression::Literal(Literal::String("%V".to_string()))]))), to: DataType::Int { length: None, integer_spelling: false }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))),
3637 "NANOSECOND" | "NANOSECONDS" | "NS" => Ok(Expression::Cast(Box::new(Cast { this: Expression::Function(Box::new(Function::new("STRFTIME".to_string(), vec![Expression::Cast(Box::new(Cast { this: date_expr, to: DataType::Custom { name: "TIMESTAMP_NS".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })), Expression::Literal(Literal::String("%n".to_string()))]))), to: DataType::BigInt { length: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))),
3638 "DAYOFMONTH" => Ok(Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: date_expr, field: crate::expressions::DateTimeField::Day }))),
3639 _ => {
3640 let field = match unit_name.as_str() {
3641 "YEAR" | "YY" | "YYYY" => crate::expressions::DateTimeField::Year,
3642 "MONTH" | "MON" | "MM" => crate::expressions::DateTimeField::Month,
3643 "DAY" | "DD" | "D" => crate::expressions::DateTimeField::Day,
3644 "HOUR" | "HH" => crate::expressions::DateTimeField::Hour,
3645 "MINUTE" | "MI" | "MIN" => crate::expressions::DateTimeField::Minute,
3646 "SECOND" | "SEC" | "SS" => crate::expressions::DateTimeField::Second,
3647 "MILLISECOND" | "MS" => crate::expressions::DateTimeField::Millisecond,
3648 "MICROSECOND" | "US" => crate::expressions::DateTimeField::Microsecond,
3649 "QUARTER" | "QTR" => crate::expressions::DateTimeField::Quarter,
3650 "WEEK" | "WK" => crate::expressions::DateTimeField::Week,
3651 "DAYOFWEEK" | "DOW" => crate::expressions::DateTimeField::DayOfWeek,
3652 "DAYOFYEAR" | "DOY" => crate::expressions::DateTimeField::DayOfYear,
3653 "TIMEZONE_HOUR" => crate::expressions::DateTimeField::TimezoneHour,
3654 "TIMEZONE_MINUTE" => crate::expressions::DateTimeField::TimezoneMinute,
3655 _ => crate::expressions::DateTimeField::Custom(unit_name),
3656 };
3657 Ok(Expression::Extract(Box::new(crate::expressions::ExtractFunc { this: date_expr, field })))
3658 }
3659 }
3660 }
3661
3662 fn transform_dateadd(&self, args: Vec<Expression>) -> Result<Expression> {
3664 let mut args = args;
3665 let unit_expr = args.remove(0);
3666 let amount = args.remove(0);
3667 let date = args.remove(0);
3668 let unit_name = match &unit_expr {
3669 Expression::Column(c) => c.name.name.to_uppercase(),
3670 Expression::Identifier(i) => i.name.to_uppercase(),
3671 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
3672 _ => String::new(),
3673 };
3674 if unit_name == "NANOSECOND" || unit_name == "NS" {
3675 let epoch_ns = Expression::Function(Box::new(Function::new("EPOCH_NS".to_string(), vec![Expression::Cast(Box::new(Cast { this: date, to: DataType::Custom { name: "TIMESTAMP_NS".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))])));
3676 return Ok(Expression::Function(Box::new(Function::new("MAKE_TIMESTAMP_NS".to_string(), vec![Expression::Add(Box::new(BinaryOp { left: epoch_ns, right: amount, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))]))));
3677 }
3678 let (interval_unit, multiplied_amount) = match unit_name.as_str() {
3679 "YEAR" | "YY" | "YYYY" => (IntervalUnit::Year, amount),
3680 "MONTH" | "MON" | "MM" => (IntervalUnit::Month, amount),
3681 "DAY" | "DD" | "D" => (IntervalUnit::Day, amount),
3682 "HOUR" | "HH" => (IntervalUnit::Hour, amount),
3683 "MINUTE" | "MI" | "MIN" => (IntervalUnit::Minute, amount),
3684 "SECOND" | "SEC" | "SS" => (IntervalUnit::Second, amount),
3685 "MILLISECOND" | "MS" => (IntervalUnit::Millisecond, amount),
3686 "MICROSECOND" | "US" => (IntervalUnit::Microsecond, amount),
3687 "WEEK" | "WK" => (IntervalUnit::Day, Expression::Mul(Box::new(BinaryOp { left: amount, right: Expression::number(7), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))),
3688 "QUARTER" | "QTR" => (IntervalUnit::Month, Expression::Mul(Box::new(BinaryOp { left: amount, right: Expression::number(3), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() }))),
3689 _ => (IntervalUnit::Day, amount),
3690 };
3691 Ok(Expression::Add(Box::new(BinaryOp { left: date, right: Expression::Interval(Box::new(Interval { this: Some(multiplied_amount), unit: Some(IntervalUnitSpec::Simple { unit: interval_unit, use_plural: false }) })), left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })))
3692 }
3693
3694 fn transform_datediff(&self, args: Vec<Expression>) -> Result<Expression> {
3696 let mut args = args;
3697 let unit_expr = args.remove(0);
3698 let start = args.remove(0);
3699 let end = args.remove(0);
3700 let unit_name = match &unit_expr {
3701 Expression::Column(c) => c.name.name.to_uppercase(),
3702 Expression::Identifier(i) => i.name.to_uppercase(),
3703 Expression::Literal(Literal::String(s)) => s.to_uppercase(),
3704 _ => String::new(),
3705 };
3706 if unit_name == "NANOSECOND" || unit_name == "NS" {
3707 let epoch_end = Expression::Function(Box::new(Function::new("EPOCH_NS".to_string(), vec![Expression::Cast(Box::new(Cast { this: end, to: DataType::Custom { name: "TIMESTAMP_NS".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))])));
3708 let epoch_start = Expression::Function(Box::new(Function::new("EPOCH_NS".to_string(), vec![Expression::Cast(Box::new(Cast { this: start, to: DataType::Custom { name: "TIMESTAMP_NS".to_string() }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))])));
3709 return Ok(Expression::Sub(Box::new(BinaryOp { left: epoch_end, right: epoch_start, left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new() })));
3710 }
3711 if unit_name == "WEEK" || unit_name == "WK" {
3712 let trunc_start = Expression::Function(Box::new(Function::new("DATE_TRUNC".to_string(), vec![Expression::Literal(Literal::String("WEEK".to_string())), Expression::Cast(Box::new(Cast { this: start, to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))])));
3713 let trunc_end = Expression::Function(Box::new(Function::new("DATE_TRUNC".to_string(), vec![Expression::Literal(Literal::String("WEEK".to_string())), Expression::Cast(Box::new(Cast { this: end, to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None }))])));
3714 return Ok(Expression::Function(Box::new(Function::new("DATE_DIFF".to_string(), vec![Expression::Literal(Literal::String("WEEK".to_string())), trunc_start, trunc_end]))));
3715 }
3716 let cast_if_string = |e: Expression| -> Expression { match &e { Expression::Literal(Literal::String(_)) => Expression::Cast(Box::new(Cast { this: e, to: DataType::Date, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })), _ => e } };
3717 let start = cast_if_string(start);
3718 let end = cast_if_string(end);
3719 Ok(Expression::Function(Box::new(Function::new("DATE_DIFF".to_string(), vec![Expression::Literal(Literal::String(unit_name)), start, end]))))
3720 }
3721
3722 fn transform_aggregate_function(
3723 &self,
3724 f: Box<crate::expressions::AggregateFunction>,
3725 ) -> Result<Expression> {
3726 let name_upper = f.name.to_uppercase();
3727 match name_upper.as_str() {
3728 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3730 Function::new("LISTAGG".to_string(), f.args),
3731 ))),
3732
3733 "LISTAGG" => Ok(Expression::AggregateFunction(f)),
3735
3736 "STRING_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3738 "LISTAGG".to_string(),
3739 f.args,
3740 )))),
3741
3742 "ARRAY_AGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3744 "list".to_string(),
3745 f.args,
3746 )))),
3747
3748 "LOGICAL_OR" if !f.args.is_empty() => {
3750 let arg = f.args.into_iter().next().unwrap();
3751 Ok(Expression::Function(Box::new(Function::new(
3752 "BOOL_OR".to_string(),
3753 vec![Expression::Cast(Box::new(crate::expressions::Cast {
3754 this: arg,
3755 to: crate::expressions::DataType::Boolean,
3756 trailing_comments: Vec::new(),
3757 double_colon_syntax: false,
3758 format: None,
3759 default: None,
3760 }))],
3761 ))))
3762 }
3763
3764 "LOGICAL_AND" if !f.args.is_empty() => {
3766 let arg = f.args.into_iter().next().unwrap();
3767 Ok(Expression::Function(Box::new(Function::new(
3768 "BOOL_AND".to_string(),
3769 vec![Expression::Cast(Box::new(crate::expressions::Cast {
3770 this: arg,
3771 to: crate::expressions::DataType::Boolean,
3772 trailing_comments: Vec::new(),
3773 double_colon_syntax: false,
3774 format: None,
3775 default: None,
3776 }))],
3777 ))))
3778 }
3779
3780 "SKEW" => Ok(Expression::Function(Box::new(Function::new(
3782 "SKEWNESS".to_string(),
3783 f.args,
3784 )))),
3785
3786 "REGR_VALX" if f.args.len() == 2 => {
3788 let mut args = f.args;
3789 let y = args.remove(0);
3790 let x = args.remove(0);
3791 Ok(Expression::Case(Box::new(Case {
3792 operand: None,
3793 whens: vec![(
3794 Expression::IsNull(Box::new(crate::expressions::IsNull { this: y, not: false, postfix_form: false })),
3795 Expression::Cast(Box::new(Cast { this: Expression::Null(crate::expressions::Null), to: DataType::Double { precision: None, scale: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })),
3796 )],
3797 else_: Some(x),
3798 })))
3799 }
3800
3801 "REGR_VALY" if f.args.len() == 2 => {
3803 let mut args = f.args;
3804 let y = args.remove(0);
3805 let x = args.remove(0);
3806 Ok(Expression::Case(Box::new(Case {
3807 operand: None,
3808 whens: vec![(
3809 Expression::IsNull(Box::new(crate::expressions::IsNull { this: x, not: false, postfix_form: false })),
3810 Expression::Cast(Box::new(Cast { this: Expression::Null(crate::expressions::Null), to: DataType::Double { precision: None, scale: None }, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })),
3811 )],
3812 else_: Some(y),
3813 })))
3814 }
3815
3816 "BOOLAND_AGG" if !f.args.is_empty() => {
3818 let arg = f.args.into_iter().next().unwrap();
3819 Ok(Expression::Function(Box::new(Function::new(
3820 "BOOL_AND".to_string(),
3821 vec![Expression::Cast(Box::new(Cast {
3822 this: arg,
3823 to: DataType::Boolean,
3824 trailing_comments: Vec::new(),
3825 double_colon_syntax: false,
3826 format: None,
3827 default: None,
3828 }))],
3829 ))))
3830 }
3831
3832 "BOOLOR_AGG" if !f.args.is_empty() => {
3834 let arg = f.args.into_iter().next().unwrap();
3835 Ok(Expression::Function(Box::new(Function::new(
3836 "BOOL_OR".to_string(),
3837 vec![Expression::Cast(Box::new(Cast {
3838 this: arg,
3839 to: DataType::Boolean,
3840 trailing_comments: Vec::new(),
3841 double_colon_syntax: false,
3842 format: None,
3843 default: None,
3844 }))],
3845 ))))
3846 }
3847
3848 "BOOLXOR_AGG" if !f.args.is_empty() => {
3850 let arg = f.args.into_iter().next().unwrap();
3851 Ok(Expression::Eq(Box::new(BinaryOp {
3852 left: Expression::Function(Box::new(Function::new("COUNT_IF".to_string(), vec![
3853 Expression::Cast(Box::new(Cast { this: arg, to: DataType::Boolean, trailing_comments: Vec::new(), double_colon_syntax: false, format: None, default: None })),
3854 ]))),
3855 right: Expression::number(1),
3856 left_comments: Vec::new(), operator_comments: Vec::new(), trailing_comments: Vec::new(),
3857 })))
3858 }
3859
3860 "MAX_BY" if f.args.len() == 2 => {
3862 Ok(Expression::AggregateFunction(Box::new(crate::expressions::AggregateFunction {
3863 name: "ARG_MAX".to_string(),
3864 ..(*f)
3865 })))
3866 }
3867
3868 "MIN_BY" if f.args.len() == 2 => {
3870 Ok(Expression::AggregateFunction(Box::new(crate::expressions::AggregateFunction {
3871 name: "ARG_MIN".to_string(),
3872 ..(*f)
3873 })))
3874 }
3875
3876 "CORR" if f.args.len() == 2 => {
3878 Ok(Expression::AggregateFunction(f))
3879 }
3880
3881 "BITMAP_CONSTRUCT_AGG" if f.args.len() == 1 => {
3883 let v_sql = Self::expr_to_sql(&f.args[0]);
3884
3885 let template = format!(
3886 "SELECT CASE WHEN l IS NULL OR LENGTH(l) = 0 THEN NULL WHEN LENGTH(l) <> LENGTH(LIST_FILTER(l, __v -> __v BETWEEN 0 AND 32767)) THEN NULL WHEN LENGTH(l) < 5 THEN UNHEX(PRINTF('%04X', LENGTH(l)) || h || REPEAT('00', GREATEST(0, 4 - LENGTH(l)) * 2)) ELSE UNHEX('08000000000000000000' || h) END FROM (SELECT l, COALESCE(LIST_REDUCE(LIST_TRANSFORM(l, __x -> PRINTF('%02X%02X', CAST(__x AS INT) & 255, (CAST(__x AS INT) >> 8) & 255)), (__a, __b) -> __a || __b, ''), '') AS h FROM (SELECT LIST_SORT(LIST_DISTINCT(LIST({v}) FILTER(WHERE NOT {v} IS NULL))) AS l))",
3887 v = v_sql
3888 );
3889
3890 Self::parse_as_subquery(&template)
3891 }
3892
3893 _ => Ok(Expression::AggregateFunction(f)),
3895 }
3896 }
3897
3898 fn convert_format_to_duckdb(expr: &Expression) -> Expression {
3902 if let Expression::Literal(Literal::String(s)) = expr {
3903 let duckdb_fmt = Self::presto_to_duckdb_format(s);
3904 Expression::Literal(Literal::String(duckdb_fmt))
3905 } else {
3906 expr.clone()
3907 }
3908 }
3909
3910 fn presto_to_duckdb_format(fmt: &str) -> String {
3912 let mut result = String::new();
3913 let chars: Vec<char> = fmt.chars().collect();
3914 let mut i = 0;
3915 while i < chars.len() {
3916 if chars[i] == '%' && i + 1 < chars.len() {
3917 match chars[i + 1] {
3918 'i' => {
3919 result.push_str("%M");
3921 i += 2;
3922 }
3923 'T' => {
3924 result.push_str("%H:%M:%S");
3926 i += 2;
3927 }
3928 'F' => {
3929 result.push_str("%Y-%m-%d");
3931 i += 2;
3932 }
3933 _ => {
3934 result.push('%');
3935 result.push(chars[i + 1]);
3936 i += 2;
3937 }
3938 }
3939 } else {
3940 result.push(chars[i]);
3941 i += 1;
3942 }
3943 }
3944 result
3945 }
3946}
3947
3948#[cfg(test)]
3949mod tests {
3950 use super::*;
3951 use crate::dialects::Dialect;
3952
3953 fn transpile_to_duckdb(sql: &str) -> String {
3954 let dialect = Dialect::get(DialectType::Generic);
3955 let result = dialect
3956 .transpile_to(sql, DialectType::DuckDB)
3957 .expect("Transpile failed");
3958 result[0].clone()
3959 }
3960
3961 #[test]
3962 fn test_ifnull_to_coalesce() {
3963 let result = transpile_to_duckdb("SELECT IFNULL(a, b)");
3964 assert!(
3965 result.contains("COALESCE"),
3966 "Expected COALESCE, got: {}",
3967 result
3968 );
3969 }
3970
3971 #[test]
3972 fn test_nvl_to_coalesce() {
3973 let result = transpile_to_duckdb("SELECT NVL(a, b)");
3974 assert!(
3975 result.contains("COALESCE"),
3976 "Expected COALESCE, got: {}",
3977 result
3978 );
3979 }
3980
3981 #[test]
3982 fn test_basic_select() {
3983 let result = transpile_to_duckdb("SELECT a, b FROM users WHERE id = 1");
3984 assert!(result.contains("SELECT"));
3985 assert!(result.contains("FROM users"));
3986 }
3987
3988 #[test]
3989 fn test_group_concat_to_listagg() {
3990 let result = transpile_to_duckdb("SELECT GROUP_CONCAT(name)");
3991 assert!(
3992 result.contains("LISTAGG"),
3993 "Expected LISTAGG, got: {}",
3994 result
3995 );
3996 }
3997
3998 #[test]
3999 fn test_listagg_preserved() {
4000 let result = transpile_to_duckdb("SELECT LISTAGG(name)");
4001 assert!(
4002 result.contains("LISTAGG"),
4003 "Expected LISTAGG, got: {}",
4004 result
4005 );
4006 }
4007
4008 #[test]
4009 fn test_date_format_to_strftime() {
4010 let result = transpile_to_duckdb("SELECT DATE_FORMAT(d, '%Y-%m-%d')");
4011 assert!(
4013 result.to_uppercase().contains("STRFTIME"),
4014 "Expected STRFTIME, got: {}",
4015 result
4016 );
4017 }
4018
4019 #[test]
4020 fn test_regexp_like_to_regexp_matches() {
4021 let result = transpile_to_duckdb("SELECT REGEXP_LIKE(name, 'pattern')");
4022 assert!(
4024 result.to_uppercase().contains("REGEXP_MATCHES"),
4025 "Expected REGEXP_MATCHES, got: {}",
4026 result
4027 );
4028 }
4029
4030 #[test]
4031 fn test_double_quote_identifiers() {
4032 let dialect = Dialect::get(DialectType::DuckDB);
4034 let config = dialect.generator_config();
4035 assert_eq!(config.identifier_quote, '"');
4036 }
4037
4038 fn duckdb_identity(sql: &str) -> String {
4040 let dialect = Dialect::get(DialectType::DuckDB);
4041 let ast = dialect.parse(sql).expect("Parse failed");
4042 let transformed = dialect.transform(ast[0].clone()).expect("Transform failed");
4043 dialect.generate(&transformed).expect("Generate failed")
4044 }
4045
4046 #[test]
4047 fn test_interval_quoting() {
4048 let result = duckdb_identity(
4050 "SELECT DATE_ADD(CAST('2020-01-01' AS DATE), INTERVAL 1 DAY)",
4051 );
4052 assert_eq!(
4053 result,
4054 "SELECT CAST('2020-01-01' AS DATE) + INTERVAL '1' DAY",
4055 "Interval value should be quoted as string"
4056 );
4057 }
4058
4059 #[test]
4060 fn test_struct_pack_to_curly_brace() {
4061 let result = duckdb_identity(
4063 "CAST([STRUCT_PACK(a := 1)] AS STRUCT(a BIGINT)[])",
4064 );
4065 assert_eq!(
4066 result,
4067 "CAST([{'a': 1}] AS STRUCT(a BIGINT)[])",
4068 "STRUCT_PACK should be transformed to curly brace notation"
4069 );
4070 }
4071
4072 #[test]
4073 fn test_struct_pack_nested() {
4074 let result = duckdb_identity(
4076 "CAST([[STRUCT_PACK(a := 1)]] AS STRUCT(a BIGINT)[][])",
4077 );
4078 assert_eq!(
4079 result,
4080 "CAST([[{'a': 1}]] AS STRUCT(a BIGINT)[][])",
4081 "Nested STRUCT_PACK should be transformed"
4082 );
4083 }
4084
4085 #[test]
4086 fn test_struct_pack_cast() {
4087 let result = duckdb_identity(
4089 "STRUCT_PACK(a := 'b')::json",
4090 );
4091 assert_eq!(
4092 result,
4093 "CAST({'a': 'b'} AS JSON)",
4094 "STRUCT_PACK with cast should be transformed"
4095 );
4096 }
4097
4098 #[test]
4099 fn test_list_value_to_bracket() {
4100 let result = duckdb_identity(
4102 "SELECT LIST_VALUE(1)[i]",
4103 );
4104 assert_eq!(
4105 result,
4106 "SELECT [1][i]",
4107 "LIST_VALUE should be transformed to bracket notation"
4108 );
4109 }
4110
4111 #[test]
4112 fn test_list_value_in_struct_literal() {
4113 let result = duckdb_identity(
4115 "{'x': LIST_VALUE(1)[i]}",
4116 );
4117 assert_eq!(
4118 result,
4119 "{'x': [1][i]}",
4120 "LIST_VALUE inside struct literal should be transformed"
4121 );
4122 }
4123
4124 #[test]
4125 fn test_struct_pack_simple() {
4126 let result = duckdb_identity("SELECT STRUCT_PACK(a := 1)");
4128 eprintln!("STRUCT_PACK result: {}", result);
4129 assert!(result.contains("{"), "Expected curly brace, got: {}", result);
4130 }
4131
4132 #[test]
4133 fn test_not_in_position() {
4134 let result = duckdb_identity(
4137 "SELECT col FROM t WHERE JSON_EXTRACT_STRING(col, '$.id') NOT IN ('b')",
4138 );
4139 assert_eq!(
4140 result,
4141 "SELECT col FROM t WHERE NOT (col ->> '$.id') IN ('b')",
4142 "NOT IN should have NOT moved outside and JSON expression wrapped"
4143 );
4144 }
4145
4146 #[test]
4147 fn test_unnest_comma_join_to_join_on_true() {
4148 let result = duckdb_identity(
4150 "WITH _data AS (SELECT [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}] AS col) SELECT t.col['b'] FROM _data, UNNEST(_data.col) AS t(col) WHERE t.col['a'] = 1",
4151 );
4152 assert_eq!(
4153 result,
4154 "WITH _data AS (SELECT [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}] AS col) SELECT t.col['b'] FROM _data JOIN UNNEST(_data.col) AS t(col) ON TRUE WHERE t.col['a'] = 1",
4155 "Comma-join with UNNEST should become JOIN ON TRUE"
4156 );
4157 }
4158}