1use crate::dialects::transform_recursive;
10use crate::dialects::{Dialect, DialectType};
11use crate::error::Result;
12use crate::expressions::{
13 Alias, BinaryOp, BooleanLiteral, Cast, DataType, Exists, Expression, From, Function,
14 Identifier, Join, JoinKind, Lateral, LateralView, Literal, NamedArgSeparator, NamedArgument,
15 Over, Select, StructField, Subquery, UnaryFunc, UnnestFunc, Where,
16};
17use std::cell::RefCell;
18
19pub fn preprocess<F>(expr: Expression, transforms: &[F]) -> Result<Expression>
28where
29 F: Fn(Expression) -> Result<Expression>,
30{
31 let mut result = expr;
32 for transform in transforms {
33 result = transform(result)?;
34 }
35 Ok(result)
36}
37
38pub fn unnest_to_explode(expr: Expression) -> Result<Expression> {
42 match expr {
43 Expression::Unnest(unnest) => {
44 Ok(Expression::Explode(Box::new(UnaryFunc::new(unnest.this))))
45 }
46 _ => Ok(expr),
47 }
48}
49
50pub fn unnest_to_explode_select(expr: Expression) -> Result<Expression> {
60 transform_recursive(expr, &unnest_to_explode_select_inner)
61}
62
63fn make_udtf_expr(unnest: &UnnestFunc) -> Expression {
66 let has_multi_expr = !unnest.expressions.is_empty();
67 if has_multi_expr {
68 let mut all_args = vec![unnest.this.clone()];
70 all_args.extend(unnest.expressions.iter().cloned());
71 let arrays_zip =
72 Expression::Function(Box::new(Function::new("ARRAYS_ZIP".to_string(), all_args)));
73 Expression::Function(Box::new(Function::new(
74 "INLINE".to_string(),
75 vec![arrays_zip],
76 )))
77 } else {
78 Expression::Explode(Box::new(UnaryFunc::new(unnest.this.clone())))
80 }
81}
82
83fn unnest_to_explode_select_inner(expr: Expression) -> Result<Expression> {
84 let Expression::Select(mut select) = expr else {
85 return Ok(expr);
86 };
87
88 if let Some(ref mut from) = select.from {
90 if from.expressions.len() >= 1 {
91 let mut new_from_exprs = Vec::new();
92 let mut new_lateral_views = Vec::new();
93 let first_is_unnest = is_unnest_expr(&from.expressions[0]);
94
95 for (idx, from_item) in from.expressions.drain(..).enumerate() {
96 if idx == 0 && first_is_unnest {
97 let replaced = replace_from_unnest(from_item);
100 new_from_exprs.push(replaced);
101 } else if idx > 0 && is_unnest_expr(&from_item) {
102 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(from_item);
104 let udtf = make_udtf_expr(&unnest_func);
105 new_lateral_views.push(LateralView {
106 this: udtf,
107 table_alias: alias_name,
108 column_aliases,
109 outer: false,
110 });
111 } else {
112 new_from_exprs.push(from_item);
113 }
114 }
115
116 from.expressions = new_from_exprs;
117 select.lateral_views.extend(new_lateral_views);
119 }
120 }
121
122 let mut remaining_joins = Vec::new();
124 for join in select.joins.drain(..) {
125 if matches!(join.kind, JoinKind::Cross | JoinKind::Inner) {
126 let (is_unnest, is_lateral) = check_join_unnest(&join.this);
127 if is_unnest {
128 let (lateral_alias, lateral_col_aliases, join_expr) = if is_lateral {
130 if let Expression::Lateral(lat) = join.this {
131 let alias = lat.alias.map(|s| Identifier::new(&s));
133 let col_aliases: Vec<Identifier> = lat
134 .column_aliases
135 .iter()
136 .map(|s| Identifier::new(s))
137 .collect();
138 (alias, col_aliases, *lat.this)
139 } else {
140 (None, Vec::new(), join.this)
141 }
142 } else {
143 (None, Vec::new(), join.this)
144 };
145
146 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(join_expr);
147
148 let final_alias = lateral_alias.or(alias_name);
150 let final_col_aliases = if !lateral_col_aliases.is_empty() {
151 lateral_col_aliases
152 } else {
153 column_aliases
154 };
155
156 let table_alias = final_alias.or_else(|| Some(Identifier::new("unnest")));
158 let col_aliases = if final_col_aliases.is_empty() {
159 vec![Identifier::new("unnest")]
160 } else {
161 final_col_aliases
162 };
163
164 let udtf = make_udtf_expr(&unnest_func);
165 select.lateral_views.push(LateralView {
166 this: udtf,
167 table_alias,
168 column_aliases: col_aliases,
169 outer: false,
170 });
171 } else {
172 remaining_joins.push(join);
173 }
174 } else {
175 remaining_joins.push(join);
176 }
177 }
178 select.joins = remaining_joins;
179
180 Ok(Expression::Select(select))
181}
182
183fn is_unnest_expr(expr: &Expression) -> bool {
185 match expr {
186 Expression::Unnest(_) => true,
187 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
188 _ => false,
189 }
190}
191
192fn check_join_unnest(expr: &Expression) -> (bool, bool) {
194 match expr {
195 Expression::Unnest(_) => (true, false),
196 Expression::Alias(a) => {
197 if matches!(a.this, Expression::Unnest(_)) {
198 (true, false)
199 } else {
200 (false, false)
201 }
202 }
203 Expression::Lateral(lat) => match &*lat.this {
204 Expression::Unnest(_) => (true, true),
205 Expression::Alias(a) => {
206 if matches!(a.this, Expression::Unnest(_)) {
207 (true, true)
208 } else {
209 (false, true)
210 }
211 }
212 _ => (false, true),
213 },
214 _ => (false, false),
215 }
216}
217
218fn replace_from_unnest(from_item: Expression) -> Expression {
220 match from_item {
221 Expression::Alias(mut a) => {
222 if let Expression::Unnest(unnest) = a.this {
223 a.this = make_udtf_expr(&unnest);
224 }
225 Expression::Alias(a)
226 }
227 Expression::Unnest(unnest) => make_udtf_expr(&unnest),
228 other => other,
229 }
230}
231
232fn extract_unnest_info(expr: Expression) -> (Option<Identifier>, Vec<Identifier>, UnnestFunc) {
234 match expr {
235 Expression::Alias(a) => {
236 if let Expression::Unnest(unnest) = a.this {
237 (Some(a.alias), a.column_aliases, *unnest)
238 } else {
239 (
241 Some(a.alias),
242 a.column_aliases,
243 UnnestFunc {
244 this: a.this,
245 expressions: Vec::new(),
246 with_ordinality: false,
247 alias: None,
248 offset_alias: None,
249 },
250 )
251 }
252 }
253 Expression::Unnest(unnest) => {
254 let alias = unnest.alias.clone();
255 (alias, Vec::new(), *unnest)
256 }
257 _ => (
258 None,
259 Vec::new(),
260 UnnestFunc {
261 this: expr,
262 expressions: Vec::new(),
263 with_ordinality: false,
264 alias: None,
265 offset_alias: None,
266 },
267 ),
268 }
269}
270
271pub fn explode_to_unnest(expr: Expression) -> Result<Expression> {
273 match expr {
274 Expression::Explode(explode) => Ok(Expression::Unnest(Box::new(UnnestFunc {
275 this: explode.this,
276 expressions: Vec::new(),
277 with_ordinality: false,
278 alias: None,
279 offset_alias: None,
280 }))),
281 _ => Ok(expr),
282 }
283}
284
285pub fn replace_bool_with_int(expr: Expression) -> Result<Expression> {
289 match expr {
290 Expression::Boolean(b) => {
291 let value = if b.value { "1" } else { "0" };
292 Ok(Expression::Literal(Box::new(Literal::Number(value.to_string()))))
293 }
294 _ => Ok(expr),
295 }
296}
297
298pub fn replace_int_with_bool(expr: Expression) -> Result<Expression> {
302 match expr {
303 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(n) if n == "1" || n == "0") => {
304 let Literal::Number(n) = lit.as_ref() else { unreachable!() };
305 Ok(Expression::Boolean(BooleanLiteral { value: n == "1" }))
306 }
307 _ => Ok(expr),
308 }
309}
310
311pub fn remove_precision_parameterized_types(expr: Expression) -> Result<Expression> {
316 Ok(strip_type_params_recursive(expr))
317}
318
319fn strip_type_params_recursive(expr: Expression) -> Expression {
321 match expr {
322 Expression::Cast(mut cast) => {
324 cast.to = strip_data_type_params(cast.to);
325 cast.this = strip_type_params_recursive(cast.this);
327 Expression::Cast(cast)
328 }
329 Expression::TryCast(mut try_cast) => {
331 try_cast.to = strip_data_type_params(try_cast.to);
332 try_cast.this = strip_type_params_recursive(try_cast.this);
333 Expression::TryCast(try_cast)
334 }
335 Expression::SafeCast(mut safe_cast) => {
337 safe_cast.to = strip_data_type_params(safe_cast.to);
338 safe_cast.this = strip_type_params_recursive(safe_cast.this);
339 Expression::SafeCast(safe_cast)
340 }
341 _ => expr,
344 }
345}
346
347fn strip_data_type_params(dt: DataType) -> DataType {
349 match dt {
350 DataType::Decimal { .. } => DataType::Decimal {
352 precision: None,
353 scale: None,
354 },
355 DataType::TinyInt { .. } => DataType::TinyInt { length: None },
356 DataType::SmallInt { .. } => DataType::SmallInt { length: None },
357 DataType::Int { .. } => DataType::Int {
358 length: None,
359 integer_spelling: false,
360 },
361 DataType::BigInt { .. } => DataType::BigInt { length: None },
362
363 DataType::Char { .. } => DataType::Char { length: None },
365 DataType::VarChar { .. } => DataType::VarChar {
366 length: None,
367 parenthesized_length: false,
368 },
369
370 DataType::Binary { .. } => DataType::Binary { length: None },
372 DataType::VarBinary { .. } => DataType::VarBinary { length: None },
373
374 DataType::Bit { .. } => DataType::Bit { length: None },
376 DataType::VarBit { .. } => DataType::VarBit { length: None },
377
378 DataType::Time { .. } => DataType::Time {
380 precision: None,
381 timezone: false,
382 },
383 DataType::Timestamp { timezone, .. } => DataType::Timestamp {
384 precision: None,
385 timezone,
386 },
387
388 DataType::Array {
390 element_type,
391 dimension,
392 } => DataType::Array {
393 element_type: Box::new(strip_data_type_params(*element_type)),
394 dimension,
395 },
396
397 DataType::Map {
399 key_type,
400 value_type,
401 } => DataType::Map {
402 key_type: Box::new(strip_data_type_params(*key_type)),
403 value_type: Box::new(strip_data_type_params(*value_type)),
404 },
405
406 DataType::Struct { fields, nested } => DataType::Struct {
408 fields: fields
409 .into_iter()
410 .map(|f| {
411 StructField::with_options(
412 f.name,
413 strip_data_type_params(f.data_type),
414 f.options,
415 )
416 })
417 .collect(),
418 nested,
419 },
420
421 DataType::Vector { element_type, .. } => DataType::Vector {
423 element_type: element_type.map(|et| Box::new(strip_data_type_params(*et))),
424 dimension: None,
425 },
426
427 DataType::Object { fields, modifier } => DataType::Object {
429 fields: fields
430 .into_iter()
431 .map(|(name, ty, not_null)| (name, strip_data_type_params(ty), not_null))
432 .collect(),
433 modifier,
434 },
435
436 other => other,
438 }
439}
440
441pub fn eliminate_qualify(expr: Expression) -> Result<Expression> {
456 match expr {
457 Expression::Select(mut select) => {
458 if let Some(qualify) = select.qualify.take() {
459 let qualify_filter = qualify.this;
466 let window_alias_name = "_w".to_string();
467 let window_alias_ident = Identifier::new(window_alias_name.clone());
468
469 let (window_expr, outer_where) =
472 extract_window_from_condition(qualify_filter.clone(), &window_alias_ident);
473
474 if let Some(win_expr) = window_expr {
475 let window_alias_expr =
477 Expression::Alias(Box::new(crate::expressions::Alias {
478 this: win_expr,
479 alias: window_alias_ident.clone(),
480 column_aliases: vec![],
481 pre_alias_comments: vec![],
482 trailing_comments: vec![],
483 inferred_type: None,
484 }));
485
486 let outer_exprs: Vec<Expression> = select
490 .expressions
491 .iter()
492 .map(|expr| {
493 if let Expression::Alias(a) = expr {
494 Expression::Column(Box::new(crate::expressions::Column {
496 name: a.alias.clone(),
497 table: None,
498 join_mark: false,
499 trailing_comments: vec![],
500 span: None,
501 inferred_type: None,
502 }))
503 } else {
504 expr.clone()
505 }
506 })
507 .collect();
508 select.expressions.push(window_alias_expr);
509
510 let inner_select = Expression::Select(select);
512 let subquery = Subquery {
513 this: inner_select,
514 alias: Some(Identifier::new("_t".to_string())),
515 column_aliases: vec![],
516 order_by: None,
517 limit: None,
518 offset: None,
519 distribute_by: None,
520 sort_by: None,
521 cluster_by: None,
522 lateral: false,
523 modifiers_inside: false,
524 trailing_comments: vec![],
525 inferred_type: None,
526 };
527
528 let outer_select = Select {
530 expressions: outer_exprs,
531 from: Some(From {
532 expressions: vec![Expression::Subquery(Box::new(subquery))],
533 }),
534 where_clause: Some(Where { this: outer_where }),
535 ..Select::new()
536 };
537
538 return Ok(Expression::Select(Box::new(outer_select)));
539 } else {
540 let qualify_alias = Expression::Alias(Box::new(crate::expressions::Alias {
542 this: qualify_filter.clone(),
543 alias: window_alias_ident.clone(),
544 column_aliases: vec![],
545 pre_alias_comments: vec![],
546 trailing_comments: vec![],
547 inferred_type: None,
548 }));
549
550 let original_exprs = select.expressions.clone();
551 select.expressions.push(qualify_alias);
552
553 let inner_select = Expression::Select(select);
554 let subquery = Subquery {
555 this: inner_select,
556 alias: Some(Identifier::new("_t".to_string())),
557 column_aliases: vec![],
558 order_by: None,
559 limit: None,
560 offset: None,
561 distribute_by: None,
562 sort_by: None,
563 cluster_by: None,
564 lateral: false,
565 modifiers_inside: false,
566 trailing_comments: vec![],
567 inferred_type: None,
568 };
569
570 let outer_select = Select {
571 expressions: original_exprs,
572 from: Some(From {
573 expressions: vec![Expression::Subquery(Box::new(subquery))],
574 }),
575 where_clause: Some(Where {
576 this: Expression::Column(Box::new(crate::expressions::Column {
577 name: window_alias_ident,
578 table: None,
579 join_mark: false,
580 trailing_comments: vec![],
581 span: None,
582 inferred_type: None,
583 })),
584 }),
585 ..Select::new()
586 };
587
588 return Ok(Expression::Select(Box::new(outer_select)));
589 }
590 }
591 Ok(Expression::Select(select))
592 }
593 other => Ok(other),
594 }
595}
596
597fn extract_window_from_condition(
601 condition: Expression,
602 alias: &Identifier,
603) -> (Option<Expression>, Expression) {
604 let alias_col = Expression::Column(Box::new(crate::expressions::Column {
605 name: alias.clone(),
606 table: None,
607 join_mark: false,
608 trailing_comments: vec![],
609 span: None,
610 inferred_type: None,
611 }));
612
613 match condition {
615 Expression::Eq(ref op) => {
617 if is_window_expr(&op.left) {
618 (
619 Some(op.left.clone()),
620 Expression::Eq(Box::new(BinaryOp {
621 left: alias_col,
622 right: op.right.clone(),
623 ..(**op).clone()
624 })),
625 )
626 } else if is_window_expr(&op.right) {
627 (
628 Some(op.right.clone()),
629 Expression::Eq(Box::new(BinaryOp {
630 left: op.left.clone(),
631 right: alias_col,
632 ..(**op).clone()
633 })),
634 )
635 } else {
636 (None, condition)
637 }
638 }
639 Expression::Neq(ref op) => {
640 if is_window_expr(&op.left) {
641 (
642 Some(op.left.clone()),
643 Expression::Neq(Box::new(BinaryOp {
644 left: alias_col,
645 right: op.right.clone(),
646 ..(**op).clone()
647 })),
648 )
649 } else if is_window_expr(&op.right) {
650 (
651 Some(op.right.clone()),
652 Expression::Neq(Box::new(BinaryOp {
653 left: op.left.clone(),
654 right: alias_col,
655 ..(**op).clone()
656 })),
657 )
658 } else {
659 (None, condition)
660 }
661 }
662 Expression::Lt(ref op) => {
663 if is_window_expr(&op.left) {
664 (
665 Some(op.left.clone()),
666 Expression::Lt(Box::new(BinaryOp {
667 left: alias_col,
668 right: op.right.clone(),
669 ..(**op).clone()
670 })),
671 )
672 } else if is_window_expr(&op.right) {
673 (
674 Some(op.right.clone()),
675 Expression::Lt(Box::new(BinaryOp {
676 left: op.left.clone(),
677 right: alias_col,
678 ..(**op).clone()
679 })),
680 )
681 } else {
682 (None, condition)
683 }
684 }
685 Expression::Lte(ref op) => {
686 if is_window_expr(&op.left) {
687 (
688 Some(op.left.clone()),
689 Expression::Lte(Box::new(BinaryOp {
690 left: alias_col,
691 right: op.right.clone(),
692 ..(**op).clone()
693 })),
694 )
695 } else if is_window_expr(&op.right) {
696 (
697 Some(op.right.clone()),
698 Expression::Lte(Box::new(BinaryOp {
699 left: op.left.clone(),
700 right: alias_col,
701 ..(**op).clone()
702 })),
703 )
704 } else {
705 (None, condition)
706 }
707 }
708 Expression::Gt(ref op) => {
709 if is_window_expr(&op.left) {
710 (
711 Some(op.left.clone()),
712 Expression::Gt(Box::new(BinaryOp {
713 left: alias_col,
714 right: op.right.clone(),
715 ..(**op).clone()
716 })),
717 )
718 } else if is_window_expr(&op.right) {
719 (
720 Some(op.right.clone()),
721 Expression::Gt(Box::new(BinaryOp {
722 left: op.left.clone(),
723 right: alias_col,
724 ..(**op).clone()
725 })),
726 )
727 } else {
728 (None, condition)
729 }
730 }
731 Expression::Gte(ref op) => {
732 if is_window_expr(&op.left) {
733 (
734 Some(op.left.clone()),
735 Expression::Gte(Box::new(BinaryOp {
736 left: alias_col,
737 right: op.right.clone(),
738 ..(**op).clone()
739 })),
740 )
741 } else if is_window_expr(&op.right) {
742 (
743 Some(op.right.clone()),
744 Expression::Gte(Box::new(BinaryOp {
745 left: op.left.clone(),
746 right: alias_col,
747 ..(**op).clone()
748 })),
749 )
750 } else {
751 (None, condition)
752 }
753 }
754 _ if is_window_expr(&condition) => (Some(condition), alias_col),
756 _ => (None, condition),
758 }
759}
760
761fn is_window_expr(expr: &Expression) -> bool {
763 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
764}
765
766pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
785 eliminate_distinct_on_for_dialect(expr, None)
786}
787
788pub fn eliminate_distinct_on_for_dialect(
793 expr: Expression,
794 target: Option<DialectType>,
795) -> Result<Expression> {
796 use crate::expressions::Case;
797
798 if matches!(
800 target,
801 Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)
802 ) {
803 return Ok(expr);
804 }
805
806 enum NullsMode {
811 None, NullsFirst, CaseExpr, }
815
816 let nulls_mode = match target {
817 Some(DialectType::MySQL)
818 | Some(DialectType::StarRocks)
819 | Some(DialectType::SingleStore)
820 | Some(DialectType::TSQL)
821 | Some(DialectType::Fabric) => NullsMode::CaseExpr,
822 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => {
823 NullsMode::None
824 }
825 _ => NullsMode::NullsFirst,
827 };
828
829 match expr {
830 Expression::Select(mut select) => {
831 if let Some(distinct_cols) = select.distinct_on.take() {
832 if !distinct_cols.is_empty() {
833 let row_number_alias = Identifier::new("_row_number".to_string());
835
836 let order_exprs = if let Some(ref order_by) = select.order_by {
838 let mut exprs = order_by.expressions.clone();
839 match nulls_mode {
841 NullsMode::NullsFirst => {
842 for ord in &mut exprs {
843 if ord.desc && ord.nulls_first.is_none() {
844 ord.nulls_first = Some(true);
845 }
846 }
847 }
848 NullsMode::CaseExpr => {
849 let mut new_exprs = Vec::new();
852 for ord in &exprs {
853 if ord.desc && ord.nulls_first.is_none() {
854 let null_check = Expression::Case(Box::new(Case {
856 operand: None,
857 whens: vec![(
858 Expression::IsNull(Box::new(
859 crate::expressions::IsNull {
860 this: ord.this.clone(),
861 not: false,
862 postfix_form: false,
863 },
864 )),
865 Expression::Literal(Box::new(Literal::Number(
866 "1".to_string(),
867 ))),
868 )],
869 else_: Some(Expression::Literal(Box::new(Literal::Number(
870 "0".to_string(),
871 )))),
872 comments: Vec::new(),
873 inferred_type: None,
874 }));
875 new_exprs.push(crate::expressions::Ordered {
876 this: null_check,
877 desc: true,
878 nulls_first: None,
879 explicit_asc: false,
880 with_fill: None,
881 });
882 }
883 new_exprs.push(ord.clone());
884 }
885 exprs = new_exprs;
886 }
887 NullsMode::None => {}
888 }
889 exprs
890 } else {
891 distinct_cols
892 .iter()
893 .map(|e| crate::expressions::Ordered {
894 this: e.clone(),
895 desc: false,
896 nulls_first: None,
897 explicit_asc: false,
898 with_fill: None,
899 })
900 .collect()
901 };
902
903 let row_number_func =
905 Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
906 this: Expression::RowNumber(crate::expressions::RowNumber),
907 over: Over {
908 partition_by: distinct_cols,
909 order_by: order_exprs,
910 frame: None,
911 window_name: None,
912 alias: None,
913 },
914 keep: None,
915 inferred_type: None,
916 }));
917
918 let mut inner_aliased_exprs = Vec::new();
922 let mut outer_select_exprs = Vec::new();
923 for orig_expr in &select.expressions {
924 match orig_expr {
925 Expression::Alias(alias) => {
926 inner_aliased_exprs.push(orig_expr.clone());
928 outer_select_exprs.push(Expression::Column(
929 Box::new(crate::expressions::Column {
930 name: alias.alias.clone(),
931 table: None,
932 join_mark: false,
933 trailing_comments: vec![],
934 span: None,
935 inferred_type: None,
936 }),
937 ));
938 }
939 Expression::Column(col) => {
940 inner_aliased_exprs.push(Expression::Alias(Box::new(
942 crate::expressions::Alias {
943 this: orig_expr.clone(),
944 alias: col.name.clone(),
945 column_aliases: vec![],
946 pre_alias_comments: vec![],
947 trailing_comments: vec![],
948 inferred_type: None,
949 },
950 )));
951 outer_select_exprs.push(Expression::Column(
952 Box::new(crate::expressions::Column {
953 name: col.name.clone(),
954 table: None,
955 join_mark: false,
956 trailing_comments: vec![],
957 span: None,
958 inferred_type: None,
959 }),
960 ));
961 }
962 _ => {
963 inner_aliased_exprs.push(orig_expr.clone());
965 outer_select_exprs.push(orig_expr.clone());
966 }
967 }
968 }
969
970 let row_number_alias_expr =
972 Expression::Alias(Box::new(crate::expressions::Alias {
973 this: row_number_func,
974 alias: row_number_alias.clone(),
975 column_aliases: vec![],
976 pre_alias_comments: vec![],
977 trailing_comments: vec![],
978 inferred_type: None,
979 }));
980 inner_aliased_exprs.push(row_number_alias_expr);
981
982 select.expressions = inner_aliased_exprs;
984
985 let _inner_order_by = select.order_by.take();
987
988 select.distinct = false;
990
991 let inner_select = Expression::Select(select);
993 let subquery = Subquery {
994 this: inner_select,
995 alias: Some(Identifier::new("_t".to_string())),
996 column_aliases: vec![],
997 order_by: None,
998 limit: None,
999 offset: None,
1000 distribute_by: None,
1001 sort_by: None,
1002 cluster_by: None,
1003 lateral: false,
1004 modifiers_inside: false,
1005 trailing_comments: vec![],
1006 inferred_type: None,
1007 };
1008
1009 let outer_select = Select {
1012 expressions: outer_select_exprs,
1013 from: Some(From {
1014 expressions: vec![Expression::Subquery(Box::new(subquery))],
1015 }),
1016 where_clause: Some(Where {
1017 this: Expression::Eq(Box::new(BinaryOp {
1018 left: Expression::Column(Box::new(crate::expressions::Column {
1019 name: row_number_alias,
1020 table: None,
1021 join_mark: false,
1022 trailing_comments: vec![],
1023 span: None,
1024 inferred_type: None,
1025 })),
1026 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
1027 left_comments: vec![],
1028 operator_comments: vec![],
1029 trailing_comments: vec![],
1030 inferred_type: None,
1031 })),
1032 }),
1033 ..Select::new()
1034 };
1035
1036 return Ok(Expression::Select(Box::new(outer_select)));
1037 }
1038 }
1039 Ok(Expression::Select(select))
1040 }
1041 other => Ok(other),
1042 }
1043}
1044
1045pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
1053 match expr {
1054 Expression::Select(mut select) => {
1055 let mut new_joins = Vec::new();
1056 let mut extra_where_conditions = Vec::new();
1057
1058 for join in select.joins.drain(..) {
1059 match join.kind {
1060 JoinKind::Semi | JoinKind::LeftSemi => {
1061 if let Some(on_condition) = join.on {
1062 let subquery_select = Select {
1064 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1065 "1".to_string(),
1066 )))],
1067 from: Some(From {
1068 expressions: vec![join.this],
1069 }),
1070 where_clause: Some(Where { this: on_condition }),
1071 ..Select::new()
1072 };
1073
1074 let exists = Expression::Exists(Box::new(Exists {
1075 this: Expression::Subquery(Box::new(Subquery {
1076 this: Expression::Select(Box::new(subquery_select)),
1077 alias: None,
1078 column_aliases: vec![],
1079 order_by: None,
1080 limit: None,
1081 offset: None,
1082 distribute_by: None,
1083 sort_by: None,
1084 cluster_by: None,
1085 lateral: false,
1086 modifiers_inside: false,
1087 trailing_comments: vec![],
1088 inferred_type: None,
1089 })),
1090 not: false,
1091 }));
1092
1093 extra_where_conditions.push(exists);
1094 }
1095 }
1096 JoinKind::Anti | JoinKind::LeftAnti => {
1097 if let Some(on_condition) = join.on {
1098 let subquery_select = Select {
1100 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1101 "1".to_string(),
1102 )))],
1103 from: Some(From {
1104 expressions: vec![join.this],
1105 }),
1106 where_clause: Some(Where { this: on_condition }),
1107 ..Select::new()
1108 };
1109
1110 let not_exists = Expression::Exists(Box::new(Exists {
1112 this: Expression::Subquery(Box::new(Subquery {
1113 this: Expression::Select(Box::new(subquery_select)),
1114 alias: None,
1115 column_aliases: vec![],
1116 order_by: None,
1117 limit: None,
1118 offset: None,
1119 distribute_by: None,
1120 sort_by: None,
1121 cluster_by: None,
1122 lateral: false,
1123 modifiers_inside: false,
1124 trailing_comments: vec![],
1125 inferred_type: None,
1126 })),
1127 not: true,
1128 }));
1129
1130 extra_where_conditions.push(not_exists);
1131 }
1132 }
1133 _ => {
1134 new_joins.push(join);
1136 }
1137 }
1138 }
1139
1140 select.joins = new_joins;
1141
1142 if !extra_where_conditions.is_empty() {
1144 let combined = extra_where_conditions
1145 .into_iter()
1146 .reduce(|acc, cond| {
1147 Expression::And(Box::new(BinaryOp {
1148 left: acc,
1149 right: cond,
1150 left_comments: vec![],
1151 operator_comments: vec![],
1152 trailing_comments: vec![],
1153 inferred_type: None,
1154 }))
1155 })
1156 .unwrap();
1157
1158 select.where_clause = match select.where_clause {
1159 Some(Where { this: existing }) => Some(Where {
1160 this: Expression::And(Box::new(BinaryOp {
1161 left: existing,
1162 right: combined,
1163 left_comments: vec![],
1164 operator_comments: vec![],
1165 trailing_comments: vec![],
1166 inferred_type: None,
1167 })),
1168 }),
1169 None => Some(Where { this: combined }),
1170 };
1171 }
1172
1173 Ok(Expression::Select(select))
1174 }
1175 other => Ok(other),
1176 }
1177}
1178
1179pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
1197 match expr {
1198 Expression::Select(mut select) => {
1199 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
1201
1202 if let Some(idx) = full_outer_join_idx {
1203 let full_join_count = select
1205 .joins
1206 .iter()
1207 .filter(|j| j.kind == JoinKind::Full)
1208 .count();
1209 if full_join_count != 1 {
1210 return Ok(Expression::Select(select));
1211 }
1212
1213 let mut right_select = select.clone();
1215
1216 let full_join = &select.joins[idx];
1218 let join_condition = full_join.on.clone();
1219
1220 select.joins[idx].kind = JoinKind::Left;
1222
1223 right_select.joins[idx].kind = JoinKind::Right;
1225
1226 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
1228 if !from.expressions.is_empty() {
1229 let anti_subquery = Expression::Select(Box::new(Select {
1230 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1231 "1".to_string(),
1232 )))],
1233 from: Some(from.clone()),
1234 where_clause: Some(Where {
1235 this: join_cond.clone(),
1236 }),
1237 ..Select::new()
1238 }));
1239
1240 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
1241 inferred_type: None,
1242 this: Expression::Exists(Box::new(Exists {
1243 this: Expression::Subquery(Box::new(Subquery {
1244 this: anti_subquery,
1245 alias: None,
1246 column_aliases: vec![],
1247 order_by: None,
1248 limit: None,
1249 offset: None,
1250 distribute_by: None,
1251 sort_by: None,
1252 cluster_by: None,
1253 lateral: false,
1254 modifiers_inside: false,
1255 trailing_comments: vec![],
1256 inferred_type: None,
1257 })),
1258 not: false,
1259 })),
1260 }));
1261
1262 right_select.where_clause = Some(Where {
1264 this: match right_select.where_clause {
1265 Some(w) => Expression::And(Box::new(BinaryOp {
1266 left: w.this,
1267 right: not_exists,
1268 left_comments: vec![],
1269 operator_comments: vec![],
1270 trailing_comments: vec![],
1271 inferred_type: None,
1272 })),
1273 None => not_exists,
1274 },
1275 });
1276 }
1277 }
1278
1279 right_select.with = None;
1281
1282 let order_by = select.order_by.take();
1284
1285 let union = crate::expressions::Union {
1287 left: Expression::Select(select),
1288 right: Expression::Select(right_select),
1289 all: true, distinct: false,
1291 with: None,
1292 order_by,
1293 limit: None,
1294 offset: None,
1295 distribute_by: None,
1296 sort_by: None,
1297 cluster_by: None,
1298 by_name: false,
1299 side: None,
1300 kind: None,
1301 corresponding: false,
1302 strict: false,
1303 on_columns: Vec::new(),
1304 };
1305
1306 return Ok(Expression::Union(Box::new(union)));
1307 }
1308
1309 Ok(Expression::Select(select))
1310 }
1311 other => Ok(other),
1312 }
1313}
1314
1315pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
1328 match expr {
1329 Expression::Select(mut select) => {
1330 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
1332 let mut has_recursive = false;
1333
1334 collect_nested_ctes(
1335 &Expression::Select(select.clone()),
1336 &mut collected_ctes,
1337 &mut has_recursive,
1338 true,
1339 );
1340
1341 let mut cte_body_collected: Vec<(String, Vec<crate::expressions::Cte>)> = Vec::new();
1344 if let Some(ref with) = select.with {
1345 for cte in &with.ctes {
1346 let mut body_ctes: Vec<crate::expressions::Cte> = Vec::new();
1347 collect_ctes_from_cte_body(&cte.this, &mut body_ctes, &mut has_recursive);
1348 if !body_ctes.is_empty() {
1349 cte_body_collected.push((cte.alias.name.clone(), body_ctes));
1350 }
1351 }
1352 }
1353
1354 let has_subquery_ctes = !collected_ctes.is_empty();
1355 let has_body_ctes = !cte_body_collected.is_empty();
1356
1357 if has_subquery_ctes || has_body_ctes {
1358 strip_nested_with_clauses(&mut select, true);
1360
1361 if has_body_ctes {
1363 if let Some(ref mut with) = select.with {
1364 for cte in with.ctes.iter_mut() {
1365 strip_with_from_cte_body(&mut cte.this);
1366 }
1367 }
1368 }
1369
1370 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
1371 ctes: Vec::new(),
1372 recursive: false,
1373 leading_comments: vec![],
1374 search: None,
1375 });
1376
1377 if has_recursive {
1378 top_with.recursive = true;
1379 }
1380
1381 if has_body_ctes {
1383 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
1384 for mut cte in top_with.ctes.drain(..) {
1385 if let Some(pos) = cte_body_collected
1387 .iter()
1388 .position(|(name, _)| *name == cte.alias.name)
1389 {
1390 let (_, mut nested) = cte_body_collected.remove(pos);
1391 for nested_cte in nested.iter_mut() {
1393 strip_with_from_cte_body(&mut nested_cte.this);
1394 }
1395 new_ctes.extend(nested);
1396 }
1397 strip_with_from_cte_body(&mut cte.this);
1399 new_ctes.push(cte);
1400 }
1401 top_with.ctes = new_ctes;
1402 }
1403
1404 top_with.ctes.extend(collected_ctes);
1406 }
1407
1408 Ok(Expression::Select(select))
1409 }
1410 other => Ok(other),
1411 }
1412}
1413
1414fn collect_ctes_from_cte_body(
1416 expr: &Expression,
1417 collected: &mut Vec<crate::expressions::Cte>,
1418 has_recursive: &mut bool,
1419) {
1420 if let Expression::Select(select) = expr {
1421 if let Some(ref with) = select.with {
1422 if with.recursive {
1423 *has_recursive = true;
1424 }
1425 for cte in &with.ctes {
1426 collect_ctes_from_cte_body(&cte.this, collected, has_recursive);
1428 collected.push(cte.clone());
1430 }
1431 }
1432 }
1433}
1434
1435fn strip_with_from_cte_body(expr: &mut Expression) {
1437 if let Expression::Select(ref mut select) = expr {
1438 select.with = None;
1439 }
1440}
1441
1442fn strip_nested_with_clauses(select: &mut Select, _is_top_level: bool) {
1444 if let Some(ref mut from) = select.from {
1446 for expr in from.expressions.iter_mut() {
1447 strip_with_from_expr(expr);
1448 }
1449 }
1450 for join in select.joins.iter_mut() {
1452 strip_with_from_expr(&mut join.this);
1453 }
1454 for expr in select.expressions.iter_mut() {
1456 strip_with_from_expr(expr);
1457 }
1458 if let Some(ref mut w) = select.where_clause {
1460 strip_with_from_expr(&mut w.this);
1461 }
1462}
1463
1464fn strip_with_from_expr(expr: &mut Expression) {
1465 match expr {
1466 Expression::Subquery(ref mut subquery) => {
1467 strip_with_from_inner_query(&mut subquery.this);
1468 }
1469 Expression::Alias(ref mut alias) => {
1470 strip_with_from_expr(&mut alias.this);
1471 }
1472 Expression::Select(ref mut select) => {
1473 select.with = None;
1475 strip_nested_with_clauses(select, false);
1477 }
1478 _ => {}
1479 }
1480}
1481
1482fn strip_with_from_inner_query(expr: &mut Expression) {
1483 if let Expression::Select(ref mut select) = expr {
1484 select.with = None;
1485 strip_nested_with_clauses(select, false);
1486 }
1487}
1488
1489fn collect_nested_ctes(
1491 expr: &Expression,
1492 collected: &mut Vec<crate::expressions::Cte>,
1493 has_recursive: &mut bool,
1494 is_top_level: bool,
1495) {
1496 match expr {
1497 Expression::Select(select) => {
1498 if !is_top_level {
1500 if let Some(ref with) = select.with {
1501 if with.recursive {
1502 *has_recursive = true;
1503 }
1504 collected.extend(with.ctes.clone());
1505 }
1506 }
1507
1508 if let Some(ref from) = select.from {
1510 for expr in &from.expressions {
1511 collect_nested_ctes(expr, collected, has_recursive, false);
1512 }
1513 }
1514
1515 for join in &select.joins {
1517 collect_nested_ctes(&join.this, collected, has_recursive, false);
1518 }
1519
1520 for sel_expr in &select.expressions {
1522 collect_nested_ctes(sel_expr, collected, has_recursive, false);
1523 }
1524
1525 if let Some(ref where_clause) = select.where_clause {
1527 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
1528 }
1529 }
1530 Expression::Subquery(subquery) => {
1531 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
1533 }
1534 Expression::Alias(alias) => {
1535 collect_nested_ctes(&alias.this, collected, has_recursive, false);
1536 }
1537 _ => {}
1539 }
1540}
1541
1542pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
1558 match expr {
1559 Expression::Select(mut select) => {
1560 if let Some(named_windows) = select.windows.take() {
1561 let window_map: std::collections::HashMap<String, &Over> = named_windows
1563 .iter()
1564 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
1565 .collect();
1566
1567 select.expressions = select
1569 .expressions
1570 .into_iter()
1571 .map(|e| inline_window_refs(e, &window_map))
1572 .collect();
1573 }
1574 Ok(Expression::Select(select))
1575 }
1576 other => Ok(other),
1577 }
1578}
1579
1580fn inline_window_refs(
1582 expr: Expression,
1583 window_map: &std::collections::HashMap<String, &Over>,
1584) -> Expression {
1585 match expr {
1586 Expression::WindowFunction(mut wf) => {
1587 if let Some(ref name) = wf.over.window_name {
1589 let key = name.name.to_lowercase();
1590 if let Some(named_spec) = window_map.get(&key) {
1591 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
1593 wf.over.partition_by = named_spec.partition_by.clone();
1594 }
1595 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
1596 wf.over.order_by = named_spec.order_by.clone();
1597 }
1598 if wf.over.frame.is_none() && named_spec.frame.is_some() {
1599 wf.over.frame = named_spec.frame.clone();
1600 }
1601 wf.over.window_name = None;
1603 }
1604 }
1605 Expression::WindowFunction(wf)
1606 }
1607 Expression::Alias(mut alias) => {
1608 alias.this = inline_window_refs(alias.this, window_map);
1610 Expression::Alias(alias)
1611 }
1612 other => other,
1615 }
1616}
1617
1618pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
1632 match expr {
1633 Expression::Select(mut select) => {
1634 let has_join_marks = select
1636 .where_clause
1637 .as_ref()
1638 .map_or(false, |w| contains_join_mark(&w.this));
1639
1640 if !has_join_marks {
1641 return Ok(Expression::Select(select));
1642 }
1643
1644 let from_tables: Vec<String> = select
1646 .from
1647 .as_ref()
1648 .map(|f| {
1649 f.expressions
1650 .iter()
1651 .filter_map(|e| get_table_name(e))
1652 .collect()
1653 })
1654 .unwrap_or_default();
1655
1656 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
1658 std::collections::HashMap::new();
1659 let mut remaining_conditions: Vec<Expression> = Vec::new();
1660
1661 if let Some(ref where_clause) = select.where_clause {
1662 extract_join_mark_conditions(
1663 &where_clause.this,
1664 &mut join_conditions,
1665 &mut remaining_conditions,
1666 );
1667 }
1668
1669 let mut new_joins = select.joins.clone();
1671 for (table_name, conditions) in join_conditions {
1672 let table_in_from = from_tables.contains(&table_name);
1674
1675 if table_in_from && !conditions.is_empty() {
1676 let combined_condition = conditions.into_iter().reduce(|a, b| {
1678 Expression::And(Box::new(BinaryOp {
1679 left: a,
1680 right: b,
1681 left_comments: vec![],
1682 operator_comments: vec![],
1683 trailing_comments: vec![],
1684 inferred_type: None,
1685 }))
1686 });
1687
1688 if let Some(ref mut from) = select.from {
1690 if let Some(pos) = from
1691 .expressions
1692 .iter()
1693 .position(|e| get_table_name(e).map_or(false, |n| n == table_name))
1694 {
1695 if from.expressions.len() > 1 {
1696 let join_table = from.expressions.remove(pos);
1697 new_joins.push(crate::expressions::Join {
1698 this: join_table,
1699 kind: JoinKind::Left,
1700 on: combined_condition,
1701 using: vec![],
1702 use_inner_keyword: false,
1703 use_outer_keyword: true,
1704 deferred_condition: false,
1705 join_hint: None,
1706 match_condition: None,
1707 pivots: Vec::new(),
1708 comments: Vec::new(),
1709 nesting_group: 0,
1710 directed: false,
1711 });
1712 }
1713 }
1714 }
1715 }
1716 }
1717
1718 select.joins = new_joins;
1719
1720 if remaining_conditions.is_empty() {
1722 select.where_clause = None;
1723 } else {
1724 let combined = remaining_conditions.into_iter().reduce(|a, b| {
1725 Expression::And(Box::new(BinaryOp {
1726 left: a,
1727 right: b,
1728 left_comments: vec![],
1729 operator_comments: vec![],
1730 trailing_comments: vec![],
1731 inferred_type: None,
1732 }))
1733 });
1734 select.where_clause = combined.map(|c| Where { this: c });
1735 }
1736
1737 clear_join_marks(&mut Expression::Select(select.clone()));
1739
1740 Ok(Expression::Select(select))
1741 }
1742 other => Ok(other),
1743 }
1744}
1745
1746fn contains_join_mark(expr: &Expression) -> bool {
1748 match expr {
1749 Expression::Column(col) => col.join_mark,
1750 Expression::And(op) | Expression::Or(op) => {
1751 contains_join_mark(&op.left) || contains_join_mark(&op.right)
1752 }
1753 Expression::Eq(op)
1754 | Expression::Neq(op)
1755 | Expression::Lt(op)
1756 | Expression::Lte(op)
1757 | Expression::Gt(op)
1758 | Expression::Gte(op) => contains_join_mark(&op.left) || contains_join_mark(&op.right),
1759 Expression::Not(op) => contains_join_mark(&op.this),
1760 _ => false,
1761 }
1762}
1763
1764fn get_table_name(expr: &Expression) -> Option<String> {
1766 match expr {
1767 Expression::Table(t) => Some(t.name.name.clone()),
1768 Expression::Alias(a) => Some(a.alias.name.clone()),
1769 _ => None,
1770 }
1771}
1772
1773fn extract_join_mark_conditions(
1775 expr: &Expression,
1776 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
1777 remaining: &mut Vec<Expression>,
1778) {
1779 match expr {
1780 Expression::And(op) => {
1781 extract_join_mark_conditions(&op.left, join_conditions, remaining);
1782 extract_join_mark_conditions(&op.right, join_conditions, remaining);
1783 }
1784 _ => {
1785 if let Some(table) = get_join_mark_table(expr) {
1786 join_conditions
1787 .entry(table)
1788 .or_insert_with(Vec::new)
1789 .push(expr.clone());
1790 } else {
1791 remaining.push(expr.clone());
1792 }
1793 }
1794 }
1795}
1796
1797fn get_join_mark_table(expr: &Expression) -> Option<String> {
1799 match expr {
1800 Expression::Eq(op)
1801 | Expression::Neq(op)
1802 | Expression::Lt(op)
1803 | Expression::Lte(op)
1804 | Expression::Gt(op)
1805 | Expression::Gte(op) => {
1806 if let Expression::Column(col) = &op.left {
1808 if col.join_mark {
1809 return col.table.as_ref().map(|t| t.name.clone());
1810 }
1811 }
1812 if let Expression::Column(col) = &op.right {
1813 if col.join_mark {
1814 return col.table.as_ref().map(|t| t.name.clone());
1815 }
1816 }
1817 None
1818 }
1819 _ => None,
1820 }
1821}
1822
1823fn clear_join_marks(expr: &mut Expression) {
1825 match expr {
1826 Expression::Column(col) => col.join_mark = false,
1827 Expression::Select(select) => {
1828 if let Some(ref mut w) = select.where_clause {
1829 clear_join_marks(&mut w.this);
1830 }
1831 for sel_expr in &mut select.expressions {
1832 clear_join_marks(sel_expr);
1833 }
1834 }
1835 Expression::And(op) | Expression::Or(op) => {
1836 clear_join_marks(&mut op.left);
1837 clear_join_marks(&mut op.right);
1838 }
1839 Expression::Eq(op)
1840 | Expression::Neq(op)
1841 | Expression::Lt(op)
1842 | Expression::Lte(op)
1843 | Expression::Gt(op)
1844 | Expression::Gte(op) => {
1845 clear_join_marks(&mut op.left);
1846 clear_join_marks(&mut op.right);
1847 }
1848 _ => {}
1849 }
1850}
1851
1852pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
1859 match expr {
1860 Expression::Select(mut select) => {
1861 if let Some(ref mut with) = select.with {
1862 if with.recursive {
1863 let mut counter = 0;
1864 for cte in &mut with.ctes {
1865 if cte.columns.is_empty() {
1866 if let Expression::Select(ref cte_select) = cte.this {
1868 let names: Vec<Identifier> = cte_select
1869 .expressions
1870 .iter()
1871 .map(|e| match e {
1872 Expression::Alias(a) => a.alias.clone(),
1873 Expression::Column(c) => c.name.clone(),
1874 _ => {
1875 counter += 1;
1876 Identifier::new(format!("_c_{}", counter))
1877 }
1878 })
1879 .collect();
1880 cte.columns = names;
1881 }
1882 }
1883 }
1884 }
1885 }
1886 Ok(Expression::Select(select))
1887 }
1888 other => Ok(other),
1889 }
1890}
1891
1892pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
1899 match expr {
1900 Expression::Cast(mut cast) => {
1901 if let Expression::Literal(ref lit) = cast.this {
1902 if let Literal::String(ref s) = lit.as_ref() {
1903 if s.to_lowercase() == "epoch" {
1904 if is_temporal_type(&cast.to) {
1905 cast.this =
1906 Expression::Literal(Box::new(Literal::String("1970-01-01 00:00:00".to_string())));
1907 }
1908 }
1909 }
1910 }
1911 Ok(Expression::Cast(cast))
1912 }
1913 Expression::TryCast(mut try_cast) => {
1914 if let Expression::Literal(ref lit) = try_cast.this {
1915 if let Literal::String(ref s) = lit.as_ref() {
1916 if s.to_lowercase() == "epoch" {
1917 if is_temporal_type(&try_cast.to) {
1918 try_cast.this =
1919 Expression::Literal(Box::new(Literal::String("1970-01-01 00:00:00".to_string())));
1920 }
1921 }
1922 }
1923 }
1924 Ok(Expression::TryCast(try_cast))
1925 }
1926 other => Ok(other),
1927 }
1928}
1929
1930fn is_temporal_type(dt: &DataType) -> bool {
1932 matches!(
1933 dt,
1934 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
1935 )
1936}
1937
1938pub fn ensure_bools(expr: Expression) -> Result<Expression> {
1963 let expr = ensure_bools_in_case(expr);
1965 match expr {
1966 Expression::Select(mut select) => {
1967 if let Some(ref mut where_clause) = select.where_clause {
1969 where_clause.this = ensure_bool_condition(where_clause.this.clone());
1970 }
1971 if let Some(ref mut having) = select.having {
1973 having.this = ensure_bool_condition(having.this.clone());
1974 }
1975 Ok(Expression::Select(select))
1976 }
1977 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => {
1979 Ok(ensure_bool_condition(expr))
1980 }
1981 other => Ok(other),
1982 }
1983}
1984
1985fn ensure_bools_in_case(expr: Expression) -> Expression {
1989 match expr {
1990 Expression::Case(mut case) => {
1991 case.whens = case
1992 .whens
1993 .into_iter()
1994 .map(|(condition, result)| {
1995 let new_condition = ensure_bool_condition(ensure_bools_in_case(condition));
1996 let new_result = ensure_bools_in_case(result);
1997 (new_condition, new_result)
1998 })
1999 .collect();
2000 if let Some(else_expr) = case.else_ {
2001 case.else_ = Some(ensure_bools_in_case(else_expr));
2002 }
2003 Expression::Case(Box::new(*case))
2004 }
2005 Expression::Select(mut select) => {
2006 select.expressions = select
2008 .expressions
2009 .into_iter()
2010 .map(ensure_bools_in_case)
2011 .collect();
2012 Expression::Select(select)
2014 }
2015 Expression::Alias(mut alias) => {
2016 alias.this = ensure_bools_in_case(alias.this);
2017 Expression::Alias(alias)
2018 }
2019 Expression::Paren(mut paren) => {
2020 paren.this = ensure_bools_in_case(paren.this);
2021 Expression::Paren(paren)
2022 }
2023 other => other,
2024 }
2025}
2026
2027fn is_boolean_expression(expr: &Expression) -> bool {
2030 matches!(
2031 expr,
2032 Expression::Eq(_)
2033 | Expression::Neq(_)
2034 | Expression::Lt(_)
2035 | Expression::Lte(_)
2036 | Expression::Gt(_)
2037 | Expression::Gte(_)
2038 | Expression::Is(_)
2039 | Expression::IsNull(_)
2040 | Expression::IsTrue(_)
2041 | Expression::IsFalse(_)
2042 | Expression::Like(_)
2043 | Expression::ILike(_)
2044 | Expression::SimilarTo(_)
2045 | Expression::Glob(_)
2046 | Expression::RegexpLike(_)
2047 | Expression::In(_)
2048 | Expression::Between(_)
2049 | Expression::Exists(_)
2050 | Expression::And(_)
2051 | Expression::Or(_)
2052 | Expression::Not(_)
2053 | Expression::Any(_)
2054 | Expression::All(_)
2055 | Expression::EqualNull(_)
2056 )
2057}
2058
2059fn wrap_neq_zero(expr: Expression) -> Expression {
2061 Expression::Neq(Box::new(BinaryOp {
2062 left: expr,
2063 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2064 left_comments: vec![],
2065 operator_comments: vec![],
2066 trailing_comments: vec![],
2067 inferred_type: None,
2068 }))
2069}
2070
2071fn ensure_bool_condition(expr: Expression) -> Expression {
2077 match expr {
2078 Expression::And(op) => {
2080 let new_op = BinaryOp {
2081 left: ensure_bool_condition(op.left.clone()),
2082 right: ensure_bool_condition(op.right.clone()),
2083 left_comments: op.left_comments.clone(),
2084 operator_comments: op.operator_comments.clone(),
2085 trailing_comments: op.trailing_comments.clone(),
2086 inferred_type: None,
2087 };
2088 Expression::And(Box::new(new_op))
2089 }
2090 Expression::Or(op) => {
2091 let new_op = BinaryOp {
2092 left: ensure_bool_condition(op.left.clone()),
2093 right: ensure_bool_condition(op.right.clone()),
2094 left_comments: op.left_comments.clone(),
2095 operator_comments: op.operator_comments.clone(),
2096 trailing_comments: op.trailing_comments.clone(),
2097 inferred_type: None,
2098 };
2099 Expression::Or(Box::new(new_op))
2100 }
2101 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
2103 this: ensure_bool_condition(op.this.clone()),
2104 inferred_type: None,
2105 })),
2106 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
2108 this: ensure_bool_condition(paren.this.clone()),
2109 trailing_comments: paren.trailing_comments.clone(),
2110 })),
2111 Expression::Boolean(BooleanLiteral { value: true }) => {
2113 Expression::Paren(Box::new(crate::expressions::Paren {
2114 this: Expression::Eq(Box::new(BinaryOp {
2115 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2116 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2117 left_comments: vec![],
2118 operator_comments: vec![],
2119 trailing_comments: vec![],
2120 inferred_type: None,
2121 })),
2122 trailing_comments: vec![],
2123 }))
2124 }
2125 Expression::Boolean(BooleanLiteral { value: false }) => {
2126 Expression::Paren(Box::new(crate::expressions::Paren {
2127 this: Expression::Eq(Box::new(BinaryOp {
2128 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2129 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2130 left_comments: vec![],
2131 operator_comments: vec![],
2132 trailing_comments: vec![],
2133 inferred_type: None,
2134 })),
2135 trailing_comments: vec![],
2136 }))
2137 }
2138 ref e if is_boolean_expression(e) => expr,
2140 _ => wrap_neq_zero(expr),
2143 }
2144}
2145
2146pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
2152 Ok(unqualify_columns_recursive(expr))
2153}
2154
2155fn unqualify_columns_recursive(expr: Expression) -> Expression {
2157 match expr {
2158 Expression::Column(mut col) => {
2159 col.table = None;
2160 Expression::Column(col)
2161 }
2162 Expression::Select(mut select) => {
2163 select.expressions = select
2164 .expressions
2165 .into_iter()
2166 .map(unqualify_columns_recursive)
2167 .collect();
2168 if let Some(ref mut where_clause) = select.where_clause {
2169 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
2170 }
2171 if let Some(ref mut having) = select.having {
2172 having.this = unqualify_columns_recursive(having.this.clone());
2173 }
2174 if let Some(ref mut group_by) = select.group_by {
2175 group_by.expressions = group_by
2176 .expressions
2177 .iter()
2178 .cloned()
2179 .map(unqualify_columns_recursive)
2180 .collect();
2181 }
2182 if let Some(ref mut order_by) = select.order_by {
2183 order_by.expressions = order_by
2184 .expressions
2185 .iter()
2186 .map(|o| crate::expressions::Ordered {
2187 this: unqualify_columns_recursive(o.this.clone()),
2188 desc: o.desc,
2189 nulls_first: o.nulls_first,
2190 explicit_asc: o.explicit_asc,
2191 with_fill: o.with_fill.clone(),
2192 })
2193 .collect();
2194 }
2195 for join in &mut select.joins {
2196 if let Some(ref mut on) = join.on {
2197 *on = unqualify_columns_recursive(on.clone());
2198 }
2199 }
2200 Expression::Select(select)
2201 }
2202 Expression::Alias(mut alias) => {
2203 alias.this = unqualify_columns_recursive(alias.this);
2204 Expression::Alias(alias)
2205 }
2206 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
2208 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
2209 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
2210 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
2211 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
2212 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
2213 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
2214 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
2215 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
2216 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
2217 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
2218 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
2219 Expression::Function(mut func) => {
2221 func.args = func
2222 .args
2223 .into_iter()
2224 .map(unqualify_columns_recursive)
2225 .collect();
2226 Expression::Function(func)
2227 }
2228 Expression::AggregateFunction(mut func) => {
2229 func.args = func
2230 .args
2231 .into_iter()
2232 .map(unqualify_columns_recursive)
2233 .collect();
2234 Expression::AggregateFunction(func)
2235 }
2236 Expression::Case(mut case) => {
2237 case.whens = case
2238 .whens
2239 .into_iter()
2240 .map(|(cond, result)| {
2241 (
2242 unqualify_columns_recursive(cond),
2243 unqualify_columns_recursive(result),
2244 )
2245 })
2246 .collect();
2247 if let Some(else_expr) = case.else_ {
2248 case.else_ = Some(unqualify_columns_recursive(else_expr));
2249 }
2250 Expression::Case(case)
2251 }
2252 other => other,
2254 }
2255}
2256
2257fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
2259 op.left = unqualify_columns_recursive(op.left);
2260 op.right = unqualify_columns_recursive(op.right);
2261 op
2262}
2263
2264pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
2284 match expr {
2285 Expression::Select(mut select) => {
2286 let mut cte_count = 0;
2287 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2288
2289 if let Some(ref mut with) = select.with {
2291 for cte in &mut with.ctes {
2292 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
2293 }
2294 }
2295
2296 if let Some(ref mut from) = select.from {
2298 for table_expr in &mut from.expressions {
2299 if let Some((cte, replacement)) =
2300 try_convert_generate_date_array(table_expr, &mut cte_count)
2301 {
2302 new_ctes.push(cte);
2303 *table_expr = replacement;
2304 }
2305 }
2306 }
2307
2308 for join in &mut select.joins {
2310 if let Some((cte, replacement)) =
2311 try_convert_generate_date_array(&join.this, &mut cte_count)
2312 {
2313 new_ctes.push(cte);
2314 join.this = replacement;
2315 }
2316 }
2317
2318 if !new_ctes.is_empty() {
2320 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
2321 ctes: Vec::new(),
2322 recursive: true, leading_comments: vec![],
2324 search: None,
2325 });
2326 with_clause.recursive = true;
2327
2328 let mut all_ctes = new_ctes;
2330 all_ctes.append(&mut with_clause.ctes);
2331 with_clause.ctes = all_ctes;
2332 }
2333
2334 Ok(Expression::Select(select))
2335 }
2336 other => Ok(other),
2337 }
2338}
2339
2340fn process_expression_for_gda(
2343 expr: &mut Expression,
2344 cte_count: &mut usize,
2345 new_ctes: &mut Vec<crate::expressions::Cte>,
2346) {
2347 match expr {
2348 Expression::Select(ref mut select) => {
2349 if let Some(ref mut from) = select.from {
2351 for table_expr in &mut from.expressions {
2352 if let Some((cte, replacement)) =
2353 try_convert_generate_date_array(table_expr, cte_count)
2354 {
2355 new_ctes.push(cte);
2356 *table_expr = replacement;
2357 }
2358 }
2359 }
2360 for join in &mut select.joins {
2362 if let Some((cte, replacement)) =
2363 try_convert_generate_date_array(&join.this, cte_count)
2364 {
2365 new_ctes.push(cte);
2366 join.this = replacement;
2367 }
2368 }
2369 }
2370 Expression::Union(ref mut u) => {
2371 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
2372 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
2373 }
2374 Expression::Subquery(ref mut sq) => {
2375 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
2376 }
2377 _ => {}
2378 }
2379}
2380
2381fn try_convert_generate_date_array(
2384 expr: &Expression,
2385 cte_count: &mut usize,
2386) -> Option<(crate::expressions::Cte, Expression)> {
2387 try_convert_generate_date_array_with_name(expr, cte_count, None)
2388}
2389
2390fn try_convert_generate_date_array_with_name(
2391 expr: &Expression,
2392 cte_count: &mut usize,
2393 column_name_override: Option<&str>,
2394) -> Option<(crate::expressions::Cte, Expression)> {
2395 fn extract_gda_args(
2397 inner: &Expression,
2398 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
2399 match inner {
2400 Expression::GenerateDateArray(gda) => {
2401 let start = gda.start.as_ref()?;
2402 let end = gda.end.as_ref()?;
2403 let step = gda.step.as_deref();
2404 Some((start, end, step))
2405 }
2406 Expression::GenerateSeries(gs) => {
2407 let start = gs.start.as_deref()?;
2408 let end = gs.end.as_deref()?;
2409 let step = gs.step.as_deref();
2410 Some((start, end, step))
2411 }
2412 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
2413 if f.args.len() >= 2 {
2414 let start = &f.args[0];
2415 let end = &f.args[1];
2416 let step = f.args.get(2);
2417 Some((start, end, step))
2418 } else {
2419 None
2420 }
2421 }
2422 _ => None,
2423 }
2424 }
2425
2426 if let Expression::Unnest(unnest) = expr {
2428 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
2429 let start = start;
2430 let end = end;
2431 let step: Option<&Expression> = step_opt;
2432
2433 let cte_name = if *cte_count == 0 {
2435 "_generated_dates".to_string()
2436 } else {
2437 format!("_generated_dates_{}", cte_count)
2438 };
2439 *cte_count += 1;
2440
2441 let column_name =
2442 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
2443
2444 let cast_to_date = |expr: &Expression| -> Expression {
2446 match expr {
2447 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
2448 if let Expression::Literal(lit) = expr {
2450 if let Literal::Date(d) = lit.as_ref() {
2451 Expression::Cast(Box::new(Cast {
2452 this: Expression::Literal(Box::new(Literal::String(d.clone()))),
2453 to: DataType::Date,
2454 trailing_comments: vec![],
2455 double_colon_syntax: false,
2456 format: None,
2457 default: None,
2458 inferred_type: None,
2459 }))
2460 } else { expr.clone() }
2461 } else {
2462 unreachable!()
2463 }
2464 }
2465 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
2466 _ => Expression::Cast(Box::new(Cast {
2467 this: expr.clone(),
2468 to: DataType::Date,
2469 trailing_comments: vec![],
2470 double_colon_syntax: false,
2471 format: None,
2472 default: None,
2473 inferred_type: None,
2474 })),
2475 }
2476 };
2477
2478 let base_select = Select {
2480 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
2481 this: cast_to_date(start),
2482 alias: column_name.clone(),
2483 column_aliases: vec![],
2484 pre_alias_comments: vec![],
2485 trailing_comments: vec![],
2486 inferred_type: None,
2487 }))],
2488 ..Select::new()
2489 };
2490
2491 let normalize_interval = |expr: &Expression| -> Expression {
2493 if let Expression::Interval(ref iv) = expr {
2494 let mut iv_clone = iv.as_ref().clone();
2495 if let Some(Expression::Literal(ref lit)) = iv_clone.this {
2496 if let Literal::String(ref s) = lit.as_ref() {
2497 if s.parse::<f64>().is_ok() {
2499 iv_clone.this = Some(Expression::Literal(Box::new(Literal::Number(s.clone()))));
2500 }
2501 }
2502 }
2503 Expression::Interval(Box::new(iv_clone))
2504 } else {
2505 expr.clone()
2506 }
2507 };
2508
2509 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
2512 Expression::Interval(Box::new(crate::expressions::Interval {
2513 this: Some(Expression::Literal(Box::new(Literal::Number("1".to_string())))),
2514 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
2515 unit: crate::expressions::IntervalUnit::Day,
2516 use_plural: false,
2517 }),
2518 }))
2519 });
2520
2521 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
2523
2524 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
2525 this: Expression::Column(Box::new(crate::expressions::Column {
2526 name: column_name.clone(),
2527 table: None,
2528 join_mark: false,
2529 trailing_comments: vec![],
2530 span: None,
2531 inferred_type: None,
2532 })),
2533 interval: add_count,
2534 unit: add_unit,
2535 }));
2536
2537 let cast_date_add = Expression::Cast(Box::new(Cast {
2538 this: date_add_expr.clone(),
2539 to: DataType::Date,
2540 trailing_comments: vec![],
2541 double_colon_syntax: false,
2542 format: None,
2543 default: None,
2544 inferred_type: None,
2545 }));
2546
2547 let recursive_select = Select {
2548 expressions: vec![cast_date_add.clone()],
2549 from: Some(From {
2550 expressions: vec![Expression::Table(Box::new(crate::expressions::TableRef::new(
2551 &cte_name,
2552 )))],
2553 }),
2554 where_clause: Some(Where {
2555 this: Expression::Lte(Box::new(BinaryOp {
2556 left: cast_date_add,
2557 right: cast_to_date(end),
2558 left_comments: vec![],
2559 operator_comments: vec![],
2560 trailing_comments: vec![],
2561 inferred_type: None,
2562 })),
2563 }),
2564 ..Select::new()
2565 };
2566
2567 let union = crate::expressions::Union {
2569 left: Expression::Select(Box::new(base_select)),
2570 right: Expression::Select(Box::new(recursive_select)),
2571 all: true, distinct: false,
2573 with: None,
2574 order_by: None,
2575 limit: None,
2576 offset: None,
2577 distribute_by: None,
2578 sort_by: None,
2579 cluster_by: None,
2580 by_name: false,
2581 side: None,
2582 kind: None,
2583 corresponding: false,
2584 strict: false,
2585 on_columns: Vec::new(),
2586 };
2587
2588 let cte = crate::expressions::Cte {
2590 this: Expression::Union(Box::new(union)),
2591 alias: Identifier::new(cte_name.clone()),
2592 columns: vec![column_name.clone()],
2593 materialized: None,
2594 key_expressions: Vec::new(),
2595 alias_first: true,
2596 comments: Vec::new(),
2597 };
2598
2599 let replacement_select = Select {
2601 expressions: vec![Expression::Column(Box::new(crate::expressions::Column {
2602 name: column_name,
2603 table: None,
2604 join_mark: false,
2605 trailing_comments: vec![],
2606 span: None,
2607 inferred_type: None,
2608 }))],
2609 from: Some(From {
2610 expressions: vec![Expression::Table(Box::new(crate::expressions::TableRef::new(
2611 &cte_name,
2612 )))],
2613 }),
2614 ..Select::new()
2615 };
2616
2617 let replacement = Expression::Subquery(Box::new(Subquery {
2618 this: Expression::Select(Box::new(replacement_select)),
2619 alias: Some(Identifier::new(cte_name)),
2620 column_aliases: vec![],
2621 order_by: None,
2622 limit: None,
2623 offset: None,
2624 distribute_by: None,
2625 sort_by: None,
2626 cluster_by: None,
2627 lateral: false,
2628 modifiers_inside: false,
2629 trailing_comments: vec![],
2630 inferred_type: None,
2631 }));
2632
2633 return Some((cte, replacement));
2634 }
2635 }
2636
2637 if let Expression::Alias(alias) = expr {
2639 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
2641 if let Some((cte, replacement)) =
2642 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
2643 {
2644 if col_name.is_some() {
2647 return Some((cte, replacement));
2648 }
2649 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
2650 this: replacement,
2651 alias: alias.alias.clone(),
2652 column_aliases: alias.column_aliases.clone(),
2653 pre_alias_comments: alias.pre_alias_comments.clone(),
2654 trailing_comments: alias.trailing_comments.clone(),
2655 inferred_type: None,
2656 }));
2657 return Some((cte, new_alias));
2658 }
2659 }
2660
2661 None
2662}
2663
2664fn extract_interval_unit_and_count(
2669 expr: &Expression,
2670) -> (crate::expressions::IntervalUnit, Expression) {
2671 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
2672
2673 if let Expression::Interval(ref iv) = expr {
2674 if let Some(ref unit_spec) = iv.unit {
2676 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
2677 let count = match &iv.this {
2678 Some(e) => e.clone(),
2679 None => Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2680 };
2681 return (unit.clone(), count);
2682 }
2683 }
2684
2685 if let Some(ref val_expr) = iv.this {
2687 match val_expr {
2688 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_) | Literal::Number(_)) => {
2689 let s = match lit.as_ref() {
2690 Literal::String(s) | Literal::Number(s) => s,
2691 _ => unreachable!(),
2692 };
2693 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
2695 if parts.len() == 2 {
2696 let count_str = parts[0].trim();
2697 let unit_str = parts[1].trim().to_uppercase();
2698 let unit = match unit_str.as_str() {
2699 "YEAR" | "YEARS" => IntervalUnit::Year,
2700 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
2701 "MONTH" | "MONTHS" => IntervalUnit::Month,
2702 "WEEK" | "WEEKS" => IntervalUnit::Week,
2703 "DAY" | "DAYS" => IntervalUnit::Day,
2704 "HOUR" | "HOURS" => IntervalUnit::Hour,
2705 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
2706 "SECOND" | "SECONDS" => IntervalUnit::Second,
2707 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
2708 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
2709 _ => IntervalUnit::Day,
2710 };
2711 return (
2712 unit,
2713 Expression::Literal(Box::new(Literal::Number(count_str.to_string()))),
2714 );
2715 }
2716 if s.parse::<f64>().is_ok() {
2718 return (
2719 IntervalUnit::Day,
2720 Expression::Literal(Box::new(Literal::Number(s.clone()))),
2721 );
2722 }
2723 }
2724 _ => {}
2725 }
2726 }
2727
2728 (
2730 IntervalUnit::Day,
2731 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2732 )
2733 } else {
2734 (
2735 IntervalUnit::Day,
2736 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2737 )
2738 }
2739}
2740
2741pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
2754 match expr {
2755 Expression::ILike(ilike) => {
2756 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
2758 name: "LOWER".to_string(),
2759 args: vec![ilike.left],
2760 distinct: false,
2761 trailing_comments: vec![],
2762 use_bracket_syntax: false,
2763 no_parens: false,
2764 quoted: false,
2765 span: None,
2766 inferred_type: None,
2767 }));
2768
2769 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
2770 name: "LOWER".to_string(),
2771 args: vec![ilike.right],
2772 distinct: false,
2773 trailing_comments: vec![],
2774 use_bracket_syntax: false,
2775 no_parens: false,
2776 quoted: false,
2777 span: None,
2778 inferred_type: None,
2779 }));
2780
2781 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
2782 left: lower_left,
2783 right: lower_right,
2784 escape: ilike.escape,
2785 quantifier: ilike.quantifier,
2786 inferred_type: None,
2787 })))
2788 }
2789 other => Ok(other),
2790 }
2791}
2792
2793pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
2801 match expr {
2802 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
2803 other => Ok(other),
2804 }
2805}
2806
2807pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
2812 match expr {
2813 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
2814 other => Ok(other),
2815 }
2816}
2817
2818pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
2825 Ok(expr)
2827}
2828
2829pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
2843 match expr {
2846 Expression::Table(ref table) => {
2847 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
2850 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2852 this: expr.clone(),
2853 expressions: Vec::new(),
2854 with_ordinality: false,
2855 alias: None,
2856 offset_alias: None,
2857 }));
2858
2859 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
2861 this: unnest,
2862 alias: Identifier::new("_u".to_string()),
2863 column_aliases: vec![],
2864 pre_alias_comments: vec![],
2865 trailing_comments: vec![],
2866 inferred_type: None,
2867 })));
2868 }
2869 Ok(expr)
2870 }
2871 Expression::GenerateSeries(gs) => {
2872 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2874 this: Expression::GenerateSeries(gs),
2875 expressions: Vec::new(),
2876 with_ordinality: false,
2877 alias: None,
2878 offset_alias: None,
2879 }));
2880 Ok(unnest)
2881 }
2882 other => Ok(other),
2883 }
2884}
2885
2886pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
2897 use crate::dialects::transform_recursive;
2898 transform_recursive(expr, &unwrap_unnest_generate_series_single)
2899}
2900
2901fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
2902 use crate::expressions::*;
2903 match expr {
2905 Expression::Select(mut select) => {
2906 if let Some(ref mut from) = select.from {
2908 for table_expr in &mut from.expressions {
2909 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
2910 *table_expr = replacement;
2911 }
2912 }
2913 }
2914 for join in &mut select.joins {
2916 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
2917 join.this = replacement;
2918 }
2919 }
2920 Ok(Expression::Select(select))
2921 }
2922 other => Ok(other),
2923 }
2924}
2925
2926fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
2929 use crate::expressions::*;
2930
2931 let gen_series = match expr {
2933 Expression::Unnest(unnest) => {
2934 if let Expression::GenerateSeries(ref gs) = unnest.this {
2935 Some(gs.as_ref().clone())
2936 } else {
2937 None
2938 }
2939 }
2940 Expression::Alias(alias) => {
2941 if let Expression::Unnest(ref unnest) = alias.this {
2942 if let Expression::GenerateSeries(ref gs) = unnest.this {
2943 Some(gs.as_ref().clone())
2944 } else {
2945 None
2946 }
2947 } else {
2948 None
2949 }
2950 }
2951 _ => None,
2952 };
2953
2954 let gs = gen_series?;
2955
2956 let value_col = Expression::boxed_column(Column {
2958 name: Identifier::new("value".to_string()),
2959 table: None,
2960 join_mark: false,
2961 trailing_comments: vec![],
2962 span: None,
2963 inferred_type: None,
2964 });
2965
2966 let cast_value = Expression::Cast(Box::new(Cast {
2967 this: value_col,
2968 to: DataType::Date,
2969 trailing_comments: vec![],
2970 double_colon_syntax: false,
2971 format: None,
2972 default: None,
2973 inferred_type: None,
2974 }));
2975
2976 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
2977
2978 let gen_series_aliased = Expression::Alias(Box::new(Alias {
2980 this: gen_series_expr,
2981 alias: Identifier::new("_t".to_string()),
2982 column_aliases: vec![Identifier::new("value".to_string())],
2983 pre_alias_comments: vec![],
2984 trailing_comments: vec![],
2985 inferred_type: None,
2986 }));
2987
2988 let mut inner_select = Select::new();
2989 inner_select.expressions = vec![cast_value];
2990 inner_select.from = Some(From {
2991 expressions: vec![gen_series_aliased],
2992 });
2993
2994 let inner_select_expr = Expression::Select(Box::new(inner_select));
2995
2996 let subquery = Expression::Subquery(Box::new(Subquery {
2997 this: inner_select_expr,
2998 alias: None,
2999 column_aliases: vec![],
3000 order_by: None,
3001 limit: None,
3002 offset: None,
3003 distribute_by: None,
3004 sort_by: None,
3005 cluster_by: None,
3006 lateral: false,
3007 modifiers_inside: false,
3008 trailing_comments: vec![],
3009 inferred_type: None,
3010 }));
3011
3012 Some(Expression::Alias(Box::new(Alias {
3014 this: subquery,
3015 alias: Identifier::new("_unnested_generate_series".to_string()),
3016 column_aliases: vec![],
3017 pre_alias_comments: vec![],
3018 trailing_comments: vec![],
3019 inferred_type: None,
3020 })))
3021}
3022
3023pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
3031 match expr {
3032 Expression::Delete(mut delete) => {
3033 if let Some(ref mut where_clause) = delete.where_clause {
3035 where_clause.this = expand_between_recursive(where_clause.this.clone());
3036 }
3037 Ok(Expression::Delete(delete))
3038 }
3039 other => Ok(other),
3040 }
3041}
3042
3043fn expand_between_recursive(expr: Expression) -> Expression {
3045 match expr {
3046 Expression::Between(between) => {
3049 let this = expand_between_recursive(between.this.clone());
3050 let low = expand_between_recursive(between.low);
3051 let high = expand_between_recursive(between.high);
3052
3053 if between.not {
3054 Expression::Or(Box::new(BinaryOp::new(
3056 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
3057 Expression::Gt(Box::new(BinaryOp::new(this, high))),
3058 )))
3059 } else {
3060 Expression::And(Box::new(BinaryOp::new(
3062 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
3063 Expression::Lte(Box::new(BinaryOp::new(this, high))),
3064 )))
3065 }
3066 }
3067
3068 Expression::And(mut op) => {
3070 op.left = expand_between_recursive(op.left);
3071 op.right = expand_between_recursive(op.right);
3072 Expression::And(op)
3073 }
3074 Expression::Or(mut op) => {
3075 op.left = expand_between_recursive(op.left);
3076 op.right = expand_between_recursive(op.right);
3077 Expression::Or(op)
3078 }
3079 Expression::Not(mut op) => {
3080 op.this = expand_between_recursive(op.this);
3081 Expression::Not(op)
3082 }
3083
3084 Expression::Paren(mut paren) => {
3086 paren.this = expand_between_recursive(paren.this);
3087 Expression::Paren(paren)
3088 }
3089
3090 other => other,
3092 }
3093}
3094
3095pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
3104 match expr {
3105 Expression::Select(mut select) => {
3106 if let Some(ref mut with) = select.with {
3107 for cte in &mut with.ctes {
3108 if !cte.columns.is_empty() {
3109 let is_star = matches!(&cte.this, Expression::Select(s) if
3111 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
3112
3113 if is_star {
3114 cte.columns.clear();
3116 continue;
3117 }
3118
3119 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
3121
3122 if let Expression::Select(ref mut inner_select) = cte.this {
3124 let new_exprs: Vec<Expression> = inner_select
3125 .expressions
3126 .drain(..)
3127 .zip(
3128 column_names
3129 .into_iter()
3130 .chain(std::iter::repeat_with(|| Identifier::new(""))),
3131 )
3132 .map(|(expr, col_name)| {
3133 if col_name.name.is_empty() {
3134 return expr;
3135 }
3136 match expr {
3138 Expression::Alias(mut a) => {
3139 a.alias = col_name;
3140 Expression::Alias(a)
3141 }
3142 other => {
3143 Expression::Alias(Box::new(crate::expressions::Alias {
3144 this: other,
3145 alias: col_name,
3146 column_aliases: Vec::new(),
3147 pre_alias_comments: Vec::new(),
3148 trailing_comments: Vec::new(),
3149 inferred_type: None,
3150 }))
3151 }
3152 }
3153 })
3154 .collect();
3155 inner_select.expressions = new_exprs;
3156 }
3157 }
3158 }
3159 }
3160 Ok(Expression::Select(select))
3161 }
3162 other => Ok(other),
3163 }
3164}
3165
3166pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
3170 match expr {
3171 Expression::Select(mut select) => {
3172 if let Some(ref mut from) = select.from {
3173 for from_item in from.expressions.iter_mut() {
3174 simplify_paren_values_in_from(from_item);
3175 }
3176 }
3177 Ok(Expression::Select(select))
3178 }
3179 other => Ok(other),
3180 }
3181}
3182
3183fn simplify_paren_values_in_from(expr: &mut Expression) {
3184 let replacement = match expr {
3186 Expression::Subquery(ref subquery) => {
3188 if let Expression::Paren(ref paren) = subquery.this {
3189 if matches!(&paren.this, Expression::Values(_)) {
3190 let mut new_sub = subquery.as_ref().clone();
3191 new_sub.this = paren.this.clone();
3192 Some(Expression::Subquery(Box::new(new_sub)))
3193 } else {
3194 None
3195 }
3196 } else {
3197 None
3198 }
3199 }
3200 Expression::Paren(ref outer_paren) => {
3203 if let Expression::Subquery(ref subquery) = outer_paren.this {
3204 if matches!(&subquery.this, Expression::Values(_)) {
3206 Some(outer_paren.this.clone())
3207 }
3208 else if let Expression::Paren(ref paren) = subquery.this {
3210 if matches!(&paren.this, Expression::Values(_)) {
3211 let mut new_sub = subquery.as_ref().clone();
3212 new_sub.this = paren.this.clone();
3213 Some(Expression::Subquery(Box::new(new_sub)))
3214 } else {
3215 None
3216 }
3217 } else {
3218 None
3219 }
3220 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
3221 if matches!(&inner_paren.this, Expression::Values(_)) {
3222 Some(outer_paren.this.clone())
3223 } else {
3224 None
3225 }
3226 } else {
3227 None
3228 }
3229 }
3230 _ => None,
3231 };
3232 if let Some(new_expr) = replacement {
3233 *expr = new_expr;
3234 }
3235}
3236
3237pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
3241 match expr {
3242 Expression::Select(mut select) => {
3243 if let Some(ref mut from) = select.from {
3245 let mut counter = 0usize;
3246 for from_item in from.expressions.iter_mut() {
3247 add_auto_alias_to_from_item(from_item, &mut counter);
3248 }
3249 }
3250 Ok(Expression::Select(select))
3251 }
3252 other => Ok(other),
3253 }
3254}
3255
3256fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
3257 use crate::expressions::Identifier;
3258
3259 match expr {
3260 Expression::Alias(ref mut alias) => {
3261 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
3263 alias.alias = Identifier::new(format!("_t{}", counter));
3264 *counter += 1;
3265 }
3266 }
3267 _ => {}
3268 }
3269}
3270
3271pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
3281 use crate::dialects::transform_recursive;
3282 transform_recursive(expr, &propagate_struct_names_in_expr)
3283}
3284
3285fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
3286 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
3287
3288 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
3290 if elements.len() <= 1 {
3291 return None;
3292 }
3293 if let Some(Expression::Function(ref first_struct)) = elements.first() {
3295 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
3296 let field_names: Vec<Option<String>> = first_struct
3298 .args
3299 .iter()
3300 .map(|arg| {
3301 if let Expression::Alias(a) = arg {
3302 Some(a.alias.name.clone())
3303 } else {
3304 None
3305 }
3306 })
3307 .collect();
3308
3309 if field_names.iter().any(|n| n.is_some()) {
3311 let mut new_elements = Vec::with_capacity(elements.len());
3312 new_elements.push(elements[0].clone());
3313
3314 for elem in &elements[1..] {
3315 if let Expression::Function(ref s) = elem {
3316 if s.name.eq_ignore_ascii_case("STRUCT")
3317 && s.args.len() == field_names.len()
3318 {
3319 let all_unnamed =
3321 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
3322 if all_unnamed {
3323 let new_args: Vec<Expression> = s
3325 .args
3326 .iter()
3327 .zip(field_names.iter())
3328 .map(|(val, name)| {
3329 if let Some(n) = name {
3330 Expression::Alias(Box::new(Alias::new(
3331 val.clone(),
3332 Identifier::new(n.clone()),
3333 )))
3334 } else {
3335 val.clone()
3336 }
3337 })
3338 .collect();
3339 new_elements.push(Expression::Function(Box::new(
3340 Function::new("STRUCT".to_string(), new_args),
3341 )));
3342 continue;
3343 }
3344 }
3345 }
3346 new_elements.push(elem.clone());
3347 }
3348
3349 return Some(new_elements);
3350 }
3351 }
3352 }
3353 None
3354 }
3355
3356 if let Expression::Array(ref arr) = expr {
3358 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3359 return Ok(Expression::Array(Box::new(crate::expressions::Array {
3360 expressions: new_elements,
3361 })));
3362 }
3363 }
3364
3365 if let Expression::ArrayFunc(ref arr) = expr {
3367 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3368 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
3369 expressions: new_elements,
3370 bracket_notation: arr.bracket_notation,
3371 use_list_keyword: arr.use_list_keyword,
3372 })));
3373 }
3374 }
3375
3376 Ok(expr)
3377}
3378
3379pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
3382 use crate::dialects::transform_recursive;
3383 transform_recursive(expr, &unnest_alias_transform_single_select)
3384}
3385
3386pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
3389 use crate::dialects::transform_recursive;
3390 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
3391}
3392
3393fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
3394 if let Expression::Select(mut select) = expr {
3395 if let Some(ref mut from) = select.from {
3396 if from.expressions.len() > 1 {
3397 let mut new_from_exprs = Vec::new();
3398 let mut new_cross_joins = Vec::new();
3399
3400 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3401 if idx == 0 {
3402 new_from_exprs.push(from_item);
3403 } else {
3404 let is_unnest = match &from_item {
3405 Expression::Unnest(_) => true,
3406 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3407 _ => false,
3408 };
3409
3410 if is_unnest {
3411 new_cross_joins.push(crate::expressions::Join {
3412 this: from_item,
3413 on: None,
3414 using: Vec::new(),
3415 kind: JoinKind::Cross,
3416 use_inner_keyword: false,
3417 use_outer_keyword: false,
3418 deferred_condition: false,
3419 join_hint: None,
3420 match_condition: None,
3421 pivots: Vec::new(),
3422 comments: Vec::new(),
3423 nesting_group: 0,
3424 directed: false,
3425 });
3426 } else {
3427 new_from_exprs.push(from_item);
3428 }
3429 }
3430 }
3431
3432 from.expressions = new_from_exprs;
3433 new_cross_joins.append(&mut select.joins);
3434 select.joins = new_cross_joins;
3435 }
3436 }
3437
3438 Ok(Expression::Select(select))
3439 } else {
3440 Ok(expr)
3441 }
3442}
3443
3444pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
3448 use crate::dialects::transform_recursive;
3449 transform_recursive(expr, &wrap_unnest_join_aliases_single)
3450}
3451
3452fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
3453 if let Expression::Select(mut select) = expr {
3454 for join in &mut select.joins {
3456 wrap_unnest_alias_in_join_item(&mut join.this);
3457 }
3458 Ok(Expression::Select(select))
3459 } else {
3460 Ok(expr)
3461 }
3462}
3463
3464fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
3466 use crate::expressions::Identifier;
3467 if let Expression::Alias(alias) = expr {
3468 let is_unnest = match &alias.this {
3470 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
3471 _ => false,
3472 };
3473
3474 if is_unnest && alias.column_aliases.is_empty() {
3475 let original_alias_name = alias.alias.name.clone();
3477 alias.alias = Identifier {
3478 name: "_u".to_string(),
3479 quoted: false,
3480 trailing_comments: Vec::new(),
3481 span: None,
3482 };
3483 alias.column_aliases = vec![Identifier {
3484 name: original_alias_name,
3485 quoted: false,
3486 trailing_comments: Vec::new(),
3487 span: None,
3488 }];
3489 }
3490 }
3491}
3492
3493fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
3494 if let Expression::Select(mut select) = expr {
3495 let mut counter = 0usize;
3496
3497 if let Some(ref mut from) = select.from {
3499 for from_item in from.expressions.iter_mut() {
3501 convert_unnest_alias_in_from(from_item, &mut counter);
3502 }
3503
3504 if from.expressions.len() > 1 {
3506 let mut new_from_exprs = Vec::new();
3507 let mut new_cross_joins = Vec::new();
3508
3509 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3510 if idx == 0 {
3511 new_from_exprs.push(from_item);
3513 } else {
3514 let is_unnest = match &from_item {
3516 Expression::Unnest(_) => true,
3517 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3518 _ => false,
3519 };
3520
3521 if is_unnest {
3522 new_cross_joins.push(crate::expressions::Join {
3524 this: from_item,
3525 on: None,
3526 using: Vec::new(),
3527 kind: JoinKind::Cross,
3528 use_inner_keyword: false,
3529 use_outer_keyword: false,
3530 deferred_condition: false,
3531 join_hint: None,
3532 match_condition: None,
3533 pivots: Vec::new(),
3534 comments: Vec::new(),
3535 nesting_group: 0,
3536 directed: false,
3537 });
3538 } else {
3539 new_from_exprs.push(from_item);
3541 }
3542 }
3543 }
3544
3545 from.expressions = new_from_exprs;
3546 new_cross_joins.append(&mut select.joins);
3548 select.joins = new_cross_joins;
3549 }
3550 }
3551
3552 for join in select.joins.iter_mut() {
3554 convert_unnest_alias_in_from(&mut join.this, &mut counter);
3555 }
3556
3557 Ok(Expression::Select(select))
3558 } else {
3559 Ok(expr)
3560 }
3561}
3562
3563fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
3564 use crate::expressions::Identifier;
3565
3566 if let Expression::Alias(ref mut alias) = expr {
3567 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
3569 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
3570
3571 if is_unnest && alias.column_aliases.is_empty() {
3572 let col_alias = alias.alias.clone();
3574 alias.column_aliases = vec![col_alias];
3575 alias.alias = Identifier::new(format!("_t{}", counter));
3576 *counter += 1;
3577 }
3578 }
3579}
3580
3581pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
3588 use crate::expressions::{Alias, Function};
3589
3590 match expr {
3591 Expression::Select(mut select) => {
3592 let mut new_expressions = Vec::new();
3594 let mut changed = false;
3595
3596 for sel_expr in select.expressions.drain(..) {
3597 if let Expression::Alias(ref alias_box) = sel_expr {
3599 if let Expression::Function(ref func) = alias_box.this {
3600 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3601 let arg = func.args[0].clone();
3602 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
3604 (
3605 alias_box.column_aliases[0].name.clone(),
3606 alias_box.column_aliases[1].name.clone(),
3607 )
3608 } else if !alias_box.alias.is_empty() {
3609 ("pos".to_string(), alias_box.alias.name.clone())
3611 } else {
3612 ("pos".to_string(), "col".to_string())
3613 };
3614
3615 let gen_subscripts = Expression::Function(Box::new(Function::new(
3617 "GENERATE_SUBSCRIPTS".to_string(),
3618 vec![
3619 arg.clone(),
3620 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3621 ],
3622 )));
3623 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3624 gen_subscripts,
3625 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3626 )));
3627 let pos_alias = Expression::Alias(Box::new(Alias {
3628 this: sub_one,
3629 alias: Identifier::new(pos_name),
3630 column_aliases: Vec::new(),
3631 pre_alias_comments: Vec::new(),
3632 trailing_comments: Vec::new(),
3633 inferred_type: None,
3634 }));
3635
3636 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3638 this: arg,
3639 expressions: Vec::new(),
3640 with_ordinality: false,
3641 alias: None,
3642 offset_alias: None,
3643 }));
3644 let col_alias = Expression::Alias(Box::new(Alias {
3645 this: unnest,
3646 alias: Identifier::new(col_name),
3647 column_aliases: Vec::new(),
3648 pre_alias_comments: Vec::new(),
3649 trailing_comments: Vec::new(),
3650 inferred_type: None,
3651 }));
3652
3653 new_expressions.push(pos_alias);
3654 new_expressions.push(col_alias);
3655 changed = true;
3656 continue;
3657 }
3658 }
3659 }
3660
3661 if let Expression::Function(ref func) = sel_expr {
3663 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3664 let arg = func.args[0].clone();
3665 let pos_name = "pos";
3666 let col_name = "col";
3667
3668 let gen_subscripts = Expression::Function(Box::new(Function::new(
3670 "GENERATE_SUBSCRIPTS".to_string(),
3671 vec![
3672 arg.clone(),
3673 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3674 ],
3675 )));
3676 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3677 gen_subscripts,
3678 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3679 )));
3680 let pos_alias = Expression::Alias(Box::new(Alias {
3681 this: sub_one,
3682 alias: Identifier::new(pos_name),
3683 column_aliases: Vec::new(),
3684 pre_alias_comments: Vec::new(),
3685 trailing_comments: Vec::new(),
3686 inferred_type: None,
3687 }));
3688
3689 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3691 this: arg,
3692 expressions: Vec::new(),
3693 with_ordinality: false,
3694 alias: None,
3695 offset_alias: None,
3696 }));
3697 let col_alias = Expression::Alias(Box::new(Alias {
3698 this: unnest,
3699 alias: Identifier::new(col_name),
3700 column_aliases: Vec::new(),
3701 pre_alias_comments: Vec::new(),
3702 trailing_comments: Vec::new(),
3703 inferred_type: None,
3704 }));
3705
3706 new_expressions.push(pos_alias);
3707 new_expressions.push(col_alias);
3708 changed = true;
3709 continue;
3710 }
3711 }
3712
3713 new_expressions.push(sel_expr);
3715 }
3716
3717 if changed {
3718 select.expressions = new_expressions;
3719 } else {
3720 select.expressions = new_expressions;
3721 }
3722
3723 if let Some(ref mut from) = select.from {
3726 expand_posexplode_in_from_duckdb(from)?;
3727 }
3728
3729 Ok(Expression::Select(select))
3730 }
3731 other => Ok(other),
3732 }
3733}
3734
3735fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
3737 use crate::expressions::{Alias, Function};
3738
3739 let mut new_expressions = Vec::new();
3740 let mut _changed = false;
3741
3742 for table_expr in from.expressions.drain(..) {
3743 if let Expression::Alias(ref alias_box) = table_expr {
3745 if let Expression::Function(ref func) = alias_box.this {
3746 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3747 let arg = func.args[0].clone();
3748 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
3749 (
3750 alias_box.column_aliases[0].name.clone(),
3751 alias_box.column_aliases[1].name.clone(),
3752 )
3753 } else {
3754 ("pos".to_string(), "col".to_string())
3755 };
3756
3757 let gen_subscripts = Expression::Function(Box::new(Function::new(
3759 "GENERATE_SUBSCRIPTS".to_string(),
3760 vec![
3761 arg.clone(),
3762 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3763 ],
3764 )));
3765 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3766 gen_subscripts,
3767 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3768 )));
3769 let pos_alias = Expression::Alias(Box::new(Alias {
3770 this: sub_one,
3771 alias: Identifier::new(&pos_name),
3772 column_aliases: Vec::new(),
3773 pre_alias_comments: Vec::new(),
3774 trailing_comments: Vec::new(),
3775 inferred_type: None,
3776 }));
3777 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3778 this: arg,
3779 expressions: Vec::new(),
3780 with_ordinality: false,
3781 alias: None,
3782 offset_alias: None,
3783 }));
3784 let col_alias = Expression::Alias(Box::new(Alias {
3785 this: unnest,
3786 alias: Identifier::new(&col_name),
3787 column_aliases: Vec::new(),
3788 pre_alias_comments: Vec::new(),
3789 trailing_comments: Vec::new(),
3790 inferred_type: None,
3791 }));
3792
3793 let mut inner_select = Select::new();
3794 inner_select.expressions = vec![pos_alias, col_alias];
3795
3796 let subquery = Expression::Subquery(Box::new(Subquery {
3797 this: Expression::Select(Box::new(inner_select)),
3798 alias: None,
3799 column_aliases: Vec::new(),
3800 order_by: None,
3801 limit: None,
3802 offset: None,
3803 distribute_by: None,
3804 sort_by: None,
3805 cluster_by: None,
3806 lateral: false,
3807 modifiers_inside: false,
3808 trailing_comments: Vec::new(),
3809 inferred_type: None,
3810 }));
3811 new_expressions.push(subquery);
3812 _changed = true;
3813 continue;
3814 }
3815 }
3816 }
3817
3818 if let Expression::Function(ref func) = table_expr {
3820 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3821 let arg = func.args[0].clone();
3822
3823 let gen_subscripts = Expression::Function(Box::new(Function::new(
3825 "GENERATE_SUBSCRIPTS".to_string(),
3826 vec![
3827 arg.clone(),
3828 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3829 ],
3830 )));
3831 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3832 gen_subscripts,
3833 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3834 )));
3835 let pos_alias = Expression::Alias(Box::new(Alias {
3836 this: sub_one,
3837 alias: Identifier::new("pos"),
3838 column_aliases: Vec::new(),
3839 pre_alias_comments: Vec::new(),
3840 trailing_comments: Vec::new(),
3841 inferred_type: None,
3842 }));
3843 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3844 this: arg,
3845 expressions: Vec::new(),
3846 with_ordinality: false,
3847 alias: None,
3848 offset_alias: None,
3849 }));
3850 let col_alias = Expression::Alias(Box::new(Alias {
3851 this: unnest,
3852 alias: Identifier::new("col"),
3853 column_aliases: Vec::new(),
3854 pre_alias_comments: Vec::new(),
3855 trailing_comments: Vec::new(),
3856 inferred_type: None,
3857 }));
3858
3859 let mut inner_select = Select::new();
3860 inner_select.expressions = vec![pos_alias, col_alias];
3861
3862 let subquery = Expression::Subquery(Box::new(Subquery {
3863 this: Expression::Select(Box::new(inner_select)),
3864 alias: None,
3865 column_aliases: Vec::new(),
3866 order_by: None,
3867 limit: None,
3868 offset: None,
3869 distribute_by: None,
3870 sort_by: None,
3871 cluster_by: None,
3872 lateral: false,
3873 modifiers_inside: false,
3874 trailing_comments: Vec::new(),
3875 inferred_type: None,
3876 }));
3877 new_expressions.push(subquery);
3878 _changed = true;
3879 continue;
3880 }
3881 }
3882
3883 new_expressions.push(table_expr);
3884 }
3885
3886 from.expressions = new_expressions;
3887 Ok(())
3888}
3889
3890pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
3905 match expr {
3906 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
3907 other => Ok(other),
3908 }
3909}
3910
3911pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
3921 match expr {
3922 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
3923 other => Ok(other),
3924 }
3925}
3926
3927fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
3928 let mut flattened_inputs: Vec<Expression> = Vec::new();
3929 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
3930
3931 for sel_expr in select.expressions.into_iter() {
3932 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
3933
3934 let rewritten = transform_recursive(sel_expr, &|e| {
3935 if let Expression::Lateral(lat) = e {
3936 if let Some(input_expr) = extract_flatten_input(&lat) {
3937 if found_input.borrow().is_none() {
3938 *found_input.borrow_mut() = Some(input_expr);
3939 }
3940 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
3941 }
3942 return Ok(Expression::Lateral(lat));
3943 }
3944 Ok(e)
3945 })?;
3946
3947 if let Some(input) = found_input.into_inner() {
3948 flattened_inputs.push(input);
3949 }
3950 new_selects.push(rewritten);
3951 }
3952
3953 if flattened_inputs.is_empty() {
3954 select.expressions = new_selects;
3955 return Ok(Expression::Select(Box::new(select)));
3956 }
3957
3958 select.expressions = new_selects;
3959
3960 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
3961 let is_first = idx == 0;
3963 let series_alias = if is_first {
3964 "pos".to_string()
3965 } else {
3966 format!("pos_{}", idx + 1)
3967 };
3968 let series_source_alias = if is_first {
3969 "_u".to_string()
3970 } else {
3971 format!("_u_{}", idx * 2 + 1)
3972 };
3973 let unnest_source_alias = if is_first {
3974 "_u_2".to_string()
3975 } else {
3976 format!("_u_{}", idx * 2 + 2)
3977 };
3978 let pos2_alias = if is_first {
3979 "pos_2".to_string()
3980 } else {
3981 format!("{}_2", series_alias)
3982 };
3983 let entity_alias = if is_first {
3984 "entity".to_string()
3985 } else {
3986 format!("entity_{}", idx + 1)
3987 };
3988
3989 let array_size_call = Expression::Function(Box::new(Function::new(
3990 "ARRAY_SIZE".to_string(),
3991 vec![Expression::NamedArgument(Box::new(NamedArgument {
3992 name: Identifier::new("INPUT"),
3993 value: input_expr.clone(),
3994 separator: NamedArgSeparator::DArrow,
3995 }))],
3996 )));
3997
3998 let greatest = Expression::Function(Box::new(Function::new(
3999 "GREATEST".to_string(),
4000 vec![array_size_call.clone()],
4001 )));
4002
4003 let series_end = Expression::Add(Box::new(BinaryOp::new(
4004 Expression::Paren(Box::new(crate::expressions::Paren {
4005 this: Expression::Sub(Box::new(BinaryOp::new(
4006 greatest,
4007 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4008 ))),
4009 trailing_comments: Vec::new(),
4010 })),
4011 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4012 )));
4013
4014 let series_range = Expression::Function(Box::new(Function::new(
4015 "ARRAY_GENERATE_RANGE".to_string(),
4016 vec![
4017 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
4018 series_end,
4019 ],
4020 )));
4021
4022 let series_flatten = Expression::Function(Box::new(Function::new(
4023 "FLATTEN".to_string(),
4024 vec![Expression::NamedArgument(Box::new(NamedArgument {
4025 name: Identifier::new("INPUT"),
4026 value: series_range,
4027 separator: NamedArgSeparator::DArrow,
4028 }))],
4029 )));
4030
4031 let series_table = Expression::Function(Box::new(Function::new(
4032 "TABLE".to_string(),
4033 vec![series_flatten],
4034 )));
4035
4036 let series_alias_expr = Expression::Alias(Box::new(Alias {
4037 this: series_table,
4038 alias: Identifier::new(series_source_alias.clone()),
4039 column_aliases: vec![
4040 Identifier::new("seq"),
4041 Identifier::new("key"),
4042 Identifier::new("path"),
4043 Identifier::new("index"),
4044 Identifier::new(series_alias.clone()),
4045 Identifier::new("this"),
4046 ],
4047 pre_alias_comments: Vec::new(),
4048 trailing_comments: Vec::new(),
4049 inferred_type: None,
4050 }));
4051
4052 select.joins.push(Join {
4053 this: series_alias_expr,
4054 on: None,
4055 using: Vec::new(),
4056 kind: JoinKind::Cross,
4057 use_inner_keyword: false,
4058 use_outer_keyword: false,
4059 deferred_condition: false,
4060 join_hint: None,
4061 match_condition: None,
4062 pivots: Vec::new(),
4063 comments: Vec::new(),
4064 nesting_group: 0,
4065 directed: false,
4066 });
4067
4068 let entity_flatten = Expression::Function(Box::new(Function::new(
4069 "FLATTEN".to_string(),
4070 vec![Expression::NamedArgument(Box::new(NamedArgument {
4071 name: Identifier::new("INPUT"),
4072 value: input_expr.clone(),
4073 separator: NamedArgSeparator::DArrow,
4074 }))],
4075 )));
4076
4077 let entity_table = Expression::Function(Box::new(Function::new(
4078 "TABLE".to_string(),
4079 vec![entity_flatten],
4080 )));
4081
4082 let entity_alias_expr = Expression::Alias(Box::new(Alias {
4083 this: entity_table,
4084 alias: Identifier::new(unnest_source_alias.clone()),
4085 column_aliases: vec![
4086 Identifier::new("seq"),
4087 Identifier::new("key"),
4088 Identifier::new("path"),
4089 Identifier::new(pos2_alias.clone()),
4090 Identifier::new(entity_alias.clone()),
4091 Identifier::new("this"),
4092 ],
4093 pre_alias_comments: Vec::new(),
4094 trailing_comments: Vec::new(),
4095 inferred_type: None,
4096 }));
4097
4098 select.joins.push(Join {
4099 this: entity_alias_expr,
4100 on: None,
4101 using: Vec::new(),
4102 kind: JoinKind::Cross,
4103 use_inner_keyword: false,
4104 use_outer_keyword: false,
4105 deferred_condition: false,
4106 join_hint: None,
4107 match_condition: None,
4108 pivots: Vec::new(),
4109 comments: Vec::new(),
4110 nesting_group: 0,
4111 directed: false,
4112 });
4113
4114 let pos_col =
4115 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
4116 let pos2_col =
4117 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
4118
4119 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
4120 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
4121 this: Expression::Sub(Box::new(BinaryOp::new(
4122 array_size_call,
4123 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4124 ))),
4125 trailing_comments: Vec::new(),
4126 }));
4127 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
4128 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
4129 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
4130 let or_cond = Expression::Or(Box::new(BinaryOp::new(
4131 eq,
4132 Expression::Paren(Box::new(crate::expressions::Paren {
4133 this: and_cond,
4134 trailing_comments: Vec::new(),
4135 })),
4136 )));
4137
4138 select.where_clause = Some(match select.where_clause.take() {
4139 Some(existing) => Where {
4140 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
4141 },
4142 None => Where { this: or_cond },
4143 });
4144 }
4145
4146 Ok(Expression::Select(Box::new(select)))
4147}
4148
4149fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
4150 let Expression::Function(f) = lat.this.as_ref() else {
4151 return None;
4152 };
4153 if !f.name.eq_ignore_ascii_case("FLATTEN") {
4154 return None;
4155 }
4156
4157 for arg in &f.args {
4158 if let Expression::NamedArgument(na) = arg {
4159 if na.name.name.eq_ignore_ascii_case("INPUT") {
4160 return Some(na.value.clone());
4161 }
4162 }
4163 }
4164 f.args.first().cloned()
4165}
4166
4167fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
4168 let cond = Expression::Eq(Box::new(BinaryOp::new(
4169 Expression::qualified_column("_u", "pos"),
4170 Expression::qualified_column("_u_2", "pos_2"),
4171 )));
4172 let true_expr = Expression::qualified_column("_u_2", "entity");
4173 let iff_expr = Expression::Function(Box::new(Function::new(
4174 "IFF".to_string(),
4175 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
4176 )));
4177
4178 lat.this = Box::new(iff_expr);
4179 if lat.column_aliases.is_empty() {
4180 lat.column_aliases = vec![
4181 "SEQ".to_string(),
4182 "KEY".to_string(),
4183 "PATH".to_string(),
4184 "INDEX".to_string(),
4185 "VALUE".to_string(),
4186 "THIS".to_string(),
4187 ];
4188 }
4189 lat
4190}
4191
4192struct ExplodeInfo {
4194 arg_sql: String,
4196 explode_alias: String,
4198 pos_alias: String,
4200 unnest_source_alias: String,
4202}
4203
4204fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
4205 let is_presto = matches!(
4206 target,
4207 DialectType::Presto | DialectType::Trino | DialectType::Athena
4208 );
4209 let is_bigquery = matches!(target, DialectType::BigQuery);
4210
4211 if !is_presto && !is_bigquery {
4212 return Ok(Expression::Select(Box::new(select)));
4213 }
4214
4215 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
4217 if !has_explode {
4218 return Ok(Expression::Select(Box::new(select)));
4219 }
4220
4221 let mut taken_select_names = std::collections::HashSet::new();
4223 let mut taken_source_names = std::collections::HashSet::new();
4224
4225 for sel in &select.expressions {
4227 if let Some(name) = get_output_name(sel) {
4228 taken_select_names.insert(name);
4229 }
4230 }
4231
4232 for sel in &select.expressions {
4234 let explode_expr = find_explode_in_expr(sel);
4235 if let Some(arg) = explode_expr {
4236 if let Some(name) = get_output_name(&arg) {
4237 taken_select_names.insert(name);
4238 }
4239 }
4240 }
4241
4242 if let Some(ref from) = select.from {
4244 for from_expr in &from.expressions {
4245 collect_source_names(from_expr, &mut taken_source_names);
4246 }
4247 }
4248 for join in &select.joins {
4250 collect_source_names(&join.this, &mut taken_source_names);
4251 }
4252
4253 let series_alias = new_name(&mut taken_select_names, "pos");
4255
4256 let series_source_alias = new_name(&mut taken_source_names, "_u");
4258
4259 let target_dialect = Dialect::get(target);
4261
4262 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
4264 let mut new_projections: Vec<String> = Vec::new();
4265
4266 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
4267 let explode_data = extract_explode_data(sel_expr);
4268
4269 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
4270 let arg_sql = target_dialect
4272 .generate(&arg_expr)
4273 .unwrap_or_else(|_| "NULL".to_string());
4274
4275 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
4276
4277 let explode_alias = if let Some(ref ea) = explicit_alias {
4278 taken_select_names.remove(ea.as_str());
4281 let name = new_name(&mut taken_select_names, ea);
4283 name
4284 } else {
4285 new_name(&mut taken_select_names, "col")
4286 };
4287
4288 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
4289 taken_select_names.remove(pa.as_str());
4291 let name = new_name(&mut taken_select_names, pa);
4292 name
4293 } else {
4294 new_name(&mut taken_select_names, "pos")
4295 };
4296
4297 if is_presto {
4299 let if_col = format!(
4301 "IF({}.{} = {}.{}, {}.{}) AS {}",
4302 series_source_alias,
4303 series_alias,
4304 unnest_source_alias,
4305 pos_alias,
4306 unnest_source_alias,
4307 explode_alias,
4308 explode_alias
4309 );
4310 new_projections.push(if_col);
4311
4312 if is_posexplode {
4314 let if_pos = format!(
4315 "IF({}.{} = {}.{}, {}.{}) AS {}",
4316 series_source_alias,
4317 series_alias,
4318 unnest_source_alias,
4319 pos_alias,
4320 unnest_source_alias,
4321 pos_alias,
4322 pos_alias
4323 );
4324 new_projections.push(if_pos);
4325 }
4326 } else {
4327 let if_col = format!(
4329 "IF({} = {}, {}, NULL) AS {}",
4330 series_alias, pos_alias, explode_alias, explode_alias
4331 );
4332 new_projections.push(if_col);
4333
4334 if is_posexplode {
4336 let if_pos = format!(
4337 "IF({} = {}, {}, NULL) AS {}",
4338 series_alias, pos_alias, pos_alias, pos_alias
4339 );
4340 new_projections.push(if_pos);
4341 }
4342 }
4343
4344 explode_infos.push(ExplodeInfo {
4345 arg_sql,
4346 explode_alias,
4347 pos_alias,
4348 unnest_source_alias,
4349 });
4350 } else {
4351 let sel_sql = target_dialect
4353 .generate(sel_expr)
4354 .unwrap_or_else(|_| "*".to_string());
4355 new_projections.push(sel_sql);
4356 }
4357 }
4358
4359 if explode_infos.is_empty() {
4360 return Ok(Expression::Select(Box::new(select)));
4361 }
4362
4363 let mut from_parts: Vec<String> = Vec::new();
4365
4366 if let Some(ref from) = select.from {
4368 for from_expr in &from.expressions {
4369 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
4370 from_parts.push(from_sql);
4371 }
4372 }
4373
4374 let size_exprs: Vec<String> = explode_infos
4376 .iter()
4377 .map(|info| {
4378 if is_presto {
4379 format!("CARDINALITY({})", info.arg_sql)
4380 } else {
4381 format!("ARRAY_LENGTH({})", info.arg_sql)
4382 }
4383 })
4384 .collect();
4385
4386 let greatest_arg = if size_exprs.len() == 1 {
4387 size_exprs[0].clone()
4388 } else {
4389 format!("GREATEST({})", size_exprs.join(", "))
4390 };
4391
4392 let series_sql = if is_presto {
4395 if size_exprs.len() == 1 {
4397 format!(
4398 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
4399 greatest_arg, series_source_alias, series_alias
4400 )
4401 } else {
4402 format!(
4404 "UNNEST(SEQUENCE(1, {})) AS {}({})",
4405 greatest_arg, series_source_alias, series_alias
4406 )
4407 }
4408 } else {
4409 if size_exprs.len() == 1 {
4411 format!(
4412 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
4413 greatest_arg, series_alias
4414 )
4415 } else {
4416 format!(
4418 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
4419 greatest_arg, series_alias
4420 )
4421 }
4422 };
4423
4424 let mut cross_joins: Vec<String> = Vec::new();
4428
4429 for info in &explode_infos {
4430 cross_joins.push(format!(
4432 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
4433 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
4434 ));
4435 }
4436
4437 let mut where_conditions: Vec<String> = Vec::new();
4439
4440 for info in &explode_infos {
4441 let size_expr = if is_presto {
4442 format!("CARDINALITY({})", info.arg_sql)
4443 } else {
4444 format!("ARRAY_LENGTH({})", info.arg_sql)
4445 };
4446
4447 let cond = if is_presto {
4448 format!(
4449 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
4450 series_src = series_source_alias,
4451 series_al = series_alias,
4452 unnest_src = info.unnest_source_alias,
4453 pos_al = info.pos_alias,
4454 size = size_expr
4455 )
4456 } else {
4457 format!(
4458 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
4459 series_al = series_alias,
4460 pos_al = info.pos_alias,
4461 size = size_expr
4462 )
4463 };
4464
4465 where_conditions.push(cond);
4466 }
4467
4468 let where_sql = if where_conditions.len() == 1 {
4470 where_conditions[0].clone()
4471 } else {
4472 where_conditions
4473 .iter()
4474 .map(|c| format!("({})", c))
4475 .collect::<Vec<_>>()
4476 .join(" AND ")
4477 };
4478
4479 let select_part = new_projections.join(", ");
4481
4482 let from_and_joins = if from_parts.is_empty() {
4484 format!("FROM {} {}", series_sql, cross_joins.join(" "))
4486 } else {
4487 format!(
4488 "FROM {} {} {}",
4489 from_parts.join(", "),
4490 format!("CROSS JOIN {}", series_sql),
4491 cross_joins.join(" ")
4492 )
4493 };
4494
4495 let full_sql = format!(
4496 "SELECT {} {} WHERE {}",
4497 select_part, from_and_joins, where_sql
4498 );
4499
4500 let generic_dialect = Dialect::get(DialectType::Generic);
4503 let parsed = generic_dialect.parse(&full_sql);
4504 match parsed {
4505 Ok(mut stmts) if !stmts.is_empty() => {
4506 let mut result = stmts.remove(0);
4507
4508 if is_bigquery {
4512 convert_unnest_presto_to_bigquery(&mut result);
4513 }
4514
4515 Ok(result)
4516 }
4517 _ => {
4518 Ok(Expression::Select(Box::new(select)))
4520 }
4521 }
4522}
4523
4524fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
4528 match expr {
4529 Expression::Select(ref mut select) => {
4530 if let Some(ref mut from) = select.from {
4532 for from_item in from.expressions.iter_mut() {
4533 convert_unnest_presto_to_bigquery(from_item);
4534 }
4535 }
4536 for join in select.joins.iter_mut() {
4538 convert_unnest_presto_to_bigquery(&mut join.this);
4539 }
4540 }
4541 Expression::Alias(ref alias) => {
4542 if let Expression::Unnest(ref unnest) = alias.this {
4544 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
4545 let col_alias = alias.column_aliases[0].clone();
4546 let pos_alias = alias.column_aliases[1].clone();
4547 let mut new_unnest = unnest.as_ref().clone();
4548 new_unnest.alias = Some(col_alias);
4549 new_unnest.offset_alias = Some(pos_alias);
4550 *expr = Expression::Unnest(Box::new(new_unnest));
4552 }
4553 }
4554 }
4555 _ => {}
4556 }
4557}
4558
4559fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
4562 if !names.contains(base) {
4563 names.insert(base.to_string());
4564 return base.to_string();
4565 }
4566 let mut i = 2;
4567 loop {
4568 let candidate = format!("{}_{}", base, i);
4569 if !names.contains(&candidate) {
4570 names.insert(candidate.clone());
4571 return candidate;
4572 }
4573 i += 1;
4574 }
4575}
4576
4577fn expr_contains_explode(expr: &Expression) -> bool {
4579 match expr {
4580 Expression::Explode(_) => true,
4581 Expression::ExplodeOuter(_) => true,
4582 Expression::Function(f) => {
4583 let name = f.name.to_uppercase();
4584 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
4585 }
4586 Expression::Alias(a) => expr_contains_explode(&a.this),
4587 _ => false,
4588 }
4589}
4590
4591fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
4593 match expr {
4594 Expression::Explode(uf) => Some(uf.this.clone()),
4595 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
4596 Expression::Function(f) => {
4597 let name = f.name.to_uppercase();
4598 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
4599 Some(f.args[0].clone())
4600 } else {
4601 None
4602 }
4603 }
4604 Expression::Alias(a) => find_explode_in_expr(&a.this),
4605 _ => None,
4606 }
4607}
4608
4609fn extract_explode_data(
4612 expr: &Expression,
4613) -> Option<(bool, Expression, Option<String>, Option<String>)> {
4614 match expr {
4615 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
4617 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
4618 Expression::Function(f) => {
4620 let name = f.name.to_uppercase();
4621 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
4622 Some((true, f.args[0].clone(), None, None))
4623 } else {
4624 None
4625 }
4626 }
4627 Expression::Alias(a) => {
4629 match &a.this {
4630 Expression::Explode(uf) => {
4631 let alias = if !a.alias.is_empty() {
4632 Some(a.alias.name.clone())
4633 } else {
4634 None
4635 };
4636 Some((false, uf.this.clone(), alias, None))
4637 }
4638 Expression::ExplodeOuter(uf) => {
4639 let alias = if !a.alias.is_empty() {
4640 Some(a.alias.name.clone())
4641 } else {
4642 None
4643 };
4644 Some((false, uf.this.clone(), alias, None))
4645 }
4646 Expression::Function(f) => {
4647 let name = f.name.to_uppercase();
4648 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
4649 if a.column_aliases.len() == 2 {
4651 let pos_alias = a.column_aliases[0].name.clone();
4652 let col_alias = a.column_aliases[1].name.clone();
4653 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
4654 } else if !a.alias.is_empty() {
4655 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
4657 } else {
4658 Some((true, f.args[0].clone(), None, None))
4659 }
4660 } else {
4661 None
4662 }
4663 }
4664 _ => None,
4665 }
4666 }
4667 _ => None,
4668 }
4669}
4670
4671fn get_output_name(expr: &Expression) -> Option<String> {
4673 match expr {
4674 Expression::Alias(a) => {
4675 if !a.alias.is_empty() {
4676 Some(a.alias.name.clone())
4677 } else {
4678 None
4679 }
4680 }
4681 Expression::Column(c) => Some(c.name.name.clone()),
4682 Expression::Identifier(id) => Some(id.name.clone()),
4683 _ => None,
4684 }
4685}
4686
4687fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
4689 match expr {
4690 Expression::Alias(a) => {
4691 if !a.alias.is_empty() {
4692 names.insert(a.alias.name.clone());
4693 }
4694 }
4695 Expression::Subquery(s) => {
4696 if let Some(ref alias) = s.alias {
4697 names.insert(alias.name.clone());
4698 }
4699 }
4700 Expression::Table(t) => {
4701 if let Some(ref alias) = t.alias {
4702 names.insert(alias.name.clone());
4703 } else {
4704 names.insert(t.name.name.clone());
4705 }
4706 }
4707 Expression::Column(c) => {
4708 names.insert(c.name.name.clone());
4709 }
4710 Expression::Identifier(id) => {
4711 names.insert(id.name.clone());
4712 }
4713 _ => {}
4714 }
4715}
4716
4717pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
4720 use crate::dialects::transform_recursive;
4721 transform_recursive(expr, &strip_unnest_column_refs_single)
4722}
4723
4724fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
4725 if let Expression::Select(mut select) = expr {
4726 for join in select.joins.iter_mut() {
4728 strip_unnest_from_expr(&mut join.this);
4729 }
4730 if let Some(ref mut from) = select.from {
4732 for from_item in from.expressions.iter_mut() {
4733 strip_unnest_from_expr(from_item);
4734 }
4735 }
4736 Ok(Expression::Select(select))
4737 } else {
4738 Ok(expr)
4739 }
4740}
4741
4742fn strip_unnest_from_expr(expr: &mut Expression) {
4745 if let Expression::Alias(ref mut alias) = expr {
4746 if let Expression::Unnest(ref unnest) = alias.this {
4747 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
4748 if is_column_ref {
4749 let inner = unnest.this.clone();
4751 alias.this = inner;
4752 }
4753 }
4754 }
4755}
4756
4757pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
4760 use crate::dialects::transform_recursive;
4761 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
4762}
4763
4764fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
4765 if let Expression::Select(mut select) = expr {
4766 if let Some(ref mut from) = select.from {
4768 for from_item in from.expressions.iter_mut() {
4769 try_wrap_unnest_in_subquery(from_item);
4770 }
4771 }
4772
4773 for join in select.joins.iter_mut() {
4775 try_wrap_unnest_in_subquery(&mut join.this);
4776 }
4777
4778 Ok(Expression::Select(select))
4779 } else {
4780 Ok(expr)
4781 }
4782}
4783
4784fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
4786 match expr {
4787 Expression::Array(arr) => arr
4789 .expressions
4790 .iter()
4791 .any(|e| matches!(e, Expression::Struct(_))),
4792 Expression::ArrayFunc(arr) => arr
4793 .expressions
4794 .iter()
4795 .any(|e| matches!(e, Expression::Struct(_))),
4796 Expression::Cast(c) => {
4798 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
4799 }
4800 _ => false,
4801 }
4802}
4803
4804fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
4807 if let Expression::Alias(ref alias) = expr {
4809 if let Expression::Unnest(ref unnest) = alias.this {
4810 if is_struct_array_unnest_arg(&unnest.this) {
4811 let unnest_clone = (**unnest).clone();
4812 let alias_name = alias.alias.clone();
4813 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
4814 *expr = new_expr;
4815 return;
4816 }
4817 }
4818 }
4819
4820 if let Expression::Unnest(ref unnest) = expr {
4822 if is_struct_array_unnest_arg(&unnest.this) {
4823 let unnest_clone = (**unnest).clone();
4824 let new_expr = make_unnest_subquery(unnest_clone, None);
4825 *expr = new_expr;
4826 }
4827 }
4828}
4829
4830fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
4832 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
4834 name: Identifier::new("max_depth".to_string()),
4835 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
4836 separator: NamedArgSeparator::DArrow,
4837 }));
4838
4839 let mut unnest_args = vec![unnest.this];
4840 unnest_args.extend(unnest.expressions);
4841 unnest_args.push(max_depth_arg);
4842
4843 let unnest_func =
4844 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
4845
4846 let mut inner_select = Select::new();
4848 inner_select.expressions = vec![unnest_func];
4849 let inner_select = Expression::Select(Box::new(inner_select));
4850
4851 let subquery = Subquery {
4853 this: inner_select,
4854 alias,
4855 column_aliases: Vec::new(),
4856 order_by: None,
4857 limit: None,
4858 offset: None,
4859 distribute_by: None,
4860 sort_by: None,
4861 cluster_by: None,
4862 lateral: false,
4863 modifiers_inside: false,
4864 trailing_comments: Vec::new(),
4865 inferred_type: None,
4866 };
4867
4868 Expression::Subquery(Box::new(subquery))
4869}
4870
4871pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
4883 use crate::expressions::{Limit as LimitClause, Offset as OffsetClause, OrderBy, Star};
4884
4885 match expr {
4886 Expression::Union(mut u) => {
4887 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
4890 if let Expression::Select(ref mut right_select) = u.right {
4892 if right_select.order_by.is_some()
4893 || right_select.limit.is_some()
4894 || right_select.offset.is_some()
4895 {
4896 u.order_by = right_select.order_by.take();
4898 u.limit = right_select.limit.take().map(|l| Box::new(l.this));
4899 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
4900 }
4901 }
4902 }
4903
4904 let has_order_or_limit =
4905 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
4906 if has_order_or_limit {
4907 let order_by: Option<OrderBy> = u.order_by.take();
4909 let union_limit: Option<Box<Expression>> = u.limit.take();
4910 let union_offset: Option<Box<Expression>> = u.offset.take();
4911
4912 let select_limit: Option<LimitClause> = union_limit.map(|l| LimitClause {
4914 this: *l,
4915 percent: false,
4916 comments: Vec::new(),
4917 });
4918
4919 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
4921 this: *o,
4922 rows: None,
4923 });
4924
4925 let subquery = Subquery {
4927 this: Expression::Union(u),
4928 alias: Some(Identifier::new("_l_0")),
4929 column_aliases: Vec::new(),
4930 lateral: false,
4931 modifiers_inside: false,
4932 order_by: None,
4933 limit: None,
4934 offset: None,
4935 distribute_by: None,
4936 sort_by: None,
4937 cluster_by: None,
4938 trailing_comments: Vec::new(),
4939 inferred_type: None,
4940 };
4941
4942 let mut select = Select::default();
4944 select.expressions = vec![Expression::Star(Star {
4945 table: None,
4946 except: None,
4947 replace: None,
4948 rename: None,
4949 trailing_comments: Vec::new(),
4950 span: None,
4951 })];
4952 select.from = Some(From {
4953 expressions: vec![Expression::Subquery(Box::new(subquery))],
4954 });
4955 select.order_by = order_by;
4956 select.limit = select_limit;
4957 select.offset = select_offset;
4958
4959 Ok(Expression::Select(Box::new(select)))
4960 } else {
4961 Ok(Expression::Union(u))
4962 }
4963 }
4964 _ => Ok(expr),
4965 }
4966}
4967
4968pub fn expand_like_any(expr: Expression) -> Result<Expression> {
4973 use crate::expressions::{BinaryOp, LikeOp};
4974
4975 fn unwrap_parens(e: &Expression) -> &Expression {
4976 match e {
4977 Expression::Paren(p) => unwrap_parens(&p.this),
4978 _ => e,
4979 }
4980 }
4981
4982 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
4983 let inner = unwrap_parens(e);
4984 match inner {
4985 Expression::Tuple(t) => Some(t.expressions.clone()),
4986 _ => None,
4987 }
4988 }
4989
4990 transform_recursive(expr, &|e| {
4991 match e {
4992 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
4993 if let Some(values) = extract_tuple_values(&op.right) {
4994 if values.is_empty() {
4995 return Ok(e);
4996 }
4997 let mut result: Option<Expression> = None;
4999 for val in values {
5000 let like = Expression::Like(Box::new(LikeOp {
5001 left: op.left.clone(),
5002 right: val,
5003 escape: op.escape.clone(),
5004 quantifier: None,
5005 inferred_type: None,
5006 }));
5007 result = Some(match result {
5008 None => like,
5009 Some(prev) => Expression::Or(Box::new(BinaryOp::new(prev, like))),
5010 });
5011 }
5012 Ok(result.unwrap_or(e))
5013 } else {
5014 Ok(e)
5015 }
5016 }
5017 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
5018 if let Some(values) = extract_tuple_values(&op.right) {
5019 if values.is_empty() {
5020 return Ok(e);
5021 }
5022 let mut result: Option<Expression> = None;
5023 for val in values {
5024 let ilike = Expression::ILike(Box::new(LikeOp {
5025 left: op.left.clone(),
5026 right: val,
5027 escape: op.escape.clone(),
5028 quantifier: None,
5029 inferred_type: None,
5030 }));
5031 result = Some(match result {
5032 None => ilike,
5033 Some(prev) => Expression::Or(Box::new(BinaryOp::new(prev, ilike))),
5034 });
5035 }
5036 Ok(result.unwrap_or(e))
5037 } else {
5038 Ok(e)
5039 }
5040 }
5041 _ => Ok(e),
5042 }
5043 })
5044}
5045
5046pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
5054 use crate::expressions::Alias;
5055
5056 fn add_self_aliases_to_select(select: &mut Select) {
5057 let new_expressions: Vec<Expression> = select
5058 .expressions
5059 .iter()
5060 .map(|e| {
5061 match e {
5062 Expression::Column(col) => {
5064 let alias_name = col.name.clone();
5065 Expression::Alias(Box::new(Alias {
5066 this: e.clone(),
5067 alias: alias_name,
5068 column_aliases: Vec::new(),
5069 pre_alias_comments: Vec::new(),
5070 trailing_comments: Vec::new(),
5071 inferred_type: None,
5072 }))
5073 }
5074 _ => e.clone(),
5076 }
5077 })
5078 .collect();
5079 select.expressions = new_expressions;
5080 }
5081
5082 fn walk_and_qualify(expr: &mut Expression) {
5083 match expr {
5084 Expression::Select(ref mut select) => {
5085 if let Some(ref mut from) = select.from {
5087 for e in from.expressions.iter_mut() {
5088 qualify_subquery_expr(e);
5089 walk_and_qualify(e);
5090 }
5091 }
5092 for join in select.joins.iter_mut() {
5094 qualify_subquery_expr(&mut join.this);
5095 walk_and_qualify(&mut join.this);
5096 }
5097 for e in select.expressions.iter_mut() {
5099 walk_and_qualify(e);
5100 }
5101 if let Some(ref mut w) = select.where_clause {
5103 walk_and_qualify(&mut w.this);
5104 }
5105 }
5106 Expression::Subquery(ref mut subquery) => {
5107 walk_and_qualify(&mut subquery.this);
5108 }
5109 Expression::Union(ref mut u) => {
5110 walk_and_qualify(&mut u.left);
5111 walk_and_qualify(&mut u.right);
5112 }
5113 Expression::Intersect(ref mut i) => {
5114 walk_and_qualify(&mut i.left);
5115 walk_and_qualify(&mut i.right);
5116 }
5117 Expression::Except(ref mut e) => {
5118 walk_and_qualify(&mut e.left);
5119 walk_and_qualify(&mut e.right);
5120 }
5121 Expression::Cte(ref mut cte) => {
5122 walk_and_qualify(&mut cte.this);
5123 }
5124 _ => {}
5125 }
5126 }
5127
5128 fn qualify_subquery_expr(expr: &mut Expression) {
5129 match expr {
5130 Expression::Subquery(ref mut subquery) => {
5131 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
5133 if let Expression::Select(ref mut inner_select) = subquery.this {
5134 let has_star = inner_select
5136 .expressions
5137 .iter()
5138 .any(|e| matches!(e, Expression::Star(_)));
5139 if !has_star {
5140 add_self_aliases_to_select(inner_select);
5141 }
5142 }
5143 }
5144 walk_and_qualify(&mut subquery.this);
5146 }
5147 Expression::Alias(ref mut alias) => {
5148 qualify_subquery_expr(&mut alias.this);
5149 }
5150 _ => {}
5151 }
5152 }
5153
5154 let mut result = expr;
5155 walk_and_qualify(&mut result);
5156
5157 if let Expression::Select(ref mut select) = result {
5159 if let Some(ref mut with) = select.with {
5160 for cte in with.ctes.iter_mut() {
5161 if cte.columns.is_empty() {
5163 walk_and_qualify(&mut cte.this);
5165 }
5166 }
5167 }
5168 }
5169
5170 Ok(result)
5171}
5172
5173#[cfg(test)]
5174mod tests {
5175 use super::*;
5176 use crate::dialects::{Dialect, DialectType};
5177 use crate::expressions::Column;
5178
5179 fn gen(expr: &Expression) -> String {
5180 let dialect = Dialect::get(DialectType::Generic);
5181 dialect.generate(expr).unwrap()
5182 }
5183
5184 #[test]
5185 fn test_preprocess() {
5186 let expr = Expression::Boolean(BooleanLiteral { value: true });
5187 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
5188 assert!(matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_))));
5189 }
5190
5191 #[test]
5192 fn test_preprocess_chain() {
5193 let expr = Expression::Boolean(BooleanLiteral { value: true });
5195 let transforms: Vec<fn(Expression) -> Result<Expression>> =
5197 vec![replace_bool_with_int, replace_int_with_bool];
5198 let result = preprocess(expr, &transforms).unwrap();
5199 if let Expression::Boolean(b) = result {
5202 assert!(b.value);
5203 } else {
5204 panic!("Expected boolean literal");
5205 }
5206 }
5207
5208 #[test]
5209 fn test_unnest_to_explode() {
5210 let unnest = Expression::Unnest(Box::new(UnnestFunc {
5211 this: Expression::boxed_column(Column {
5212 name: Identifier::new("arr".to_string()),
5213 table: None,
5214 join_mark: false,
5215 trailing_comments: vec![],
5216 span: None,
5217 inferred_type: None,
5218 }),
5219 expressions: Vec::new(),
5220 with_ordinality: false,
5221 alias: None,
5222 offset_alias: None,
5223 }));
5224
5225 let result = unnest_to_explode(unnest).unwrap();
5226 assert!(matches!(result, Expression::Explode(_)));
5227 }
5228
5229 #[test]
5230 fn test_explode_to_unnest() {
5231 let explode = Expression::Explode(Box::new(UnaryFunc {
5232 this: Expression::boxed_column(Column {
5233 name: Identifier::new("arr".to_string()),
5234 table: None,
5235 join_mark: false,
5236 trailing_comments: vec![],
5237 span: None,
5238 inferred_type: None,
5239 }),
5240 original_name: None,
5241 inferred_type: None,
5242 }));
5243
5244 let result = explode_to_unnest(explode).unwrap();
5245 assert!(matches!(result, Expression::Unnest(_)));
5246 }
5247
5248 #[test]
5249 fn test_replace_bool_with_int() {
5250 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
5251 let result = replace_bool_with_int(true_expr).unwrap();
5252 if let Expression::Literal(lit) = result {
5253 if let Literal::Number(n) = lit.as_ref() {
5254 assert_eq!(n, "1");
5255 }
5256 } else {
5257 panic!("Expected number literal");
5258 }
5259
5260 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
5261 let result = replace_bool_with_int(false_expr).unwrap();
5262 if let Expression::Literal(lit) = result {
5263 if let Literal::Number(n) = lit.as_ref() {
5264 assert_eq!(n, "0");
5265 }
5266 } else {
5267 panic!("Expected number literal");
5268 }
5269 }
5270
5271 #[test]
5272 fn test_replace_int_with_bool() {
5273 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
5274 let result = replace_int_with_bool(one_expr).unwrap();
5275 if let Expression::Boolean(b) = result {
5276 assert!(b.value);
5277 } else {
5278 panic!("Expected boolean true");
5279 }
5280
5281 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
5282 let result = replace_int_with_bool(zero_expr).unwrap();
5283 if let Expression::Boolean(b) = result {
5284 assert!(!b.value);
5285 } else {
5286 panic!("Expected boolean false");
5287 }
5288
5289 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
5291 let result = replace_int_with_bool(two_expr).unwrap();
5292 assert!(matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_))));
5293 }
5294
5295 #[test]
5296 fn test_strip_data_type_params() {
5297 let decimal = DataType::Decimal {
5299 precision: Some(10),
5300 scale: Some(2),
5301 };
5302 let stripped = strip_data_type_params(decimal);
5303 assert_eq!(
5304 stripped,
5305 DataType::Decimal {
5306 precision: None,
5307 scale: None
5308 }
5309 );
5310
5311 let varchar = DataType::VarChar {
5313 length: Some(255),
5314 parenthesized_length: false,
5315 };
5316 let stripped = strip_data_type_params(varchar);
5317 assert_eq!(
5318 stripped,
5319 DataType::VarChar {
5320 length: None,
5321 parenthesized_length: false
5322 }
5323 );
5324
5325 let char_type = DataType::Char { length: Some(10) };
5327 let stripped = strip_data_type_params(char_type);
5328 assert_eq!(stripped, DataType::Char { length: None });
5329
5330 let timestamp = DataType::Timestamp {
5332 precision: Some(6),
5333 timezone: true,
5334 };
5335 let stripped = strip_data_type_params(timestamp);
5336 assert_eq!(
5337 stripped,
5338 DataType::Timestamp {
5339 precision: None,
5340 timezone: true
5341 }
5342 );
5343
5344 let array = DataType::Array {
5346 element_type: Box::new(DataType::VarChar {
5347 length: Some(100),
5348 parenthesized_length: false,
5349 }),
5350 dimension: None,
5351 };
5352 let stripped = strip_data_type_params(array);
5353 assert_eq!(
5354 stripped,
5355 DataType::Array {
5356 element_type: Box::new(DataType::VarChar {
5357 length: None,
5358 parenthesized_length: false
5359 }),
5360 dimension: None,
5361 }
5362 );
5363
5364 let text = DataType::Text;
5366 let stripped = strip_data_type_params(text);
5367 assert_eq!(stripped, DataType::Text);
5368 }
5369
5370 #[test]
5371 fn test_remove_precision_parameterized_types_cast() {
5372 let cast_expr = Expression::Cast(Box::new(Cast {
5374 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5375 to: DataType::Decimal {
5376 precision: Some(10),
5377 scale: Some(2),
5378 },
5379 trailing_comments: vec![],
5380 double_colon_syntax: false,
5381 format: None,
5382 default: None,
5383 inferred_type: None,
5384 }));
5385
5386 let result = remove_precision_parameterized_types(cast_expr).unwrap();
5387 if let Expression::Cast(cast) = result {
5388 assert_eq!(
5389 cast.to,
5390 DataType::Decimal {
5391 precision: None,
5392 scale: None
5393 }
5394 );
5395 } else {
5396 panic!("Expected Cast expression");
5397 }
5398 }
5399
5400 #[test]
5401 fn test_remove_precision_parameterized_types_varchar() {
5402 let cast_expr = Expression::Cast(Box::new(Cast {
5404 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
5405 to: DataType::VarChar {
5406 length: Some(10),
5407 parenthesized_length: false,
5408 },
5409 trailing_comments: vec![],
5410 double_colon_syntax: false,
5411 format: None,
5412 default: None,
5413 inferred_type: None,
5414 }));
5415
5416 let result = remove_precision_parameterized_types(cast_expr).unwrap();
5417 if let Expression::Cast(cast) = result {
5418 assert_eq!(
5419 cast.to,
5420 DataType::VarChar {
5421 length: None,
5422 parenthesized_length: false
5423 }
5424 );
5425 } else {
5426 panic!("Expected Cast expression");
5427 }
5428 }
5429
5430 #[test]
5431 fn test_remove_precision_direct_cast() {
5432 let cast = Expression::Cast(Box::new(Cast {
5436 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5437 to: DataType::Decimal {
5438 precision: Some(10),
5439 scale: Some(2),
5440 },
5441 trailing_comments: vec![],
5442 double_colon_syntax: false,
5443 format: None,
5444 default: None,
5445 inferred_type: None,
5446 }));
5447
5448 let transformed = remove_precision_parameterized_types(cast).unwrap();
5449 let generated = gen(&transformed);
5450
5451 assert!(generated.contains("DECIMAL"));
5453 assert!(!generated.contains("(10"));
5454 }
5455
5456 #[test]
5457 fn test_epoch_cast_to_ts() {
5458 let cast_expr = Expression::Cast(Box::new(Cast {
5460 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
5461 to: DataType::Timestamp {
5462 precision: None,
5463 timezone: false,
5464 },
5465 trailing_comments: vec![],
5466 double_colon_syntax: false,
5467 format: None,
5468 default: None,
5469 inferred_type: None,
5470 }));
5471
5472 let result = epoch_cast_to_ts(cast_expr).unwrap();
5473 if let Expression::Cast(cast) = result {
5474 if let Expression::Literal(lit) = cast.this {
5475 if let Literal::String(s) = lit.as_ref() {
5476 assert_eq!(s, "1970-01-01 00:00:00");
5477 }
5478 } else {
5479 panic!("Expected string literal");
5480 }
5481 } else {
5482 panic!("Expected Cast expression");
5483 }
5484 }
5485
5486 #[test]
5487 fn test_epoch_cast_to_ts_preserves_non_epoch() {
5488 let cast_expr = Expression::Cast(Box::new(Cast {
5490 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
5491 to: DataType::Timestamp {
5492 precision: None,
5493 timezone: false,
5494 },
5495 trailing_comments: vec![],
5496 double_colon_syntax: false,
5497 format: None,
5498 default: None,
5499 inferred_type: None,
5500 }));
5501
5502 let result = epoch_cast_to_ts(cast_expr).unwrap();
5503 if let Expression::Cast(cast) = result {
5504 if let Expression::Literal(lit) = cast.this {
5505 if let Literal::String(s) = lit.as_ref() {
5506 assert_eq!(s, "2024-01-15");
5507 }
5508 } else {
5509 panic!("Expected string literal");
5510 }
5511 } else {
5512 panic!("Expected Cast expression");
5513 }
5514 }
5515
5516 #[test]
5517 fn test_unqualify_columns() {
5518 let col = Expression::boxed_column(Column {
5520 name: Identifier::new("id".to_string()),
5521 table: Some(Identifier::new("users".to_string())),
5522 join_mark: false,
5523 trailing_comments: vec![],
5524 span: None,
5525 inferred_type: None,
5526 });
5527
5528 let result = unqualify_columns(col).unwrap();
5529 if let Expression::Column(c) = result {
5530 assert!(c.table.is_none());
5531 assert_eq!(c.name.name, "id");
5532 } else {
5533 panic!("Expected Column expression");
5534 }
5535 }
5536
5537 #[test]
5538 fn test_is_temporal_type() {
5539 assert!(is_temporal_type(&DataType::Date));
5540 assert!(is_temporal_type(&DataType::Timestamp {
5541 precision: None,
5542 timezone: false
5543 }));
5544 assert!(is_temporal_type(&DataType::Time {
5545 precision: None,
5546 timezone: false
5547 }));
5548 assert!(!is_temporal_type(&DataType::Int {
5549 length: None,
5550 integer_spelling: false
5551 }));
5552 assert!(!is_temporal_type(&DataType::VarChar {
5553 length: None,
5554 parenthesized_length: false
5555 }));
5556 }
5557
5558 #[test]
5559 fn test_eliminate_semi_join_basic() {
5560 use crate::expressions::{Join, TableRef};
5561
5562 let select = Expression::Select(Box::new(Select {
5564 expressions: vec![Expression::boxed_column(Column {
5565 name: Identifier::new("a".to_string()),
5566 table: None,
5567 join_mark: false,
5568 trailing_comments: vec![],
5569 span: None,
5570 inferred_type: None,
5571 })],
5572 from: Some(From {
5573 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
5574 }),
5575 joins: vec![Join {
5576 this: Expression::Table(Box::new(TableRef::new("t2"))),
5577 kind: JoinKind::Semi,
5578 on: Some(Expression::Eq(Box::new(BinaryOp {
5579 left: Expression::boxed_column(Column {
5580 name: Identifier::new("x".to_string()),
5581 table: None,
5582 join_mark: false,
5583 trailing_comments: vec![],
5584 span: None,
5585 inferred_type: None,
5586 }),
5587 right: Expression::boxed_column(Column {
5588 name: Identifier::new("y".to_string()),
5589 table: None,
5590 join_mark: false,
5591 trailing_comments: vec![],
5592 span: None,
5593 inferred_type: None,
5594 }),
5595 left_comments: vec![],
5596 operator_comments: vec![],
5597 trailing_comments: vec![],
5598 inferred_type: None,
5599 }))),
5600 using: vec![],
5601 use_inner_keyword: false,
5602 use_outer_keyword: false,
5603 deferred_condition: false,
5604 join_hint: None,
5605 match_condition: None,
5606 pivots: Vec::new(),
5607 comments: Vec::new(),
5608 nesting_group: 0,
5609 directed: false,
5610 }],
5611 ..Select::new()
5612 }));
5613
5614 let result = eliminate_semi_and_anti_joins(select).unwrap();
5615 if let Expression::Select(s) = result {
5616 assert!(s.joins.is_empty());
5618 assert!(s.where_clause.is_some());
5620 } else {
5621 panic!("Expected Select expression");
5622 }
5623 }
5624
5625 #[test]
5626 fn test_no_ilike_sql() {
5627 use crate::expressions::LikeOp;
5628
5629 let ilike_expr = Expression::ILike(Box::new(LikeOp {
5631 left: Expression::boxed_column(Column {
5632 name: Identifier::new("name".to_string()),
5633 table: None,
5634 join_mark: false,
5635 trailing_comments: vec![],
5636 span: None,
5637 inferred_type: None,
5638 }),
5639 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
5640 escape: None,
5641 quantifier: None,
5642 inferred_type: None,
5643 }));
5644
5645 let result = no_ilike_sql(ilike_expr).unwrap();
5646 if let Expression::Like(like) = result {
5647 if let Expression::Function(f) = &like.left {
5649 assert_eq!(f.name, "LOWER");
5650 } else {
5651 panic!("Expected LOWER function on left");
5652 }
5653 if let Expression::Function(f) = &like.right {
5655 assert_eq!(f.name, "LOWER");
5656 } else {
5657 panic!("Expected LOWER function on right");
5658 }
5659 } else {
5660 panic!("Expected Like expression");
5661 }
5662 }
5663
5664 #[test]
5665 fn test_no_trycast_sql() {
5666 let trycast_expr = Expression::TryCast(Box::new(Cast {
5668 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
5669 to: DataType::Int {
5670 length: None,
5671 integer_spelling: false,
5672 },
5673 trailing_comments: vec![],
5674 double_colon_syntax: false,
5675 format: None,
5676 default: None,
5677 inferred_type: None,
5678 }));
5679
5680 let result = no_trycast_sql(trycast_expr).unwrap();
5681 assert!(matches!(result, Expression::Cast(_)));
5682 }
5683
5684 #[test]
5685 fn test_no_safe_cast_sql() {
5686 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
5688 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
5689 to: DataType::Int {
5690 length: None,
5691 integer_spelling: false,
5692 },
5693 trailing_comments: vec![],
5694 double_colon_syntax: false,
5695 format: None,
5696 default: None,
5697 inferred_type: None,
5698 }));
5699
5700 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
5701 assert!(matches!(result, Expression::Cast(_)));
5702 }
5703
5704 #[test]
5705 fn test_explode_to_unnest_presto() {
5706 let spark = Dialect::get(DialectType::Spark);
5707 let result = spark
5708 .transpile_to("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
5709 .unwrap();
5710 assert_eq!(
5711 result[0],
5712 "SELECT IF(_u.pos = _u_2.pos_2, _u_2.col) AS col FROM tbl CROSS JOIN UNNEST(SEQUENCE(1, GREATEST(CARDINALITY(x)))) AS _u(pos) CROSS JOIN UNNEST(x) WITH ORDINALITY AS _u_2(col, pos_2) WHERE _u.pos = _u_2.pos_2 OR (_u.pos > CARDINALITY(x) AND _u_2.pos_2 = CARDINALITY(x))"
5713 );
5714 }
5715
5716 #[test]
5717 fn test_explode_to_unnest_bigquery() {
5718 let spark = Dialect::get(DialectType::Spark);
5719 let result = spark
5720 .transpile_to("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
5721 .unwrap();
5722 assert_eq!(
5723 result[0],
5724 "SELECT IF(pos = pos_2, col, NULL) AS col FROM tbl CROSS JOIN UNNEST(GENERATE_ARRAY(0, GREATEST(ARRAY_LENGTH(x)) - 1)) AS pos CROSS JOIN UNNEST(x) AS col WITH OFFSET AS pos_2 WHERE pos = pos_2 OR (pos > (ARRAY_LENGTH(x) - 1) AND pos_2 = (ARRAY_LENGTH(x) - 1))"
5725 );
5726 }
5727}