1use crate::error::Result;
10use crate::dialects::{Dialect, DialectType};
11use crate::dialects::transform_recursive;
12use crate::expressions::{
13 Alias, BinaryOp, BooleanLiteral, Cast, DataType, Exists, Expression, From, Identifier, Join,
14 Function, JoinKind, Lateral, LateralView, Literal, NamedArgSeparator, NamedArgument, Over, Select, StructField,
15 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 = Expression::Function(Box::new(Function::new(
72 "ARRAYS_ZIP".to_string(),
73 all_args,
74 )));
75 Expression::Function(Box::new(Function::new(
76 "INLINE".to_string(),
77 vec![arrays_zip],
78 )))
79 } else {
80 Expression::Explode(Box::new(UnaryFunc::new(unnest.this.clone())))
82 }
83}
84
85fn unnest_to_explode_select_inner(expr: Expression) -> Result<Expression> {
86 let Expression::Select(mut select) = expr else { return Ok(expr); };
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.column_aliases.iter()
134 .map(|s| Identifier::new(s))
135 .collect();
136 (alias, col_aliases, *lat.this)
137 } else {
138 (None, Vec::new(), join.this)
139 }
140 } else {
141 (None, Vec::new(), join.this)
142 };
143
144 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(join_expr);
145
146 let final_alias = lateral_alias.or(alias_name);
148 let final_col_aliases = if !lateral_col_aliases.is_empty() {
149 lateral_col_aliases
150 } else {
151 column_aliases
152 };
153
154 let table_alias = final_alias.or_else(|| {
156 Some(Identifier::new("unnest"))
157 });
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) => {
204 match &*lat.this {
205 Expression::Unnest(_) => (true, true),
206 Expression::Alias(a) => {
207 if matches!(a.this, Expression::Unnest(_)) {
208 (true, true)
209 } else {
210 (false, true)
211 }
212 }
213 _ => (false, true),
214 }
215 }
216 _ => (false, false),
217 }
218}
219
220fn replace_from_unnest(from_item: Expression) -> Expression {
222 match from_item {
223 Expression::Alias(mut a) => {
224 if let Expression::Unnest(unnest) = a.this {
225 a.this = make_udtf_expr(&unnest);
226 }
227 Expression::Alias(a)
228 }
229 Expression::Unnest(unnest) => {
230 make_udtf_expr(&unnest)
231 }
232 other => other,
233 }
234}
235
236fn extract_unnest_info(expr: Expression) -> (Option<Identifier>, Vec<Identifier>, UnnestFunc) {
238 match expr {
239 Expression::Alias(a) => {
240 if let Expression::Unnest(unnest) = a.this {
241 (Some(a.alias), a.column_aliases, *unnest)
242 } else {
243 (Some(a.alias), a.column_aliases, UnnestFunc {
245 this: a.this,
246 expressions: Vec::new(),
247 with_ordinality: false,
248 alias: None,
249 offset_alias: None,
250 })
251 }
252 }
253 Expression::Unnest(unnest) => {
254 let alias = unnest.alias.clone();
255 (alias, Vec::new(), *unnest)
256 }
257 _ => {
258 (None, Vec::new(), UnnestFunc {
259 this: expr,
260 expressions: Vec::new(),
261 with_ordinality: false,
262 alias: None,
263 offset_alias: None,
264 })
265 }
266 }
267}
268
269pub fn explode_to_unnest(expr: Expression) -> Result<Expression> {
271 match expr {
272 Expression::Explode(explode) => {
273 Ok(Expression::Unnest(Box::new(UnnestFunc {
274 this: explode.this,
275 expressions: Vec::new(),
276 with_ordinality: false,
277 alias: None,
278 offset_alias: None,
279 })))
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(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(Literal::Number(n)) if n == "1" || n == "0" => {
304 Ok(Expression::Boolean(BooleanLiteral { value: n == "1" }))
305 }
306 _ => Ok(expr),
307 }
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 { precision: None, scale: None },
352 DataType::TinyInt { .. } => DataType::TinyInt { length: None },
353 DataType::SmallInt { .. } => DataType::SmallInt { length: None },
354 DataType::Int { .. } => DataType::Int { length: None, integer_spelling: false },
355 DataType::BigInt { .. } => DataType::BigInt { length: None },
356
357 DataType::Char { .. } => DataType::Char { length: None },
359 DataType::VarChar { .. } => DataType::VarChar { length: None, parenthesized_length: false },
360
361 DataType::Binary { .. } => DataType::Binary { length: None },
363 DataType::VarBinary { .. } => DataType::VarBinary { length: None },
364
365 DataType::Bit { .. } => DataType::Bit { length: None },
367 DataType::VarBit { .. } => DataType::VarBit { length: None },
368
369 DataType::Time { .. } => DataType::Time { precision: None, timezone: false },
371 DataType::Timestamp { timezone, .. } => DataType::Timestamp { precision: None, timezone },
372
373 DataType::Array { element_type, dimension } => DataType::Array {
375 element_type: Box::new(strip_data_type_params(*element_type)),
376 dimension,
377 },
378
379 DataType::Map { key_type, value_type } => DataType::Map {
381 key_type: Box::new(strip_data_type_params(*key_type)),
382 value_type: Box::new(strip_data_type_params(*value_type)),
383 },
384
385 DataType::Struct { fields, nested } => DataType::Struct {
387 fields: fields
388 .into_iter()
389 .map(|f| StructField::with_options(f.name, strip_data_type_params(f.data_type), f.options))
390 .collect(),
391 nested,
392 },
393
394 DataType::Vector { element_type, .. } => DataType::Vector {
396 element_type: element_type.map(|et| Box::new(strip_data_type_params(*et))),
397 dimension: None,
398 },
399
400 DataType::Object { fields, modifier } => DataType::Object {
402 fields: fields
403 .into_iter()
404 .map(|(name, ty, not_null)| (name, strip_data_type_params(ty), not_null))
405 .collect(),
406 modifier,
407 },
408
409 other => other,
411 }
412}
413
414
415pub fn eliminate_qualify(expr: Expression) -> Result<Expression> {
430 match expr {
431 Expression::Select(mut select) => {
432 if let Some(qualify) = select.qualify.take() {
433 let qualify_filter = qualify.this;
440 let window_alias_name = "_w".to_string();
441 let window_alias_ident = Identifier::new(window_alias_name.clone());
442
443 let (window_expr, outer_where) = extract_window_from_condition(
446 qualify_filter.clone(),
447 &window_alias_ident,
448 );
449
450 if let Some(win_expr) = window_expr {
451 let window_alias_expr = Expression::Alias(Box::new(crate::expressions::Alias {
453 this: win_expr,
454 alias: window_alias_ident.clone(),
455 column_aliases: vec![],
456 pre_alias_comments: vec![],
457 trailing_comments: vec![],
458 }));
459
460 let original_exprs = select.expressions.clone();
462 select.expressions.push(window_alias_expr);
463
464 let inner_select = Expression::Select(select);
466 let subquery = Subquery {
467 this: inner_select,
468 alias: Some(Identifier::new("_t".to_string())),
469 column_aliases: vec![],
470 order_by: None,
471 limit: None,
472 offset: None,
473 distribute_by: None,
474 sort_by: None,
475 cluster_by: None,
476 lateral: false,
477 modifiers_inside: false,
478 trailing_comments: vec![],
479 };
480
481 let outer_select = Select {
483 expressions: original_exprs,
484 from: Some(From {
485 expressions: vec![Expression::Subquery(Box::new(subquery))],
486 }),
487 where_clause: Some(Where {
488 this: outer_where,
489 }),
490 ..Select::new()
491 };
492
493 return Ok(Expression::Select(Box::new(outer_select)));
494 } else {
495 let qualify_alias = Expression::Alias(Box::new(crate::expressions::Alias {
497 this: qualify_filter.clone(),
498 alias: window_alias_ident.clone(),
499 column_aliases: vec![],
500 pre_alias_comments: vec![],
501 trailing_comments: vec![],
502 }));
503
504 let original_exprs = select.expressions.clone();
505 select.expressions.push(qualify_alias);
506
507 let inner_select = Expression::Select(select);
508 let subquery = Subquery {
509 this: inner_select,
510 alias: Some(Identifier::new("_t".to_string())),
511 column_aliases: vec![],
512 order_by: None,
513 limit: None,
514 offset: None,
515 distribute_by: None,
516 sort_by: None,
517 cluster_by: None,
518 lateral: false,
519 modifiers_inside: false,
520 trailing_comments: vec![],
521 };
522
523 let outer_select = Select {
524 expressions: original_exprs,
525 from: Some(From {
526 expressions: vec![Expression::Subquery(Box::new(subquery))],
527 }),
528 where_clause: Some(Where {
529 this: Expression::Column(crate::expressions::Column {
530 name: window_alias_ident,
531 table: None,
532 join_mark: false,
533 trailing_comments: vec![],
534 }),
535 }),
536 ..Select::new()
537 };
538
539 return Ok(Expression::Select(Box::new(outer_select)));
540 }
541 }
542 Ok(Expression::Select(select))
543 }
544 other => Ok(other),
545 }
546}
547
548fn extract_window_from_condition(
552 condition: Expression,
553 alias: &Identifier,
554) -> (Option<Expression>, Expression) {
555 let alias_col = Expression::Column(crate::expressions::Column {
556 name: alias.clone(),
557 table: None,
558 join_mark: false,
559 trailing_comments: vec![],
560 });
561
562 match condition {
564 Expression::Eq(ref op) => {
566 if is_window_expr(&op.left) {
567 (Some(op.left.clone()), Expression::Eq(Box::new(BinaryOp {
568 left: alias_col,
569 right: op.right.clone(),
570 ..(**op).clone()
571 })))
572 } else if is_window_expr(&op.right) {
573 (Some(op.right.clone()), Expression::Eq(Box::new(BinaryOp {
574 left: op.left.clone(),
575 right: alias_col,
576 ..(**op).clone()
577 })))
578 } else {
579 (None, condition)
580 }
581 }
582 Expression::Neq(ref op) => {
583 if is_window_expr(&op.left) {
584 (Some(op.left.clone()), Expression::Neq(Box::new(BinaryOp {
585 left: alias_col,
586 right: op.right.clone(),
587 ..(**op).clone()
588 })))
589 } else if is_window_expr(&op.right) {
590 (Some(op.right.clone()), Expression::Neq(Box::new(BinaryOp {
591 left: op.left.clone(),
592 right: alias_col,
593 ..(**op).clone()
594 })))
595 } else {
596 (None, condition)
597 }
598 }
599 Expression::Lt(ref op) => {
600 if is_window_expr(&op.left) {
601 (Some(op.left.clone()), Expression::Lt(Box::new(BinaryOp {
602 left: alias_col,
603 right: op.right.clone(),
604 ..(**op).clone()
605 })))
606 } else if is_window_expr(&op.right) {
607 (Some(op.right.clone()), Expression::Lt(Box::new(BinaryOp {
608 left: op.left.clone(),
609 right: alias_col,
610 ..(**op).clone()
611 })))
612 } else {
613 (None, condition)
614 }
615 }
616 Expression::Lte(ref op) => {
617 if is_window_expr(&op.left) {
618 (Some(op.left.clone()), Expression::Lte(Box::new(BinaryOp {
619 left: alias_col,
620 right: op.right.clone(),
621 ..(**op).clone()
622 })))
623 } else if is_window_expr(&op.right) {
624 (Some(op.right.clone()), Expression::Lte(Box::new(BinaryOp {
625 left: op.left.clone(),
626 right: alias_col,
627 ..(**op).clone()
628 })))
629 } else {
630 (None, condition)
631 }
632 }
633 Expression::Gt(ref op) => {
634 if is_window_expr(&op.left) {
635 (Some(op.left.clone()), Expression::Gt(Box::new(BinaryOp {
636 left: alias_col,
637 right: op.right.clone(),
638 ..(**op).clone()
639 })))
640 } else if is_window_expr(&op.right) {
641 (Some(op.right.clone()), Expression::Gt(Box::new(BinaryOp {
642 left: op.left.clone(),
643 right: alias_col,
644 ..(**op).clone()
645 })))
646 } else {
647 (None, condition)
648 }
649 }
650 Expression::Gte(ref op) => {
651 if is_window_expr(&op.left) {
652 (Some(op.left.clone()), Expression::Gte(Box::new(BinaryOp {
653 left: alias_col,
654 right: op.right.clone(),
655 ..(**op).clone()
656 })))
657 } else if is_window_expr(&op.right) {
658 (Some(op.right.clone()), Expression::Gte(Box::new(BinaryOp {
659 left: op.left.clone(),
660 right: alias_col,
661 ..(**op).clone()
662 })))
663 } else {
664 (None, condition)
665 }
666 }
667 _ if is_window_expr(&condition) => {
669 (Some(condition), alias_col)
670 }
671 _ => (None, condition),
673 }
674}
675
676fn is_window_expr(expr: &Expression) -> bool {
678 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
679}
680
681pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
700 eliminate_distinct_on_for_dialect(expr, None)
701}
702
703pub fn eliminate_distinct_on_for_dialect(expr: Expression, target: Option<DialectType>) -> Result<Expression> {
708 use crate::expressions::Case;
709
710 if matches!(target, Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)) {
712 return Ok(expr);
713 }
714
715 enum NullsMode {
720 None, NullsFirst, CaseExpr, }
724
725 let nulls_mode = match target {
726 Some(DialectType::MySQL) | Some(DialectType::StarRocks) | Some(DialectType::SingleStore)
727 | Some(DialectType::TSQL) | Some(DialectType::Fabric) => NullsMode::CaseExpr,
728 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => NullsMode::None,
729 _ => NullsMode::NullsFirst,
731 };
732
733 match expr {
734 Expression::Select(mut select) => {
735 if let Some(distinct_cols) = select.distinct_on.take() {
736 if !distinct_cols.is_empty() {
737 let row_number_alias = Identifier::new("_row_number".to_string());
739
740 let order_exprs = if let Some(ref order_by) = select.order_by {
742 let mut exprs = order_by.expressions.clone();
743 match nulls_mode {
745 NullsMode::NullsFirst => {
746 for ord in &mut exprs {
747 if ord.desc && ord.nulls_first.is_none() {
748 ord.nulls_first = Some(true);
749 }
750 }
751 }
752 NullsMode::CaseExpr => {
753 let mut new_exprs = Vec::new();
756 for ord in &exprs {
757 if ord.desc && ord.nulls_first.is_none() {
758 let null_check = Expression::Case(Box::new(Case {
760 operand: None,
761 whens: vec![(
762 Expression::IsNull(Box::new(crate::expressions::IsNull {
763 this: ord.this.clone(),
764 not: false,
765 postfix_form: false,
766 })),
767 Expression::Literal(Literal::Number("1".to_string())),
768 )],
769 else_: Some(Expression::Literal(Literal::Number("0".to_string()))),
770 }));
771 new_exprs.push(crate::expressions::Ordered {
772 this: null_check,
773 desc: true,
774 nulls_first: None,
775 explicit_asc: false,
776 with_fill: None,
777 });
778 }
779 new_exprs.push(ord.clone());
780 }
781 exprs = new_exprs;
782 }
783 NullsMode::None => {}
784 }
785 exprs
786 } else {
787 distinct_cols
788 .iter()
789 .map(|e| crate::expressions::Ordered {
790 this: e.clone(),
791 desc: false,
792 nulls_first: None,
793 explicit_asc: false,
794 with_fill: None,
795 })
796 .collect()
797 };
798
799 let row_number_func = Expression::WindowFunction(Box::new(
801 crate::expressions::WindowFunction {
802 this: Expression::RowNumber(crate::expressions::RowNumber),
803 over: Over {
804 partition_by: distinct_cols,
805 order_by: order_exprs,
806 frame: None,
807 window_name: None,
808 alias: None,
809 },
810 keep: None,
811 },
812 ));
813
814 let mut inner_aliased_exprs = Vec::new();
818 let mut outer_select_exprs = Vec::new();
819 for orig_expr in &select.expressions {
820 match orig_expr {
821 Expression::Alias(alias) => {
822 inner_aliased_exprs.push(orig_expr.clone());
824 outer_select_exprs.push(Expression::Column(
825 crate::expressions::Column {
826 name: alias.alias.clone(),
827 table: None,
828 join_mark: false,
829 trailing_comments: vec![],
830 },
831 ));
832 }
833 Expression::Column(col) => {
834 inner_aliased_exprs.push(Expression::Alias(Box::new(
836 crate::expressions::Alias {
837 this: orig_expr.clone(),
838 alias: col.name.clone(),
839 column_aliases: vec![],
840 pre_alias_comments: vec![],
841 trailing_comments: vec![],
842 },
843 )));
844 outer_select_exprs.push(Expression::Column(
845 crate::expressions::Column {
846 name: col.name.clone(),
847 table: None,
848 join_mark: false,
849 trailing_comments: vec![],
850 },
851 ));
852 }
853 _ => {
854 inner_aliased_exprs.push(orig_expr.clone());
856 outer_select_exprs.push(orig_expr.clone());
857 }
858 }
859 }
860
861 let row_number_alias_expr =
863 Expression::Alias(Box::new(crate::expressions::Alias {
864 this: row_number_func,
865 alias: row_number_alias.clone(),
866 column_aliases: vec![],
867 pre_alias_comments: vec![],
868 trailing_comments: vec![],
869 }));
870 inner_aliased_exprs.push(row_number_alias_expr);
871
872 select.expressions = inner_aliased_exprs;
874
875 let _inner_order_by = select.order_by.take();
877
878 select.distinct = false;
880
881 let inner_select = Expression::Select(select);
883 let subquery = Subquery {
884 this: inner_select,
885 alias: Some(Identifier::new("_t".to_string())),
886 column_aliases: vec![],
887 order_by: None,
888 limit: None,
889 offset: None,
890 distribute_by: None,
891 sort_by: None,
892 cluster_by: None,
893 lateral: false,
894 modifiers_inside: false,
895 trailing_comments: vec![],
896 };
897
898 let outer_select = Select {
901 expressions: outer_select_exprs,
902 from: Some(From {
903 expressions: vec![Expression::Subquery(Box::new(subquery))],
904 }),
905 where_clause: Some(Where {
906 this: Expression::Eq(Box::new(BinaryOp {
907 left: Expression::Column(crate::expressions::Column {
908 name: row_number_alias,
909 table: None,
910 join_mark: false,
911 trailing_comments: vec![],
912 }),
913 right: Expression::Literal(Literal::Number("1".to_string())),
914 left_comments: vec![],
915 operator_comments: vec![],
916 trailing_comments: vec![],
917 })),
918 }),
919 ..Select::new()
920 };
921
922 return Ok(Expression::Select(Box::new(outer_select)));
923 }
924 }
925 Ok(Expression::Select(select))
926 }
927 other => Ok(other),
928 }
929}
930
931pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
939 match expr {
940 Expression::Select(mut select) => {
941 let mut new_joins = Vec::new();
942 let mut extra_where_conditions = Vec::new();
943
944 for join in select.joins.drain(..) {
945 match join.kind {
946 JoinKind::Semi | JoinKind::LeftSemi => {
947 if let Some(on_condition) = join.on {
948 let subquery_select = Select {
950 expressions: vec![Expression::Literal(Literal::Number(
951 "1".to_string(),
952 ))],
953 from: Some(From {
954 expressions: vec![join.this],
955 }),
956 where_clause: Some(Where {
957 this: on_condition,
958 }),
959 ..Select::new()
960 };
961
962 let exists = Expression::Exists(Box::new(Exists {
963 this: Expression::Subquery(Box::new(Subquery {
964 this: Expression::Select(Box::new(subquery_select)),
965 alias: None,
966 column_aliases: vec![],
967 order_by: None,
968 limit: None,
969 offset: None,
970 distribute_by: None,
971 sort_by: None,
972 cluster_by: None,
973 lateral: false,
974 modifiers_inside: false,
975 trailing_comments: vec![],
976 })),
977 not: false,
978 }));
979
980 extra_where_conditions.push(exists);
981 }
982 }
983 JoinKind::Anti | JoinKind::LeftAnti => {
984 if let Some(on_condition) = join.on {
985 let subquery_select = Select {
987 expressions: vec![Expression::Literal(Literal::Number(
988 "1".to_string(),
989 ))],
990 from: Some(From {
991 expressions: vec![join.this],
992 }),
993 where_clause: Some(Where {
994 this: on_condition,
995 }),
996 ..Select::new()
997 };
998
999 let not_exists = Expression::Exists(Box::new(Exists {
1001 this: Expression::Subquery(Box::new(Subquery {
1002 this: Expression::Select(Box::new(subquery_select)),
1003 alias: None,
1004 column_aliases: vec![],
1005 order_by: None,
1006 limit: None,
1007 offset: None,
1008 distribute_by: None,
1009 sort_by: None,
1010 cluster_by: None,
1011 lateral: false,
1012 modifiers_inside: false,
1013 trailing_comments: vec![],
1014 })),
1015 not: true,
1016 }));
1017
1018 extra_where_conditions.push(not_exists);
1019 }
1020 }
1021 _ => {
1022 new_joins.push(join);
1024 }
1025 }
1026 }
1027
1028 select.joins = new_joins;
1029
1030 if !extra_where_conditions.is_empty() {
1032 let combined = extra_where_conditions
1033 .into_iter()
1034 .reduce(|acc, cond| {
1035 Expression::And(Box::new(BinaryOp {
1036 left: acc,
1037 right: cond,
1038 left_comments: vec![],
1039 operator_comments: vec![],
1040 trailing_comments: vec![],
1041 }))
1042 })
1043 .unwrap();
1044
1045 select.where_clause = match select.where_clause {
1046 Some(Where { this: existing }) => Some(Where {
1047 this: Expression::And(Box::new(BinaryOp {
1048 left: existing,
1049 right: combined,
1050 left_comments: vec![],
1051 operator_comments: vec![],
1052 trailing_comments: vec![],
1053 })),
1054 }),
1055 None => Some(Where { this: combined }),
1056 };
1057 }
1058
1059 Ok(Expression::Select(select))
1060 }
1061 other => Ok(other),
1062 }
1063}
1064
1065pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
1083 match expr {
1084 Expression::Select(mut select) => {
1085 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
1087
1088 if let Some(idx) = full_outer_join_idx {
1089 let full_join_count = select.joins.iter().filter(|j| j.kind == JoinKind::Full).count();
1091 if full_join_count != 1 {
1092 return Ok(Expression::Select(select));
1093 }
1094
1095 let mut right_select = select.clone();
1097
1098 let full_join = &select.joins[idx];
1100 let join_condition = full_join.on.clone();
1101
1102 select.joins[idx].kind = JoinKind::Left;
1104
1105 right_select.joins[idx].kind = JoinKind::Right;
1107
1108 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
1110 if !from.expressions.is_empty() {
1111 let anti_subquery = Expression::Select(Box::new(Select {
1112 expressions: vec![Expression::Literal(Literal::Number("1".to_string()))],
1113 from: Some(from.clone()),
1114 where_clause: Some(Where { this: join_cond.clone() }),
1115 ..Select::new()
1116 }));
1117
1118 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
1119 this: Expression::Exists(Box::new(Exists {
1120 this: Expression::Subquery(Box::new(Subquery {
1121 this: anti_subquery,
1122 alias: None,
1123 column_aliases: vec![],
1124 order_by: None,
1125 limit: None,
1126 offset: None,
1127 distribute_by: None,
1128 sort_by: None,
1129 cluster_by: None,
1130 lateral: false,
1131 modifiers_inside: false,
1132 trailing_comments: vec![],
1133 })),
1134 not: false,
1135 })),
1136 }));
1137
1138 right_select.where_clause = Some(Where {
1140 this: match right_select.where_clause {
1141 Some(w) => Expression::And(Box::new(BinaryOp {
1142 left: w.this,
1143 right: not_exists,
1144 left_comments: vec![],
1145 operator_comments: vec![],
1146 trailing_comments: vec![],
1147 })),
1148 None => not_exists,
1149 },
1150 });
1151 }
1152 }
1153
1154 right_select.with = None;
1156
1157 let order_by = select.order_by.take();
1159
1160 let union = crate::expressions::Union {
1162 left: Expression::Select(select),
1163 right: Expression::Select(right_select),
1164 all: true, distinct: false,
1166 with: None,
1167 order_by,
1168 limit: None,
1169 offset: None,
1170 distribute_by: None,
1171 sort_by: None,
1172 cluster_by: None,
1173 by_name: false,
1174 side: None,
1175 kind: None,
1176 corresponding: false,
1177 strict: false,
1178 on_columns: Vec::new(),
1179 };
1180
1181 return Ok(Expression::Union(Box::new(union)));
1182 }
1183
1184 Ok(Expression::Select(select))
1185 }
1186 other => Ok(other),
1187 }
1188}
1189
1190pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
1203 match expr {
1204 Expression::Select(mut select) => {
1205 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
1207 let mut has_recursive = false;
1208
1209 collect_nested_ctes(&Expression::Select(select.clone()), &mut collected_ctes, &mut has_recursive, true);
1211
1212 if !collected_ctes.is_empty() {
1214 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
1215 ctes: Vec::new(),
1216 recursive: false,
1217 leading_comments: vec![],
1218 search: None,
1219 });
1220
1221 if has_recursive {
1223 top_with.recursive = true;
1224 }
1225
1226 let mut new_ctes = collected_ctes;
1228 new_ctes.append(&mut top_with.ctes);
1229 top_with.ctes = new_ctes;
1230 }
1231
1232 Ok(Expression::Select(select))
1233 }
1234 other => Ok(other),
1235 }
1236}
1237
1238fn collect_nested_ctes(
1240 expr: &Expression,
1241 collected: &mut Vec<crate::expressions::Cte>,
1242 has_recursive: &mut bool,
1243 is_top_level: bool,
1244) {
1245 match expr {
1246 Expression::Select(select) => {
1247 if !is_top_level {
1249 if let Some(ref with) = select.with {
1250 if with.recursive {
1251 *has_recursive = true;
1252 }
1253 collected.extend(with.ctes.clone());
1254 }
1255 }
1256
1257 if let Some(ref from) = select.from {
1259 for expr in &from.expressions {
1260 collect_nested_ctes(expr, collected, has_recursive, false);
1261 }
1262 }
1263
1264 for join in &select.joins {
1266 collect_nested_ctes(&join.this, collected, has_recursive, false);
1267 }
1268
1269 for sel_expr in &select.expressions {
1271 collect_nested_ctes(sel_expr, collected, has_recursive, false);
1272 }
1273
1274 if let Some(ref where_clause) = select.where_clause {
1276 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
1277 }
1278 }
1279 Expression::Subquery(subquery) => {
1280 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
1282 }
1283 Expression::Alias(alias) => {
1284 collect_nested_ctes(&alias.this, collected, has_recursive, false);
1285 }
1286 _ => {}
1288 }
1289}
1290
1291pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
1307 match expr {
1308 Expression::Select(mut select) => {
1309 if let Some(named_windows) = select.windows.take() {
1310 let window_map: std::collections::HashMap<String, &Over> = named_windows
1312 .iter()
1313 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
1314 .collect();
1315
1316 select.expressions = select
1318 .expressions
1319 .into_iter()
1320 .map(|e| inline_window_refs(e, &window_map))
1321 .collect();
1322 }
1323 Ok(Expression::Select(select))
1324 }
1325 other => Ok(other),
1326 }
1327}
1328
1329fn inline_window_refs(
1331 expr: Expression,
1332 window_map: &std::collections::HashMap<String, &Over>,
1333) -> Expression {
1334 match expr {
1335 Expression::WindowFunction(mut wf) => {
1336 if let Some(ref name) = wf.over.window_name {
1338 let key = name.name.to_lowercase();
1339 if let Some(named_spec) = window_map.get(&key) {
1340 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
1342 wf.over.partition_by = named_spec.partition_by.clone();
1343 }
1344 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
1345 wf.over.order_by = named_spec.order_by.clone();
1346 }
1347 if wf.over.frame.is_none() && named_spec.frame.is_some() {
1348 wf.over.frame = named_spec.frame.clone();
1349 }
1350 wf.over.window_name = None;
1352 }
1353 }
1354 Expression::WindowFunction(wf)
1355 }
1356 Expression::Alias(mut alias) => {
1357 alias.this = inline_window_refs(alias.this, window_map);
1359 Expression::Alias(alias)
1360 }
1361 other => other,
1364 }
1365}
1366
1367pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
1381 match expr {
1382 Expression::Select(mut select) => {
1383 let has_join_marks = select.where_clause.as_ref().map_or(false, |w| {
1385 contains_join_mark(&w.this)
1386 });
1387
1388 if !has_join_marks {
1389 return Ok(Expression::Select(select));
1390 }
1391
1392 let from_tables: Vec<String> = select
1394 .from
1395 .as_ref()
1396 .map(|f| {
1397 f.expressions
1398 .iter()
1399 .filter_map(|e| get_table_name(e))
1400 .collect()
1401 })
1402 .unwrap_or_default();
1403
1404 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
1406 std::collections::HashMap::new();
1407 let mut remaining_conditions: Vec<Expression> = Vec::new();
1408
1409 if let Some(ref where_clause) = select.where_clause {
1410 extract_join_mark_conditions(
1411 &where_clause.this,
1412 &mut join_conditions,
1413 &mut remaining_conditions,
1414 );
1415 }
1416
1417 let mut new_joins = select.joins.clone();
1419 for (table_name, conditions) in join_conditions {
1420 let table_in_from = from_tables.contains(&table_name);
1422
1423 if table_in_from && !conditions.is_empty() {
1424 let combined_condition = conditions.into_iter().reduce(|a, b| {
1426 Expression::And(Box::new(BinaryOp {
1427 left: a,
1428 right: b,
1429 left_comments: vec![],
1430 operator_comments: vec![],
1431 trailing_comments: vec![],
1432 }))
1433 });
1434
1435 if let Some(ref mut from) = select.from {
1437 if let Some(pos) = from.expressions.iter().position(|e| {
1438 get_table_name(e).map_or(false, |n| n == table_name)
1439 }) {
1440 if from.expressions.len() > 1 {
1441 let join_table = from.expressions.remove(pos);
1442 new_joins.push(crate::expressions::Join {
1443 this: join_table,
1444 kind: JoinKind::Left,
1445 on: combined_condition,
1446 using: vec![],
1447 use_inner_keyword: false,
1448 use_outer_keyword: true,
1449 deferred_condition: false,
1450 join_hint: None,
1451 match_condition: None,
1452 pivots: Vec::new(),
1453 });
1454 }
1455 }
1456 }
1457 }
1458 }
1459
1460 select.joins = new_joins;
1461
1462 if remaining_conditions.is_empty() {
1464 select.where_clause = None;
1465 } else {
1466 let combined = remaining_conditions.into_iter().reduce(|a, b| {
1467 Expression::And(Box::new(BinaryOp {
1468 left: a,
1469 right: b,
1470 left_comments: vec![],
1471 operator_comments: vec![],
1472 trailing_comments: vec![],
1473 }))
1474 });
1475 select.where_clause = combined.map(|c| Where { this: c });
1476 }
1477
1478 clear_join_marks(&mut Expression::Select(select.clone()));
1480
1481 Ok(Expression::Select(select))
1482 }
1483 other => Ok(other),
1484 }
1485}
1486
1487fn contains_join_mark(expr: &Expression) -> bool {
1489 match expr {
1490 Expression::Column(col) => col.join_mark,
1491 Expression::And(op) | Expression::Or(op) => {
1492 contains_join_mark(&op.left) || contains_join_mark(&op.right)
1493 }
1494 Expression::Eq(op) | Expression::Neq(op) | Expression::Lt(op)
1495 | Expression::Lte(op) | Expression::Gt(op) | Expression::Gte(op) => {
1496 contains_join_mark(&op.left) || contains_join_mark(&op.right)
1497 }
1498 Expression::Not(op) => contains_join_mark(&op.this),
1499 _ => false,
1500 }
1501}
1502
1503fn get_table_name(expr: &Expression) -> Option<String> {
1505 match expr {
1506 Expression::Table(t) => Some(t.name.name.clone()),
1507 Expression::Alias(a) => Some(a.alias.name.clone()),
1508 _ => None,
1509 }
1510}
1511
1512fn extract_join_mark_conditions(
1514 expr: &Expression,
1515 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
1516 remaining: &mut Vec<Expression>,
1517) {
1518 match expr {
1519 Expression::And(op) => {
1520 extract_join_mark_conditions(&op.left, join_conditions, remaining);
1521 extract_join_mark_conditions(&op.right, join_conditions, remaining);
1522 }
1523 _ => {
1524 if let Some(table) = get_join_mark_table(expr) {
1525 join_conditions
1526 .entry(table)
1527 .or_insert_with(Vec::new)
1528 .push(expr.clone());
1529 } else {
1530 remaining.push(expr.clone());
1531 }
1532 }
1533 }
1534}
1535
1536fn get_join_mark_table(expr: &Expression) -> Option<String> {
1538 match expr {
1539 Expression::Eq(op) | Expression::Neq(op) | Expression::Lt(op)
1540 | Expression::Lte(op) | Expression::Gt(op) | Expression::Gte(op) => {
1541 if let Expression::Column(col) = &op.left {
1543 if col.join_mark {
1544 return col.table.as_ref().map(|t| t.name.clone());
1545 }
1546 }
1547 if let Expression::Column(col) = &op.right {
1548 if col.join_mark {
1549 return col.table.as_ref().map(|t| t.name.clone());
1550 }
1551 }
1552 None
1553 }
1554 _ => None,
1555 }
1556}
1557
1558fn clear_join_marks(expr: &mut Expression) {
1560 match expr {
1561 Expression::Column(col) => col.join_mark = false,
1562 Expression::Select(select) => {
1563 if let Some(ref mut w) = select.where_clause {
1564 clear_join_marks(&mut w.this);
1565 }
1566 for sel_expr in &mut select.expressions {
1567 clear_join_marks(sel_expr);
1568 }
1569 }
1570 Expression::And(op) | Expression::Or(op) => {
1571 clear_join_marks(&mut op.left);
1572 clear_join_marks(&mut op.right);
1573 }
1574 Expression::Eq(op) | Expression::Neq(op) | Expression::Lt(op)
1575 | Expression::Lte(op) | Expression::Gt(op) | Expression::Gte(op) => {
1576 clear_join_marks(&mut op.left);
1577 clear_join_marks(&mut op.right);
1578 }
1579 _ => {}
1580 }
1581}
1582
1583pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
1590 match expr {
1591 Expression::Select(mut select) => {
1592 if let Some(ref mut with) = select.with {
1593 if with.recursive {
1594 let mut counter = 0;
1595 for cte in &mut with.ctes {
1596 if cte.columns.is_empty() {
1597 if let Expression::Select(ref cte_select) = cte.this {
1599 let names: Vec<Identifier> = cte_select
1600 .expressions
1601 .iter()
1602 .map(|e| match e {
1603 Expression::Alias(a) => a.alias.clone(),
1604 Expression::Column(c) => c.name.clone(),
1605 _ => {
1606 counter += 1;
1607 Identifier::new(format!("_c_{}", counter))
1608 }
1609 })
1610 .collect();
1611 cte.columns = names;
1612 }
1613 }
1614 }
1615 }
1616 }
1617 Ok(Expression::Select(select))
1618 }
1619 other => Ok(other),
1620 }
1621}
1622
1623pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
1630 match expr {
1631 Expression::Cast(mut cast) => {
1632 if let Expression::Literal(Literal::String(ref s)) = cast.this {
1633 if s.to_lowercase() == "epoch" {
1634 if is_temporal_type(&cast.to) {
1635 cast.this =
1636 Expression::Literal(Literal::String("1970-01-01 00:00:00".to_string()));
1637 }
1638 }
1639 }
1640 Ok(Expression::Cast(cast))
1641 }
1642 Expression::TryCast(mut try_cast) => {
1643 if let Expression::Literal(Literal::String(ref s)) = try_cast.this {
1644 if s.to_lowercase() == "epoch" {
1645 if is_temporal_type(&try_cast.to) {
1646 try_cast.this =
1647 Expression::Literal(Literal::String("1970-01-01 00:00:00".to_string()));
1648 }
1649 }
1650 }
1651 Ok(Expression::TryCast(try_cast))
1652 }
1653 other => Ok(other),
1654 }
1655}
1656
1657fn is_temporal_type(dt: &DataType) -> bool {
1659 matches!(
1660 dt,
1661 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
1662 )
1663}
1664
1665pub fn ensure_bools(expr: Expression) -> Result<Expression> {
1690 let expr = ensure_bools_in_case(expr);
1692 match expr {
1693 Expression::Select(mut select) => {
1694 if let Some(ref mut where_clause) = select.where_clause {
1696 where_clause.this = ensure_bool_condition(where_clause.this.clone());
1697 }
1698 if let Some(ref mut having) = select.having {
1700 having.this = ensure_bool_condition(having.this.clone());
1701 }
1702 Ok(Expression::Select(select))
1703 }
1704 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => {
1706 Ok(ensure_bool_condition(expr))
1707 }
1708 other => Ok(other),
1709 }
1710}
1711
1712fn ensure_bools_in_case(expr: Expression) -> Expression {
1716 match expr {
1717 Expression::Case(mut case) => {
1718 case.whens = case.whens.into_iter().map(|(condition, result)| {
1719 let new_condition = ensure_bool_condition(ensure_bools_in_case(condition));
1720 let new_result = ensure_bools_in_case(result);
1721 (new_condition, new_result)
1722 }).collect();
1723 if let Some(else_expr) = case.else_ {
1724 case.else_ = Some(ensure_bools_in_case(else_expr));
1725 }
1726 Expression::Case(Box::new(*case))
1727 }
1728 Expression::Select(mut select) => {
1729 select.expressions = select.expressions.into_iter().map(ensure_bools_in_case).collect();
1731 Expression::Select(select)
1733 }
1734 Expression::Alias(mut alias) => {
1735 alias.this = ensure_bools_in_case(alias.this);
1736 Expression::Alias(alias)
1737 }
1738 Expression::Paren(mut paren) => {
1739 paren.this = ensure_bools_in_case(paren.this);
1740 Expression::Paren(paren)
1741 }
1742 other => other,
1743 }
1744}
1745
1746fn is_boolean_expression(expr: &Expression) -> bool {
1749 matches!(
1750 expr,
1751 Expression::Eq(_)
1752 | Expression::Neq(_)
1753 | Expression::Lt(_)
1754 | Expression::Lte(_)
1755 | Expression::Gt(_)
1756 | Expression::Gte(_)
1757 | Expression::Is(_)
1758 | Expression::IsNull(_)
1759 | Expression::IsTrue(_)
1760 | Expression::IsFalse(_)
1761 | Expression::Like(_)
1762 | Expression::ILike(_)
1763 | Expression::SimilarTo(_)
1764 | Expression::Glob(_)
1765 | Expression::RegexpLike(_)
1766 | Expression::In(_)
1767 | Expression::Between(_)
1768 | Expression::Exists(_)
1769 | Expression::And(_)
1770 | Expression::Or(_)
1771 | Expression::Not(_)
1772 | Expression::Any(_)
1773 | Expression::All(_)
1774 | Expression::EqualNull(_)
1775 )
1776}
1777
1778fn wrap_neq_zero(expr: Expression) -> Expression {
1780 Expression::Neq(Box::new(BinaryOp {
1781 left: expr,
1782 right: Expression::Literal(Literal::Number("0".to_string())),
1783 left_comments: vec![],
1784 operator_comments: vec![],
1785 trailing_comments: vec![],
1786 }))
1787}
1788
1789fn ensure_bool_condition(expr: Expression) -> Expression {
1795 match expr {
1796 Expression::And(op) => {
1798 let new_op = BinaryOp {
1799 left: ensure_bool_condition(op.left.clone()),
1800 right: ensure_bool_condition(op.right.clone()),
1801 left_comments: op.left_comments.clone(),
1802 operator_comments: op.operator_comments.clone(),
1803 trailing_comments: op.trailing_comments.clone(),
1804 };
1805 Expression::And(Box::new(new_op))
1806 }
1807 Expression::Or(op) => {
1808 let new_op = BinaryOp {
1809 left: ensure_bool_condition(op.left.clone()),
1810 right: ensure_bool_condition(op.right.clone()),
1811 left_comments: op.left_comments.clone(),
1812 operator_comments: op.operator_comments.clone(),
1813 trailing_comments: op.trailing_comments.clone(),
1814 };
1815 Expression::Or(Box::new(new_op))
1816 }
1817 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
1819 this: ensure_bool_condition(op.this.clone()),
1820 })),
1821 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
1823 this: ensure_bool_condition(paren.this.clone()),
1824 trailing_comments: paren.trailing_comments.clone(),
1825 })),
1826 Expression::Boolean(BooleanLiteral { value: true }) => {
1828 Expression::Paren(Box::new(crate::expressions::Paren {
1829 this: Expression::Eq(Box::new(BinaryOp {
1830 left: Expression::Literal(Literal::Number("1".to_string())),
1831 right: Expression::Literal(Literal::Number("1".to_string())),
1832 left_comments: vec![],
1833 operator_comments: vec![],
1834 trailing_comments: vec![],
1835 })),
1836 trailing_comments: vec![],
1837 }))
1838 }
1839 Expression::Boolean(BooleanLiteral { value: false }) => {
1840 Expression::Paren(Box::new(crate::expressions::Paren {
1841 this: Expression::Eq(Box::new(BinaryOp {
1842 left: Expression::Literal(Literal::Number("1".to_string())),
1843 right: Expression::Literal(Literal::Number("0".to_string())),
1844 left_comments: vec![],
1845 operator_comments: vec![],
1846 trailing_comments: vec![],
1847 })),
1848 trailing_comments: vec![],
1849 }))
1850 }
1851 ref e if is_boolean_expression(e) => expr,
1853 _ => wrap_neq_zero(expr),
1856 }
1857}
1858
1859pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
1865 Ok(unqualify_columns_recursive(expr))
1866}
1867
1868fn unqualify_columns_recursive(expr: Expression) -> Expression {
1870 match expr {
1871 Expression::Column(mut col) => {
1872 col.table = None;
1873 Expression::Column(col)
1874 }
1875 Expression::Select(mut select) => {
1876 select.expressions = select
1877 .expressions
1878 .into_iter()
1879 .map(unqualify_columns_recursive)
1880 .collect();
1881 if let Some(ref mut where_clause) = select.where_clause {
1882 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
1883 }
1884 if let Some(ref mut having) = select.having {
1885 having.this = unqualify_columns_recursive(having.this.clone());
1886 }
1887 if let Some(ref mut group_by) = select.group_by {
1888 group_by.expressions = group_by
1889 .expressions
1890 .iter()
1891 .cloned()
1892 .map(unqualify_columns_recursive)
1893 .collect();
1894 }
1895 if let Some(ref mut order_by) = select.order_by {
1896 order_by.expressions = order_by
1897 .expressions
1898 .iter()
1899 .map(|o| crate::expressions::Ordered {
1900 this: unqualify_columns_recursive(o.this.clone()),
1901 desc: o.desc,
1902 nulls_first: o.nulls_first,
1903 explicit_asc: o.explicit_asc,
1904 with_fill: o.with_fill.clone(),
1905 })
1906 .collect();
1907 }
1908 for join in &mut select.joins {
1909 if let Some(ref mut on) = join.on {
1910 *on = unqualify_columns_recursive(on.clone());
1911 }
1912 }
1913 Expression::Select(select)
1914 }
1915 Expression::Alias(mut alias) => {
1916 alias.this = unqualify_columns_recursive(alias.this);
1917 Expression::Alias(alias)
1918 }
1919 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
1921 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
1922 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
1923 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
1924 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
1925 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
1926 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
1927 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
1928 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
1929 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
1930 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
1931 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
1932 Expression::Function(mut func) => {
1934 func.args = func.args.into_iter().map(unqualify_columns_recursive).collect();
1935 Expression::Function(func)
1936 }
1937 Expression::AggregateFunction(mut func) => {
1938 func.args = func.args.into_iter().map(unqualify_columns_recursive).collect();
1939 Expression::AggregateFunction(func)
1940 }
1941 Expression::Case(mut case) => {
1942 case.whens = case
1943 .whens
1944 .into_iter()
1945 .map(|(cond, result)| {
1946 (
1947 unqualify_columns_recursive(cond),
1948 unqualify_columns_recursive(result),
1949 )
1950 })
1951 .collect();
1952 if let Some(else_expr) = case.else_ {
1953 case.else_ = Some(unqualify_columns_recursive(else_expr));
1954 }
1955 Expression::Case(case)
1956 }
1957 other => other,
1959 }
1960}
1961
1962fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
1964 op.left = unqualify_columns_recursive(op.left);
1965 op.right = unqualify_columns_recursive(op.right);
1966 op
1967}
1968
1969pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
1989 match expr {
1990 Expression::Select(mut select) => {
1991 let mut cte_count = 0;
1992 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
1993
1994 if let Some(ref mut from) = select.from {
1996 for table_expr in &mut from.expressions {
1997 if let Some((cte, replacement)) = try_convert_generate_date_array(table_expr, &mut cte_count) {
1998 new_ctes.push(cte);
1999 *table_expr = replacement;
2000 }
2001 }
2002 }
2003
2004 for join in &mut select.joins {
2006 if let Some((cte, replacement)) = try_convert_generate_date_array(&join.this, &mut cte_count) {
2007 new_ctes.push(cte);
2008 join.this = replacement;
2009 }
2010 }
2011
2012 if !new_ctes.is_empty() {
2014 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
2015 ctes: Vec::new(),
2016 recursive: true, leading_comments: vec![],
2018 search: None,
2019 });
2020 with_clause.recursive = true;
2021
2022 let mut all_ctes = new_ctes;
2024 all_ctes.append(&mut with_clause.ctes);
2025 with_clause.ctes = all_ctes;
2026 }
2027
2028 Ok(Expression::Select(select))
2029 }
2030 other => Ok(other),
2031 }
2032}
2033
2034fn try_convert_generate_date_array(
2036 expr: &Expression,
2037 cte_count: &mut usize,
2038) -> Option<(crate::expressions::Cte, Expression)> {
2039 if let Expression::Unnest(unnest) = expr {
2041 if let Expression::GenerateDateArray(gda) = &unnest.this {
2042 let start = gda.start.as_ref()?;
2044 let end = gda.end.as_ref()?;
2045 let step = gda.step.as_ref();
2046
2047 let cte_name = if *cte_count == 0 {
2049 "_generated_dates".to_string()
2050 } else {
2051 format!("_generated_dates_{}", cte_count)
2052 };
2053 *cte_count += 1;
2054
2055 let column_name = Identifier::new("date_value".to_string());
2056
2057 let base_select = Select {
2059 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
2060 this: Expression::Cast(Box::new(Cast {
2061 this: (**start).clone(),
2062 to: DataType::Date,
2063 trailing_comments: vec![],
2064 double_colon_syntax: false,
2065 format: None,
2066 default: None,
2067 })),
2068 alias: column_name.clone(),
2069 column_aliases: vec![],
2070 pre_alias_comments: vec![],
2071 trailing_comments: vec![],
2072 }))],
2073 ..Select::new()
2074 };
2075
2076 let date_add_expr = Expression::Function(Box::new(crate::expressions::Function {
2078 name: "DATE_ADD".to_string(),
2079 args: vec![
2080 Expression::Column(crate::expressions::Column {
2081 name: column_name.clone(),
2082 table: None,
2083 join_mark: false,
2084 trailing_comments: vec![],
2085 }),
2086 step.map(|s| (**s).clone()).unwrap_or_else(||
2087 Expression::Interval(Box::new(crate::expressions::Interval {
2088 this: Some(Expression::Literal(Literal::Number("1".to_string()))),
2089 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
2090 unit: crate::expressions::IntervalUnit::Day,
2091 use_plural: false,
2092 }),
2093 }))
2094 ),
2095 ],
2096 distinct: false,
2097 trailing_comments: vec![],
2098 use_bracket_syntax: false,
2099 no_parens: false,
2100 quoted: false,
2101 }));
2102
2103 let cast_date_add = Expression::Cast(Box::new(Cast {
2104 this: date_add_expr.clone(),
2105 to: DataType::Date,
2106 trailing_comments: vec![],
2107 double_colon_syntax: false,
2108 format: None,
2109 default: None,
2110 }));
2111
2112 let recursive_select = Select {
2113 expressions: vec![cast_date_add.clone()],
2114 from: Some(From {
2115 expressions: vec![Expression::Table(crate::expressions::TableRef::new(&cte_name))],
2116 }),
2117 where_clause: Some(Where {
2118 this: Expression::Lte(Box::new(BinaryOp {
2119 left: cast_date_add,
2120 right: Expression::Cast(Box::new(Cast {
2121 this: (**end).clone(),
2122 to: DataType::Date,
2123 trailing_comments: vec![],
2124 double_colon_syntax: false,
2125 format: None,
2126 default: None,
2127 })),
2128 left_comments: vec![],
2129 operator_comments: vec![],
2130 trailing_comments: vec![],
2131 })),
2132 }),
2133 ..Select::new()
2134 };
2135
2136 let union = crate::expressions::Union {
2138 left: Expression::Select(Box::new(base_select)),
2139 right: Expression::Select(Box::new(recursive_select)),
2140 all: true, distinct: false,
2142 with: None,
2143 order_by: None,
2144 limit: None,
2145 offset: None,
2146 distribute_by: None,
2147 sort_by: None,
2148 cluster_by: None,
2149 by_name: false,
2150 side: None,
2151 kind: None,
2152 corresponding: false,
2153 strict: false,
2154 on_columns: Vec::new(),
2155 };
2156
2157 let cte = crate::expressions::Cte {
2159 this: Expression::Union(Box::new(union)),
2160 alias: Identifier::new(cte_name.clone()),
2161 columns: vec![column_name.clone()],
2162 materialized: None,
2163 key_expressions: Vec::new(),
2164 alias_first: true,
2165 };
2166
2167 let replacement_select = Select {
2169 expressions: vec![Expression::Column(crate::expressions::Column {
2170 name: column_name,
2171 table: None,
2172 join_mark: false,
2173 trailing_comments: vec![],
2174 })],
2175 from: Some(From {
2176 expressions: vec![Expression::Table(crate::expressions::TableRef::new(&cte_name))],
2177 }),
2178 ..Select::new()
2179 };
2180
2181 let replacement = Expression::Subquery(Box::new(Subquery {
2182 this: Expression::Select(Box::new(replacement_select)),
2183 alias: Some(Identifier::new(cte_name)),
2184 column_aliases: vec![],
2185 order_by: None,
2186 limit: None,
2187 offset: None,
2188 distribute_by: None,
2189 sort_by: None,
2190 cluster_by: None,
2191 lateral: false,
2192 modifiers_inside: false,
2193 trailing_comments: vec![],
2194 }));
2195
2196 return Some((cte, replacement));
2197 }
2198 }
2199
2200 if let Expression::Alias(alias) = expr {
2202 if let Some((cte, replacement)) = try_convert_generate_date_array(&alias.this, cte_count) {
2203 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
2204 this: replacement,
2205 alias: alias.alias.clone(),
2206 column_aliases: alias.column_aliases.clone(),
2207 pre_alias_comments: alias.pre_alias_comments.clone(),
2208 trailing_comments: alias.trailing_comments.clone(),
2209 }));
2210 return Some((cte, new_alias));
2211 }
2212 }
2213
2214 None
2215}
2216
2217pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
2230 match expr {
2231 Expression::ILike(ilike) => {
2232 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
2234 name: "LOWER".to_string(),
2235 args: vec![ilike.left],
2236 distinct: false,
2237 trailing_comments: vec![],
2238 use_bracket_syntax: false,
2239 no_parens: false,
2240 quoted: false,
2241 }));
2242
2243 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
2244 name: "LOWER".to_string(),
2245 args: vec![ilike.right],
2246 distinct: false,
2247 trailing_comments: vec![],
2248 use_bracket_syntax: false,
2249 no_parens: false,
2250 quoted: false,
2251 }));
2252
2253 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
2254 left: lower_left,
2255 right: lower_right,
2256 escape: ilike.escape,
2257 quantifier: ilike.quantifier,
2258 })))
2259 }
2260 other => Ok(other),
2261 }
2262}
2263
2264pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
2272 match expr {
2273 Expression::TryCast(try_cast) => {
2274 Ok(Expression::Cast(try_cast))
2275 }
2276 other => Ok(other),
2277 }
2278}
2279
2280pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
2285 match expr {
2286 Expression::SafeCast(safe_cast) => {
2287 Ok(Expression::Cast(safe_cast))
2288 }
2289 other => Ok(other),
2290 }
2291}
2292
2293pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
2300 Ok(expr)
2302}
2303
2304pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
2318 match expr {
2321 Expression::Table(ref table) => {
2322 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
2325 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2327 this: expr.clone(),
2328 expressions: Vec::new(),
2329 with_ordinality: false,
2330 alias: None,
2331 offset_alias: None,
2332 }));
2333
2334 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
2336 this: unnest,
2337 alias: Identifier::new("_u".to_string()),
2338 column_aliases: vec![],
2339 pre_alias_comments: vec![],
2340 trailing_comments: vec![],
2341 })));
2342 }
2343 Ok(expr)
2344 }
2345 Expression::GenerateSeries(gs) => {
2346 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2348 this: Expression::GenerateSeries(gs),
2349 expressions: Vec::new(),
2350 with_ordinality: false,
2351 alias: None,
2352 offset_alias: None,
2353 }));
2354 Ok(unnest)
2355 }
2356 other => Ok(other),
2357 }
2358}
2359
2360pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
2368 match expr {
2369 Expression::Delete(mut delete) => {
2370 if let Some(ref mut where_clause) = delete.where_clause {
2372 where_clause.this = expand_between_recursive(where_clause.this.clone());
2373 }
2374 Ok(Expression::Delete(delete))
2375 }
2376 other => Ok(other),
2377 }
2378}
2379
2380fn expand_between_recursive(expr: Expression) -> Expression {
2382 match expr {
2383 Expression::Between(between) => {
2386 let this = expand_between_recursive(between.this.clone());
2387 let low = expand_between_recursive(between.low);
2388 let high = expand_between_recursive(between.high);
2389
2390 if between.not {
2391 Expression::Or(Box::new(BinaryOp::new(
2393 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
2394 Expression::Gt(Box::new(BinaryOp::new(this, high))),
2395 )))
2396 } else {
2397 Expression::And(Box::new(BinaryOp::new(
2399 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
2400 Expression::Lte(Box::new(BinaryOp::new(this, high))),
2401 )))
2402 }
2403 }
2404
2405 Expression::And(mut op) => {
2407 op.left = expand_between_recursive(op.left);
2408 op.right = expand_between_recursive(op.right);
2409 Expression::And(op)
2410 }
2411 Expression::Or(mut op) => {
2412 op.left = expand_between_recursive(op.left);
2413 op.right = expand_between_recursive(op.right);
2414 Expression::Or(op)
2415 }
2416 Expression::Not(mut op) => {
2417 op.this = expand_between_recursive(op.this);
2418 Expression::Not(op)
2419 }
2420
2421 Expression::Paren(mut paren) => {
2423 paren.this = expand_between_recursive(paren.this);
2424 Expression::Paren(paren)
2425 }
2426
2427 other => other,
2429 }
2430}
2431
2432pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
2441 match expr {
2442 Expression::Select(mut select) => {
2443 if let Some(ref mut with) = select.with {
2444 for cte in &mut with.ctes {
2445 if !cte.columns.is_empty() {
2446 let is_star = matches!(&cte.this, Expression::Select(s) if
2448 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
2449
2450 if is_star {
2451 cte.columns.clear();
2453 continue;
2454 }
2455
2456 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
2458
2459 if let Expression::Select(ref mut inner_select) = cte.this {
2461 let new_exprs: Vec<Expression> = inner_select
2462 .expressions
2463 .drain(..)
2464 .zip(column_names.into_iter().chain(std::iter::repeat_with(|| Identifier::new(""))))
2465 .map(|(expr, col_name)| {
2466 if col_name.name.is_empty() {
2467 return expr;
2468 }
2469 match expr {
2471 Expression::Alias(mut a) => {
2472 a.alias = col_name;
2473 Expression::Alias(a)
2474 }
2475 other => {
2476 Expression::Alias(Box::new(crate::expressions::Alias {
2477 this: other,
2478 alias: col_name,
2479 column_aliases: Vec::new(),
2480 pre_alias_comments: Vec::new(),
2481 trailing_comments: Vec::new(),
2482 }))
2483 }
2484 }
2485 })
2486 .collect();
2487 inner_select.expressions = new_exprs;
2488 }
2489 }
2490 }
2491 }
2492 Ok(Expression::Select(select))
2493 }
2494 other => Ok(other),
2495 }
2496}
2497
2498pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
2502 match expr {
2503 Expression::Select(mut select) => {
2504 if let Some(ref mut from) = select.from {
2505 for from_item in from.expressions.iter_mut() {
2506 simplify_paren_values_in_from(from_item);
2507 }
2508 }
2509 Ok(Expression::Select(select))
2510 }
2511 other => Ok(other),
2512 }
2513}
2514
2515fn simplify_paren_values_in_from(expr: &mut Expression) {
2516 let replacement = match expr {
2518 Expression::Subquery(ref subquery) => {
2520 if let Expression::Paren(ref paren) = subquery.this {
2521 if matches!(&paren.this, Expression::Values(_)) {
2522 let mut new_sub = subquery.as_ref().clone();
2523 new_sub.this = paren.this.clone();
2524 Some(Expression::Subquery(Box::new(new_sub)))
2525 } else {
2526 None
2527 }
2528 } else {
2529 None
2530 }
2531 }
2532 Expression::Paren(ref outer_paren) => {
2535 if let Expression::Subquery(ref subquery) = outer_paren.this {
2536 if matches!(&subquery.this, Expression::Values(_)) {
2538 Some(outer_paren.this.clone())
2539 }
2540 else if let Expression::Paren(ref paren) = subquery.this {
2542 if matches!(&paren.this, Expression::Values(_)) {
2543 let mut new_sub = subquery.as_ref().clone();
2544 new_sub.this = paren.this.clone();
2545 Some(Expression::Subquery(Box::new(new_sub)))
2546 } else {
2547 None
2548 }
2549 } else {
2550 None
2551 }
2552 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
2553 if matches!(&inner_paren.this, Expression::Values(_)) {
2554 Some(outer_paren.this.clone())
2555 } else {
2556 None
2557 }
2558 } else {
2559 None
2560 }
2561 }
2562 _ => None,
2563 };
2564 if let Some(new_expr) = replacement {
2565 *expr = new_expr;
2566 }
2567}
2568
2569pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
2573 match expr {
2574 Expression::Select(mut select) => {
2575 if let Some(ref mut from) = select.from {
2577 let mut counter = 0usize;
2578 for from_item in from.expressions.iter_mut() {
2579 add_auto_alias_to_from_item(from_item, &mut counter);
2580 }
2581 }
2582 Ok(Expression::Select(select))
2583 }
2584 other => Ok(other),
2585 }
2586}
2587
2588fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
2589 use crate::expressions::Identifier;
2590
2591 match expr {
2592 Expression::Alias(ref mut alias) => {
2593 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
2595 alias.alias = Identifier::new(format!("_t{}", counter));
2596 *counter += 1;
2597 }
2598 }
2599 _ => {}
2600 }
2601}
2602
2603pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
2613 use crate::dialects::transform_recursive;
2614 transform_recursive(expr, &propagate_struct_names_in_expr)
2615}
2616
2617fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
2618 use crate::expressions::{Alias, Function, Identifier, ArrayConstructor};
2619
2620 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
2622 if elements.len() <= 1 {
2623 return None;
2624 }
2625 if let Some(Expression::Function(ref first_struct)) = elements.first() {
2627 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
2628 let field_names: Vec<Option<String>> = first_struct.args.iter().map(|arg| {
2630 if let Expression::Alias(a) = arg {
2631 Some(a.alias.name.clone())
2632 } else {
2633 None
2634 }
2635 }).collect();
2636
2637 if field_names.iter().any(|n| n.is_some()) {
2639 let mut new_elements = Vec::with_capacity(elements.len());
2640 new_elements.push(elements[0].clone());
2641
2642 for elem in &elements[1..] {
2643 if let Expression::Function(ref s) = elem {
2644 if s.name.eq_ignore_ascii_case("STRUCT") && s.args.len() == field_names.len() {
2645 let all_unnamed = s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
2647 if all_unnamed {
2648 let new_args: Vec<Expression> = s.args.iter().zip(field_names.iter()).map(|(val, name)| {
2650 if let Some(n) = name {
2651 Expression::Alias(Box::new(Alias::new(
2652 val.clone(),
2653 Identifier::new(n.clone()),
2654 )))
2655 } else {
2656 val.clone()
2657 }
2658 }).collect();
2659 new_elements.push(Expression::Function(Box::new(Function::new(
2660 "STRUCT".to_string(), new_args,
2661 ))));
2662 continue;
2663 }
2664 }
2665 }
2666 new_elements.push(elem.clone());
2667 }
2668
2669 return Some(new_elements);
2670 }
2671 }
2672 }
2673 None
2674 }
2675
2676 if let Expression::Array(ref arr) = expr {
2678 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
2679 return Ok(Expression::Array(Box::new(crate::expressions::Array {
2680 expressions: new_elements,
2681 })));
2682 }
2683 }
2684
2685 if let Expression::ArrayFunc(ref arr) = expr {
2687 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
2688 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
2689 expressions: new_elements,
2690 bracket_notation: arr.bracket_notation,
2691 use_list_keyword: arr.use_list_keyword,
2692 })));
2693 }
2694 }
2695
2696 Ok(expr)
2697}
2698
2699pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
2702 use crate::dialects::transform_recursive;
2703 transform_recursive(expr, &unnest_alias_transform_single_select)
2704}
2705
2706pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
2709 use crate::dialects::transform_recursive;
2710 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
2711}
2712
2713fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
2714 if let Expression::Select(mut select) = expr {
2715 if let Some(ref mut from) = select.from {
2716 if from.expressions.len() > 1 {
2717 let mut new_from_exprs = Vec::new();
2718 let mut new_cross_joins = Vec::new();
2719
2720 for (idx, from_item) in from.expressions.drain(..).enumerate() {
2721 if idx == 0 {
2722 new_from_exprs.push(from_item);
2723 } else {
2724 let is_unnest = match &from_item {
2725 Expression::Unnest(_) => true,
2726 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
2727 _ => false,
2728 };
2729
2730 if is_unnest {
2731 new_cross_joins.push(crate::expressions::Join {
2732 this: from_item,
2733 on: None,
2734 using: Vec::new(),
2735 kind: JoinKind::Cross,
2736 use_inner_keyword: false,
2737 use_outer_keyword: false,
2738 deferred_condition: false,
2739 join_hint: None,
2740 match_condition: None,
2741 pivots: Vec::new(),
2742 });
2743 } else {
2744 new_from_exprs.push(from_item);
2745 }
2746 }
2747 }
2748
2749 from.expressions = new_from_exprs;
2750 new_cross_joins.append(&mut select.joins);
2751 select.joins = new_cross_joins;
2752 }
2753 }
2754
2755 Ok(Expression::Select(select))
2756 } else {
2757 Ok(expr)
2758 }
2759}
2760
2761pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
2765 use crate::dialects::transform_recursive;
2766 transform_recursive(expr, &wrap_unnest_join_aliases_single)
2767}
2768
2769fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
2770 if let Expression::Select(mut select) = expr {
2771 for join in &mut select.joins {
2773 wrap_unnest_alias_in_join_item(&mut join.this);
2774 }
2775 Ok(Expression::Select(select))
2776 } else {
2777 Ok(expr)
2778 }
2779}
2780
2781fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
2783 use crate::expressions::Identifier;
2784 if let Expression::Alias(alias) = expr {
2785 let is_unnest = match &alias.this {
2787 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
2788 _ => false,
2789 };
2790
2791 if is_unnest && alias.column_aliases.is_empty() {
2792 let original_alias_name = alias.alias.name.clone();
2794 alias.alias = Identifier {
2795 name: "_u".to_string(),
2796 quoted: false,
2797 trailing_comments: Vec::new(),
2798 };
2799 alias.column_aliases = vec![Identifier {
2800 name: original_alias_name,
2801 quoted: false,
2802 trailing_comments: Vec::new(),
2803 }];
2804 }
2805 }
2806}
2807
2808fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
2809 if let Expression::Select(mut select) = expr {
2810 let mut counter = 0usize;
2811
2812 if let Some(ref mut from) = select.from {
2814 for from_item in from.expressions.iter_mut() {
2816 convert_unnest_alias_in_from(from_item, &mut counter);
2817 }
2818
2819 if from.expressions.len() > 1 {
2821 let mut new_from_exprs = Vec::new();
2822 let mut new_cross_joins = Vec::new();
2823
2824 for (idx, from_item) in from.expressions.drain(..).enumerate() {
2825 if idx == 0 {
2826 new_from_exprs.push(from_item);
2828 } else {
2829 let is_unnest = match &from_item {
2831 Expression::Unnest(_) => true,
2832 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
2833 _ => false,
2834 };
2835
2836 if is_unnest {
2837 new_cross_joins.push(crate::expressions::Join {
2839 this: from_item,
2840 on: None,
2841 using: Vec::new(),
2842 kind: JoinKind::Cross,
2843 use_inner_keyword: false,
2844 use_outer_keyword: false,
2845 deferred_condition: false,
2846 join_hint: None,
2847 match_condition: None,
2848 pivots: Vec::new(),
2849 });
2850 } else {
2851 new_from_exprs.push(from_item);
2853 }
2854 }
2855 }
2856
2857 from.expressions = new_from_exprs;
2858 new_cross_joins.append(&mut select.joins);
2860 select.joins = new_cross_joins;
2861 }
2862 }
2863
2864 for join in select.joins.iter_mut() {
2866 convert_unnest_alias_in_from(&mut join.this, &mut counter);
2867 }
2868
2869 Ok(Expression::Select(select))
2870 } else {
2871 Ok(expr)
2872 }
2873}
2874
2875fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
2876 use crate::expressions::Identifier;
2877
2878 if let Expression::Alias(ref mut alias) = expr {
2879 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
2881 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
2882
2883 if is_unnest && alias.column_aliases.is_empty() {
2884 let col_alias = alias.alias.clone();
2886 alias.column_aliases = vec![col_alias];
2887 alias.alias = Identifier::new(format!("_t{}", counter));
2888 *counter += 1;
2889 }
2890 }
2891}
2892
2893pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
2900 use crate::expressions::{Alias, Function};
2901
2902 match expr {
2903 Expression::Select(mut select) => {
2904 let mut new_expressions = Vec::new();
2906 let mut changed = false;
2907
2908 for sel_expr in select.expressions.drain(..) {
2909 if let Expression::Alias(ref alias_box) = sel_expr {
2911 if let Expression::Function(ref func) = alias_box.this {
2912 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
2913 let arg = func.args[0].clone();
2914 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
2916 (alias_box.column_aliases[0].name.clone(), alias_box.column_aliases[1].name.clone())
2917 } else if !alias_box.alias.is_empty() {
2918 ("pos".to_string(), alias_box.alias.name.clone())
2920 } else {
2921 ("pos".to_string(), "col".to_string())
2922 };
2923
2924 let gen_subscripts = Expression::Function(Box::new(Function::new(
2926 "GENERATE_SUBSCRIPTS".to_string(),
2927 vec![arg.clone(), Expression::Literal(Literal::Number("1".to_string()))],
2928 )));
2929 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
2930 gen_subscripts,
2931 Expression::Literal(Literal::Number("1".to_string())),
2932 )));
2933 let pos_alias = Expression::Alias(Box::new(Alias {
2934 this: sub_one,
2935 alias: Identifier::new(pos_name),
2936 column_aliases: Vec::new(),
2937 pre_alias_comments: Vec::new(),
2938 trailing_comments: Vec::new(),
2939 }));
2940
2941 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2943 this: arg,
2944 expressions: Vec::new(),
2945 with_ordinality: false,
2946 alias: None,
2947 offset_alias: None,
2948 }));
2949 let col_alias = Expression::Alias(Box::new(Alias {
2950 this: unnest,
2951 alias: Identifier::new(col_name),
2952 column_aliases: Vec::new(),
2953 pre_alias_comments: Vec::new(),
2954 trailing_comments: Vec::new(),
2955 }));
2956
2957 new_expressions.push(pos_alias);
2958 new_expressions.push(col_alias);
2959 changed = true;
2960 continue;
2961 }
2962 }
2963 }
2964
2965 if let Expression::Function(ref func) = sel_expr {
2967 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
2968 let arg = func.args[0].clone();
2969 let pos_name = "pos";
2970 let col_name = "col";
2971
2972 let gen_subscripts = Expression::Function(Box::new(Function::new(
2974 "GENERATE_SUBSCRIPTS".to_string(),
2975 vec![arg.clone(), Expression::Literal(Literal::Number("1".to_string()))],
2976 )));
2977 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
2978 gen_subscripts,
2979 Expression::Literal(Literal::Number("1".to_string())),
2980 )));
2981 let pos_alias = Expression::Alias(Box::new(Alias {
2982 this: sub_one,
2983 alias: Identifier::new(pos_name),
2984 column_aliases: Vec::new(),
2985 pre_alias_comments: Vec::new(),
2986 trailing_comments: Vec::new(),
2987 }));
2988
2989 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2991 this: arg,
2992 expressions: Vec::new(),
2993 with_ordinality: false,
2994 alias: None,
2995 offset_alias: None,
2996 }));
2997 let col_alias = Expression::Alias(Box::new(Alias {
2998 this: unnest,
2999 alias: Identifier::new(col_name),
3000 column_aliases: Vec::new(),
3001 pre_alias_comments: Vec::new(),
3002 trailing_comments: Vec::new(),
3003 }));
3004
3005 new_expressions.push(pos_alias);
3006 new_expressions.push(col_alias);
3007 changed = true;
3008 continue;
3009 }
3010 }
3011
3012 new_expressions.push(sel_expr);
3014 }
3015
3016 if changed {
3017 select.expressions = new_expressions;
3018 } else {
3019 select.expressions = new_expressions;
3020 }
3021
3022 if let Some(ref mut from) = select.from {
3025 expand_posexplode_in_from_duckdb(from)?;
3026 }
3027
3028 Ok(Expression::Select(select))
3029 }
3030 other => Ok(other),
3031 }
3032}
3033
3034fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
3036 use crate::expressions::{Alias, Function};
3037
3038 let mut new_expressions = Vec::new();
3039 let mut _changed = false;
3040
3041 for table_expr in from.expressions.drain(..) {
3042 if let Expression::Alias(ref alias_box) = table_expr {
3044 if let Expression::Function(ref func) = alias_box.this {
3045 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3046 let arg = func.args[0].clone();
3047 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
3048 (alias_box.column_aliases[0].name.clone(), alias_box.column_aliases[1].name.clone())
3049 } else {
3050 ("pos".to_string(), "col".to_string())
3051 };
3052
3053 let gen_subscripts = Expression::Function(Box::new(Function::new(
3055 "GENERATE_SUBSCRIPTS".to_string(),
3056 vec![arg.clone(), Expression::Literal(Literal::Number("1".to_string()))],
3057 )));
3058 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3059 gen_subscripts,
3060 Expression::Literal(Literal::Number("1".to_string())),
3061 )));
3062 let pos_alias = Expression::Alias(Box::new(Alias {
3063 this: sub_one,
3064 alias: Identifier::new(&pos_name),
3065 column_aliases: Vec::new(),
3066 pre_alias_comments: Vec::new(),
3067 trailing_comments: Vec::new(),
3068 }));
3069 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3070 this: arg,
3071 expressions: Vec::new(),
3072 with_ordinality: false,
3073 alias: None,
3074 offset_alias: None,
3075 }));
3076 let col_alias = Expression::Alias(Box::new(Alias {
3077 this: unnest,
3078 alias: Identifier::new(&col_name),
3079 column_aliases: Vec::new(),
3080 pre_alias_comments: Vec::new(),
3081 trailing_comments: Vec::new(),
3082 }));
3083
3084 let mut inner_select = Select::new();
3085 inner_select.expressions = vec![pos_alias, col_alias];
3086
3087 let subquery = Expression::Subquery(Box::new(Subquery {
3088 this: Expression::Select(Box::new(inner_select)),
3089 alias: None,
3090 column_aliases: Vec::new(),
3091 order_by: None,
3092 limit: None,
3093 offset: None,
3094 distribute_by: None,
3095 sort_by: None,
3096 cluster_by: None,
3097 lateral: false,
3098 modifiers_inside: false,
3099 trailing_comments: Vec::new(),
3100 }));
3101 new_expressions.push(subquery);
3102 _changed = true;
3103 continue;
3104 }
3105 }
3106 }
3107
3108 if let Expression::Function(ref func) = table_expr {
3110 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3111 let arg = func.args[0].clone();
3112
3113 let gen_subscripts = Expression::Function(Box::new(Function::new(
3115 "GENERATE_SUBSCRIPTS".to_string(),
3116 vec![arg.clone(), Expression::Literal(Literal::Number("1".to_string()))],
3117 )));
3118 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3119 gen_subscripts,
3120 Expression::Literal(Literal::Number("1".to_string())),
3121 )));
3122 let pos_alias = Expression::Alias(Box::new(Alias {
3123 this: sub_one,
3124 alias: Identifier::new("pos"),
3125 column_aliases: Vec::new(),
3126 pre_alias_comments: Vec::new(),
3127 trailing_comments: Vec::new(),
3128 }));
3129 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3130 this: arg,
3131 expressions: Vec::new(),
3132 with_ordinality: false,
3133 alias: None,
3134 offset_alias: None,
3135 }));
3136 let col_alias = Expression::Alias(Box::new(Alias {
3137 this: unnest,
3138 alias: Identifier::new("col"),
3139 column_aliases: Vec::new(),
3140 pre_alias_comments: Vec::new(),
3141 trailing_comments: Vec::new(),
3142 }));
3143
3144 let mut inner_select = Select::new();
3145 inner_select.expressions = vec![pos_alias, col_alias];
3146
3147 let subquery = Expression::Subquery(Box::new(Subquery {
3148 this: Expression::Select(Box::new(inner_select)),
3149 alias: None,
3150 column_aliases: Vec::new(),
3151 order_by: None,
3152 limit: None,
3153 offset: None,
3154 distribute_by: None,
3155 sort_by: None,
3156 cluster_by: None,
3157 lateral: false,
3158 modifiers_inside: false,
3159 trailing_comments: Vec::new(),
3160 }));
3161 new_expressions.push(subquery);
3162 _changed = true;
3163 continue;
3164 }
3165 }
3166
3167 new_expressions.push(table_expr);
3168 }
3169
3170 from.expressions = new_expressions;
3171 Ok(())
3172}
3173
3174pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
3189 match expr {
3190 Expression::Select(select) => {
3191 explode_projection_to_unnest_impl(*select, target)
3192 }
3193 other => Ok(other),
3194 }
3195}
3196
3197pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
3207 match expr {
3208 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
3209 other => Ok(other),
3210 }
3211}
3212
3213fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
3214 let mut flattened_inputs: Vec<Expression> = Vec::new();
3215 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
3216
3217 for sel_expr in select.expressions.into_iter() {
3218 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
3219
3220 let rewritten = transform_recursive(sel_expr, &|e| {
3221 if let Expression::Lateral(lat) = e {
3222 if let Some(input_expr) = extract_flatten_input(&lat) {
3223 if found_input.borrow().is_none() {
3224 *found_input.borrow_mut() = Some(input_expr);
3225 }
3226 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
3227 }
3228 return Ok(Expression::Lateral(lat));
3229 }
3230 Ok(e)
3231 })?;
3232
3233 if let Some(input) = found_input.into_inner() {
3234 flattened_inputs.push(input);
3235 }
3236 new_selects.push(rewritten);
3237 }
3238
3239 if flattened_inputs.is_empty() {
3240 select.expressions = new_selects;
3241 return Ok(Expression::Select(Box::new(select)));
3242 }
3243
3244 select.expressions = new_selects;
3245
3246 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
3247 let is_first = idx == 0;
3249 let series_alias = if is_first { "pos".to_string() } else { format!("pos_{}", idx + 1) };
3250 let series_source_alias = if is_first { "_u".to_string() } else { format!("_u_{}", idx * 2 + 1) };
3251 let unnest_source_alias = if is_first { "_u_2".to_string() } else { format!("_u_{}", idx * 2 + 2) };
3252 let pos2_alias = if is_first { "pos_2".to_string() } else { format!("{}_2", series_alias) };
3253 let entity_alias = if is_first { "entity".to_string() } else { format!("entity_{}", idx + 1) };
3254
3255 let array_size_call = Expression::Function(Box::new(Function::new(
3256 "ARRAY_SIZE".to_string(),
3257 vec![Expression::NamedArgument(Box::new(NamedArgument {
3258 name: Identifier::new("INPUT"),
3259 value: input_expr.clone(),
3260 separator: NamedArgSeparator::DArrow,
3261 }))],
3262 )));
3263
3264 let greatest = Expression::Function(Box::new(Function::new(
3265 "GREATEST".to_string(),
3266 vec![array_size_call.clone()],
3267 )));
3268
3269 let series_end = Expression::Add(Box::new(BinaryOp::new(
3270 Expression::Paren(Box::new(crate::expressions::Paren {
3271 this: Expression::Sub(Box::new(BinaryOp::new(
3272 greatest,
3273 Expression::Literal(Literal::Number("1".to_string())),
3274 ))),
3275 trailing_comments: Vec::new(),
3276 })),
3277 Expression::Literal(Literal::Number("1".to_string())),
3278 )));
3279
3280 let series_range = Expression::Function(Box::new(Function::new(
3281 "ARRAY_GENERATE_RANGE".to_string(),
3282 vec![Expression::Literal(Literal::Number("0".to_string())), series_end],
3283 )));
3284
3285 let series_flatten = Expression::Function(Box::new(Function::new(
3286 "FLATTEN".to_string(),
3287 vec![Expression::NamedArgument(Box::new(NamedArgument {
3288 name: Identifier::new("INPUT"),
3289 value: series_range,
3290 separator: NamedArgSeparator::DArrow,
3291 }))],
3292 )));
3293
3294 let series_table = Expression::Function(Box::new(Function::new(
3295 "TABLE".to_string(),
3296 vec![series_flatten],
3297 )));
3298
3299 let series_alias_expr = Expression::Alias(Box::new(Alias {
3300 this: series_table,
3301 alias: Identifier::new(series_source_alias.clone()),
3302 column_aliases: vec![
3303 Identifier::new("seq"),
3304 Identifier::new("key"),
3305 Identifier::new("path"),
3306 Identifier::new("index"),
3307 Identifier::new(series_alias.clone()),
3308 Identifier::new("this"),
3309 ],
3310 pre_alias_comments: Vec::new(),
3311 trailing_comments: Vec::new(),
3312 }));
3313
3314 select.joins.push(Join {
3315 this: series_alias_expr,
3316 on: None,
3317 using: Vec::new(),
3318 kind: JoinKind::Cross,
3319 use_inner_keyword: false,
3320 use_outer_keyword: false,
3321 deferred_condition: false,
3322 join_hint: None,
3323 match_condition: None,
3324 pivots: Vec::new(),
3325 });
3326
3327 let entity_flatten = Expression::Function(Box::new(Function::new(
3328 "FLATTEN".to_string(),
3329 vec![Expression::NamedArgument(Box::new(NamedArgument {
3330 name: Identifier::new("INPUT"),
3331 value: input_expr.clone(),
3332 separator: NamedArgSeparator::DArrow,
3333 }))],
3334 )));
3335
3336 let entity_table = Expression::Function(Box::new(Function::new(
3337 "TABLE".to_string(),
3338 vec![entity_flatten],
3339 )));
3340
3341 let entity_alias_expr = Expression::Alias(Box::new(Alias {
3342 this: entity_table,
3343 alias: Identifier::new(unnest_source_alias.clone()),
3344 column_aliases: vec![
3345 Identifier::new("seq"),
3346 Identifier::new("key"),
3347 Identifier::new("path"),
3348 Identifier::new(pos2_alias.clone()),
3349 Identifier::new(entity_alias.clone()),
3350 Identifier::new("this"),
3351 ],
3352 pre_alias_comments: Vec::new(),
3353 trailing_comments: Vec::new(),
3354 }));
3355
3356 select.joins.push(Join {
3357 this: entity_alias_expr,
3358 on: None,
3359 using: Vec::new(),
3360 kind: JoinKind::Cross,
3361 use_inner_keyword: false,
3362 use_outer_keyword: false,
3363 deferred_condition: false,
3364 join_hint: None,
3365 match_condition: None,
3366 pivots: Vec::new(),
3367 });
3368
3369 let pos_col = Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
3370 let pos2_col = Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
3371
3372 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
3373 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
3374 this: Expression::Sub(Box::new(BinaryOp::new(
3375 array_size_call,
3376 Expression::Literal(Literal::Number("1".to_string())),
3377 ))),
3378 trailing_comments: Vec::new(),
3379 }));
3380 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
3381 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
3382 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
3383 let or_cond = Expression::Or(Box::new(BinaryOp::new(
3384 eq,
3385 Expression::Paren(Box::new(crate::expressions::Paren {
3386 this: and_cond,
3387 trailing_comments: Vec::new(),
3388 })),
3389 )));
3390
3391 select.where_clause = Some(match select.where_clause.take() {
3392 Some(existing) => Where {
3393 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
3394 },
3395 None => Where { this: or_cond },
3396 });
3397 }
3398
3399 Ok(Expression::Select(Box::new(select)))
3400}
3401
3402fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
3403 let Expression::Function(f) = lat.this.as_ref() else {
3404 return None;
3405 };
3406 if !f.name.eq_ignore_ascii_case("FLATTEN") {
3407 return None;
3408 }
3409
3410 for arg in &f.args {
3411 if let Expression::NamedArgument(na) = arg {
3412 if na.name.name.eq_ignore_ascii_case("INPUT") {
3413 return Some(na.value.clone());
3414 }
3415 }
3416 }
3417 f.args.first().cloned()
3418}
3419
3420fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
3421 let cond = Expression::Eq(Box::new(BinaryOp::new(
3422 Expression::qualified_column("_u", "pos"),
3423 Expression::qualified_column("_u_2", "pos_2"),
3424 )));
3425 let true_expr = Expression::qualified_column("_u_2", "entity");
3426 let iff_expr = Expression::Function(Box::new(Function::new(
3427 "IFF".to_string(),
3428 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
3429 )));
3430
3431 lat.this = Box::new(iff_expr);
3432 if lat.column_aliases.is_empty() {
3433 lat.column_aliases = vec![
3434 "SEQ".to_string(),
3435 "KEY".to_string(),
3436 "PATH".to_string(),
3437 "INDEX".to_string(),
3438 "VALUE".to_string(),
3439 "THIS".to_string(),
3440 ];
3441 }
3442 lat
3443}
3444
3445struct ExplodeInfo {
3447 arg_sql: String,
3449 explode_alias: String,
3451 pos_alias: String,
3453 unnest_source_alias: String,
3455}
3456
3457fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
3458 let is_presto = matches!(target, DialectType::Presto | DialectType::Trino | DialectType::Athena);
3459 let is_bigquery = matches!(target, DialectType::BigQuery);
3460
3461 if !is_presto && !is_bigquery {
3462 return Ok(Expression::Select(Box::new(select)));
3463 }
3464
3465 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
3467 if !has_explode {
3468 return Ok(Expression::Select(Box::new(select)));
3469 }
3470
3471 let mut taken_select_names = std::collections::HashSet::new();
3473 let mut taken_source_names = std::collections::HashSet::new();
3474
3475 for sel in &select.expressions {
3477 if let Some(name) = get_output_name(sel) {
3478 taken_select_names.insert(name);
3479 }
3480 }
3481
3482 for sel in &select.expressions {
3484 let explode_expr = find_explode_in_expr(sel);
3485 if let Some(arg) = explode_expr {
3486 if let Some(name) = get_output_name(&arg) {
3487 taken_select_names.insert(name);
3488 }
3489 }
3490 }
3491
3492 if let Some(ref from) = select.from {
3494 for from_expr in &from.expressions {
3495 collect_source_names(from_expr, &mut taken_source_names);
3496 }
3497 }
3498 for join in &select.joins {
3500 collect_source_names(&join.this, &mut taken_source_names);
3501 }
3502
3503 let series_alias = new_name(&mut taken_select_names, "pos");
3505
3506 let series_source_alias = new_name(&mut taken_source_names, "_u");
3508
3509 let target_dialect = Dialect::get(target);
3511
3512 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
3514 let mut new_projections: Vec<String> = Vec::new();
3515
3516 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
3517 let explode_data = extract_explode_data(sel_expr);
3518
3519 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
3520 let arg_sql = target_dialect.generate(&arg_expr).unwrap_or_else(|_| "NULL".to_string());
3522
3523 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
3524
3525 let explode_alias = if let Some(ref ea) = explicit_alias {
3526 taken_select_names.remove(ea.as_str());
3529 let name = new_name(&mut taken_select_names, ea);
3531 name
3532 } else {
3533 new_name(&mut taken_select_names, "col")
3534 };
3535
3536 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
3537 taken_select_names.remove(pa.as_str());
3539 let name = new_name(&mut taken_select_names, pa);
3540 name
3541 } else {
3542 new_name(&mut taken_select_names, "pos")
3543 };
3544
3545 if is_presto {
3547 let if_col = format!(
3549 "IF({}.{} = {}.{}, {}.{}) AS {}",
3550 series_source_alias, series_alias,
3551 unnest_source_alias, pos_alias,
3552 unnest_source_alias, explode_alias,
3553 explode_alias
3554 );
3555 new_projections.push(if_col);
3556
3557 if is_posexplode {
3559 let if_pos = format!(
3560 "IF({}.{} = {}.{}, {}.{}) AS {}",
3561 series_source_alias, series_alias,
3562 unnest_source_alias, pos_alias,
3563 unnest_source_alias, pos_alias,
3564 pos_alias
3565 );
3566 new_projections.push(if_pos);
3567 }
3568 } else {
3569 let if_col = format!(
3571 "IF({} = {}, {}, NULL) AS {}",
3572 series_alias, pos_alias,
3573 explode_alias, explode_alias
3574 );
3575 new_projections.push(if_col);
3576
3577 if is_posexplode {
3579 let if_pos = format!(
3580 "IF({} = {}, {}, NULL) AS {}",
3581 series_alias, pos_alias,
3582 pos_alias, pos_alias
3583 );
3584 new_projections.push(if_pos);
3585 }
3586 }
3587
3588 explode_infos.push(ExplodeInfo {
3589 arg_sql,
3590 explode_alias,
3591 pos_alias,
3592 unnest_source_alias,
3593 });
3594 } else {
3595 let sel_sql = target_dialect.generate(sel_expr).unwrap_or_else(|_| "*".to_string());
3597 new_projections.push(sel_sql);
3598 }
3599 }
3600
3601 if explode_infos.is_empty() {
3602 return Ok(Expression::Select(Box::new(select)));
3603 }
3604
3605 let mut from_parts: Vec<String> = Vec::new();
3607
3608 if let Some(ref from) = select.from {
3610 for from_expr in &from.expressions {
3611 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
3612 from_parts.push(from_sql);
3613 }
3614 }
3615
3616 let size_exprs: Vec<String> = explode_infos.iter().map(|info| {
3618 if is_presto {
3619 format!("CARDINALITY({})", info.arg_sql)
3620 } else {
3621 format!("ARRAY_LENGTH({})", info.arg_sql)
3622 }
3623 }).collect();
3624
3625 let greatest_arg = if size_exprs.len() == 1 {
3626 size_exprs[0].clone()
3627 } else {
3628 format!("GREATEST({})", size_exprs.join(", "))
3629 };
3630
3631 let series_sql = if is_presto {
3634 if size_exprs.len() == 1 {
3636 format!("UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
3637 greatest_arg, series_source_alias, series_alias)
3638 } else {
3639 format!("UNNEST(SEQUENCE(1, {})) AS {}({})",
3641 greatest_arg, series_source_alias, series_alias)
3642 }
3643 } else {
3644 if size_exprs.len() == 1 {
3646 format!("UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
3647 greatest_arg, series_alias)
3648 } else {
3649 format!("UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
3651 greatest_arg, series_alias)
3652 }
3653 };
3654
3655 let mut cross_joins: Vec<String> = Vec::new();
3659
3660 for info in &explode_infos {
3661 cross_joins.push(format!(
3663 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
3664 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
3665 ));
3666 }
3667
3668 let mut where_conditions: Vec<String> = Vec::new();
3670
3671 for info in &explode_infos {
3672 let size_expr = if is_presto {
3673 format!("CARDINALITY({})", info.arg_sql)
3674 } else {
3675 format!("ARRAY_LENGTH({})", info.arg_sql)
3676 };
3677
3678 let cond = if is_presto {
3679 format!(
3680 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
3681 series_src = series_source_alias,
3682 series_al = series_alias,
3683 unnest_src = info.unnest_source_alias,
3684 pos_al = info.pos_alias,
3685 size = size_expr
3686 )
3687 } else {
3688 format!(
3689 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
3690 series_al = series_alias,
3691 pos_al = info.pos_alias,
3692 size = size_expr
3693 )
3694 };
3695
3696 where_conditions.push(cond);
3697 }
3698
3699 let where_sql = if where_conditions.len() == 1 {
3701 where_conditions[0].clone()
3702 } else {
3703 where_conditions.iter().map(|c| format!("({})", c)).collect::<Vec<_>>().join(" AND ")
3704 };
3705
3706 let select_part = new_projections.join(", ");
3708
3709 let from_and_joins = if from_parts.is_empty() {
3711 format!("FROM {} {}", series_sql, cross_joins.join(" "))
3713 } else {
3714 format!("FROM {} {} {}", from_parts.join(", "),
3715 format!("CROSS JOIN {}", series_sql),
3716 cross_joins.join(" "))
3717 };
3718
3719 let full_sql = format!(
3720 "SELECT {} {} WHERE {}",
3721 select_part, from_and_joins, where_sql
3722 );
3723
3724 let generic_dialect = Dialect::get(DialectType::Generic);
3727 let parsed = generic_dialect.parse(&full_sql);
3728 match parsed {
3729 Ok(mut stmts) if !stmts.is_empty() => {
3730 let mut result = stmts.remove(0);
3731
3732 if is_bigquery {
3736 convert_unnest_presto_to_bigquery(&mut result);
3737 }
3738
3739 Ok(result)
3740 }
3741 _ => {
3742 Ok(Expression::Select(Box::new(select)))
3744 }
3745 }
3746}
3747
3748fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
3752 match expr {
3753 Expression::Select(ref mut select) => {
3754 if let Some(ref mut from) = select.from {
3756 for from_item in from.expressions.iter_mut() {
3757 convert_unnest_presto_to_bigquery(from_item);
3758 }
3759 }
3760 for join in select.joins.iter_mut() {
3762 convert_unnest_presto_to_bigquery(&mut join.this);
3763 }
3764 }
3765 Expression::Alias(ref alias) => {
3766 if let Expression::Unnest(ref unnest) = alias.this {
3768 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
3769 let col_alias = alias.column_aliases[0].clone();
3770 let pos_alias = alias.column_aliases[1].clone();
3771 let mut new_unnest = unnest.as_ref().clone();
3772 new_unnest.alias = Some(col_alias);
3773 new_unnest.offset_alias = Some(pos_alias);
3774 *expr = Expression::Unnest(Box::new(new_unnest));
3776 }
3777 }
3778 }
3779 _ => {}
3780 }
3781}
3782
3783fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
3786 if !names.contains(base) {
3787 names.insert(base.to_string());
3788 return base.to_string();
3789 }
3790 let mut i = 2;
3791 loop {
3792 let candidate = format!("{}_{}", base, i);
3793 if !names.contains(&candidate) {
3794 names.insert(candidate.clone());
3795 return candidate;
3796 }
3797 i += 1;
3798 }
3799}
3800
3801fn expr_contains_explode(expr: &Expression) -> bool {
3803 match expr {
3804 Expression::Explode(_) => true,
3805 Expression::ExplodeOuter(_) => true,
3806 Expression::Function(f) => {
3807 let name = f.name.to_uppercase();
3808 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
3809 }
3810 Expression::Alias(a) => expr_contains_explode(&a.this),
3811 _ => false,
3812 }
3813}
3814
3815fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
3817 match expr {
3818 Expression::Explode(uf) => Some(uf.this.clone()),
3819 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
3820 Expression::Function(f) => {
3821 let name = f.name.to_uppercase();
3822 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
3823 Some(f.args[0].clone())
3824 } else {
3825 None
3826 }
3827 }
3828 Expression::Alias(a) => find_explode_in_expr(&a.this),
3829 _ => None,
3830 }
3831}
3832
3833fn extract_explode_data(expr: &Expression) -> Option<(bool, Expression, Option<String>, Option<String>)> {
3836 match expr {
3837 Expression::Explode(uf) => {
3839 Some((false, uf.this.clone(), None, None))
3840 }
3841 Expression::ExplodeOuter(uf) => {
3842 Some((false, uf.this.clone(), None, None))
3843 }
3844 Expression::Function(f) => {
3846 let name = f.name.to_uppercase();
3847 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
3848 Some((true, f.args[0].clone(), None, None))
3849 } else {
3850 None
3851 }
3852 }
3853 Expression::Alias(a) => {
3855 match &a.this {
3856 Expression::Explode(uf) => {
3857 let alias = if !a.alias.is_empty() {
3858 Some(a.alias.name.clone())
3859 } else {
3860 None
3861 };
3862 Some((false, uf.this.clone(), alias, None))
3863 }
3864 Expression::ExplodeOuter(uf) => {
3865 let alias = if !a.alias.is_empty() {
3866 Some(a.alias.name.clone())
3867 } else {
3868 None
3869 };
3870 Some((false, uf.this.clone(), alias, None))
3871 }
3872 Expression::Function(f) => {
3873 let name = f.name.to_uppercase();
3874 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
3875 if a.column_aliases.len() == 2 {
3877 let pos_alias = a.column_aliases[0].name.clone();
3878 let col_alias = a.column_aliases[1].name.clone();
3879 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
3880 } else if !a.alias.is_empty() {
3881 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
3883 } else {
3884 Some((true, f.args[0].clone(), None, None))
3885 }
3886 } else {
3887 None
3888 }
3889 }
3890 _ => None,
3891 }
3892 }
3893 _ => None,
3894 }
3895}
3896
3897fn get_output_name(expr: &Expression) -> Option<String> {
3899 match expr {
3900 Expression::Alias(a) => {
3901 if !a.alias.is_empty() {
3902 Some(a.alias.name.clone())
3903 } else {
3904 None
3905 }
3906 }
3907 Expression::Column(c) => Some(c.name.name.clone()),
3908 Expression::Identifier(id) => Some(id.name.clone()),
3909 _ => None,
3910 }
3911}
3912
3913fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
3915 match expr {
3916 Expression::Alias(a) => {
3917 if !a.alias.is_empty() {
3918 names.insert(a.alias.name.clone());
3919 }
3920 }
3921 Expression::Subquery(s) => {
3922 if let Some(ref alias) = s.alias {
3923 names.insert(alias.name.clone());
3924 }
3925 }
3926 Expression::Table(t) => {
3927 if let Some(ref alias) = t.alias {
3928 names.insert(alias.name.clone());
3929 } else {
3930 names.insert(t.name.name.clone());
3931 }
3932 }
3933 Expression::Column(c) => {
3934 names.insert(c.name.name.clone());
3935 }
3936 Expression::Identifier(id) => {
3937 names.insert(id.name.clone());
3938 }
3939 _ => {}
3940 }
3941}
3942
3943pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
3946 use crate::dialects::transform_recursive;
3947 transform_recursive(expr, &strip_unnest_column_refs_single)
3948}
3949
3950fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
3951 if let Expression::Select(mut select) = expr {
3952 for join in select.joins.iter_mut() {
3954 strip_unnest_from_expr(&mut join.this);
3955 }
3956 if let Some(ref mut from) = select.from {
3958 for from_item in from.expressions.iter_mut() {
3959 strip_unnest_from_expr(from_item);
3960 }
3961 }
3962 Ok(Expression::Select(select))
3963 } else {
3964 Ok(expr)
3965 }
3966}
3967
3968fn strip_unnest_from_expr(expr: &mut Expression) {
3971 if let Expression::Alias(ref mut alias) = expr {
3972 if let Expression::Unnest(ref unnest) = alias.this {
3973 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
3974 if is_column_ref {
3975 let inner = unnest.this.clone();
3977 alias.this = inner;
3978 }
3979 }
3980 }
3981}
3982
3983pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
3986 use crate::dialects::transform_recursive;
3987 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
3988}
3989
3990fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
3991 if let Expression::Select(mut select) = expr {
3992 if let Some(ref mut from) = select.from {
3994 for from_item in from.expressions.iter_mut() {
3995 try_wrap_unnest_in_subquery(from_item);
3996 }
3997 }
3998
3999 for join in select.joins.iter_mut() {
4001 try_wrap_unnest_in_subquery(&mut join.this);
4002 }
4003
4004 Ok(Expression::Select(select))
4005 } else {
4006 Ok(expr)
4007 }
4008}
4009
4010fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
4012 match expr {
4013 Expression::Array(arr) => {
4015 arr.expressions.iter().any(|e| matches!(e, Expression::Struct(_)))
4016 }
4017 Expression::ArrayFunc(arr) => {
4018 arr.expressions.iter().any(|e| matches!(e, Expression::Struct(_)))
4019 }
4020 Expression::Cast(c) => {
4022 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
4023 }
4024 _ => false,
4025 }
4026}
4027
4028fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
4031 if let Expression::Alias(ref alias) = expr {
4033 if let Expression::Unnest(ref unnest) = alias.this {
4034 if is_struct_array_unnest_arg(&unnest.this) {
4035 let unnest_clone = (**unnest).clone();
4036 let alias_name = alias.alias.clone();
4037 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
4038 *expr = new_expr;
4039 return;
4040 }
4041 }
4042 }
4043
4044 if let Expression::Unnest(ref unnest) = expr {
4046 if is_struct_array_unnest_arg(&unnest.this) {
4047 let unnest_clone = (**unnest).clone();
4048 let new_expr = make_unnest_subquery(unnest_clone, None);
4049 *expr = new_expr;
4050 }
4051 }
4052}
4053
4054fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
4056 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
4058 name: Identifier::new("max_depth".to_string()),
4059 value: Expression::Literal(Literal::Number("2".to_string())),
4060 separator: NamedArgSeparator::DArrow,
4061 }));
4062
4063 let mut unnest_args = vec![unnest.this];
4064 unnest_args.extend(unnest.expressions);
4065 unnest_args.push(max_depth_arg);
4066
4067 let unnest_func = Expression::Function(Box::new(Function::new(
4068 "UNNEST".to_string(),
4069 unnest_args,
4070 )));
4071
4072 let mut inner_select = Select::new();
4074 inner_select.expressions = vec![unnest_func];
4075 let inner_select = Expression::Select(Box::new(inner_select));
4076
4077 let subquery = Subquery {
4079 this: inner_select,
4080 alias,
4081 column_aliases: Vec::new(),
4082 order_by: None,
4083 limit: None,
4084 offset: None,
4085 distribute_by: None,
4086 sort_by: None,
4087 cluster_by: None,
4088 lateral: false,
4089 modifiers_inside: false,
4090 trailing_comments: Vec::new(),
4091 };
4092
4093 Expression::Subquery(Box::new(subquery))
4094}
4095
4096#[cfg(test)]
4097mod tests {
4098 use super::*;
4099 use crate::dialects::{Dialect, DialectType};
4100 use crate::expressions::Column;
4101
4102 fn parse(sql: &str) -> Expression {
4103 let dialect = Dialect::get(DialectType::Generic);
4104 let ast = dialect.parse(sql).unwrap();
4105 ast.into_iter().next().unwrap()
4106 }
4107
4108 fn gen(expr: &Expression) -> String {
4109 let dialect = Dialect::get(DialectType::Generic);
4110 dialect.generate(expr).unwrap()
4111 }
4112
4113 #[test]
4114 fn test_preprocess() {
4115 let expr = Expression::Boolean(BooleanLiteral { value: true });
4116 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
4117 assert!(matches!(result, Expression::Literal(Literal::Number(_))));
4118 }
4119
4120 #[test]
4121 fn test_preprocess_chain() {
4122 let expr = Expression::Boolean(BooleanLiteral { value: true });
4124 let transforms: Vec<fn(Expression) -> Result<Expression>> =
4126 vec![replace_bool_with_int, replace_int_with_bool];
4127 let result = preprocess(expr, &transforms).unwrap();
4128 if let Expression::Boolean(b) = result {
4131 assert!(b.value);
4132 } else {
4133 panic!("Expected boolean literal");
4134 }
4135 }
4136
4137 #[test]
4138 fn test_unnest_to_explode() {
4139 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4140 this: Expression::Column(Column {
4141 name: Identifier::new("arr".to_string()),
4142 table: None,
4143 join_mark: false,
4144 trailing_comments: vec![],
4145 }),
4146 expressions: Vec::new(),
4147 with_ordinality: false,
4148 alias: None,
4149 offset_alias: None,
4150 }));
4151
4152 let result = unnest_to_explode(unnest).unwrap();
4153 assert!(matches!(result, Expression::Explode(_)));
4154 }
4155
4156 #[test]
4157 fn test_explode_to_unnest() {
4158 let explode = Expression::Explode(Box::new(UnaryFunc {
4159 this: Expression::Column(Column {
4160 name: Identifier::new("arr".to_string()),
4161 table: None,
4162 join_mark: false,
4163 trailing_comments: vec![],
4164 }),
4165 original_name: None,
4166 }));
4167
4168 let result = explode_to_unnest(explode).unwrap();
4169 assert!(matches!(result, Expression::Unnest(_)));
4170 }
4171
4172 #[test]
4173 fn test_replace_bool_with_int() {
4174 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
4175 let result = replace_bool_with_int(true_expr).unwrap();
4176 if let Expression::Literal(Literal::Number(n)) = result {
4177 assert_eq!(n, "1");
4178 } else {
4179 panic!("Expected number literal");
4180 }
4181
4182 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
4183 let result = replace_bool_with_int(false_expr).unwrap();
4184 if let Expression::Literal(Literal::Number(n)) = result {
4185 assert_eq!(n, "0");
4186 } else {
4187 panic!("Expected number literal");
4188 }
4189 }
4190
4191 #[test]
4192 fn test_replace_int_with_bool() {
4193 let one_expr = Expression::Literal(Literal::Number("1".to_string()));
4194 let result = replace_int_with_bool(one_expr).unwrap();
4195 if let Expression::Boolean(b) = result {
4196 assert!(b.value);
4197 } else {
4198 panic!("Expected boolean true");
4199 }
4200
4201 let zero_expr = Expression::Literal(Literal::Number("0".to_string()));
4202 let result = replace_int_with_bool(zero_expr).unwrap();
4203 if let Expression::Boolean(b) = result {
4204 assert!(!b.value);
4205 } else {
4206 panic!("Expected boolean false");
4207 }
4208
4209 let two_expr = Expression::Literal(Literal::Number("2".to_string()));
4211 let result = replace_int_with_bool(two_expr).unwrap();
4212 assert!(matches!(result, Expression::Literal(Literal::Number(_))));
4213 }
4214
4215 #[test]
4216 fn test_strip_data_type_params() {
4217 let decimal = DataType::Decimal {
4219 precision: Some(10),
4220 scale: Some(2),
4221 };
4222 let stripped = strip_data_type_params(decimal);
4223 assert_eq!(
4224 stripped,
4225 DataType::Decimal {
4226 precision: None,
4227 scale: None
4228 }
4229 );
4230
4231 let varchar = DataType::VarChar { length: Some(255), parenthesized_length: false };
4233 let stripped = strip_data_type_params(varchar);
4234 assert_eq!(stripped, DataType::VarChar { length: None, parenthesized_length: false });
4235
4236 let char_type = DataType::Char { length: Some(10) };
4238 let stripped = strip_data_type_params(char_type);
4239 assert_eq!(stripped, DataType::Char { length: None });
4240
4241 let timestamp = DataType::Timestamp {
4243 precision: Some(6),
4244 timezone: true,
4245 };
4246 let stripped = strip_data_type_params(timestamp);
4247 assert_eq!(
4248 stripped,
4249 DataType::Timestamp {
4250 precision: None,
4251 timezone: true
4252 }
4253 );
4254
4255 let array = DataType::Array {
4257 element_type: Box::new(DataType::VarChar { length: Some(100), parenthesized_length: false }),
4258 dimension: None,
4259 };
4260 let stripped = strip_data_type_params(array);
4261 assert_eq!(
4262 stripped,
4263 DataType::Array {
4264 element_type: Box::new(DataType::VarChar { length: None, parenthesized_length: false }),
4265 dimension: None,
4266 }
4267 );
4268
4269 let text = DataType::Text;
4271 let stripped = strip_data_type_params(text);
4272 assert_eq!(stripped, DataType::Text);
4273 }
4274
4275 #[test]
4276 fn test_remove_precision_parameterized_types_cast() {
4277 let cast_expr = Expression::Cast(Box::new(Cast {
4279 this: Expression::Literal(Literal::Number("1".to_string())),
4280 to: DataType::Decimal {
4281 precision: Some(10),
4282 scale: Some(2),
4283 },
4284 trailing_comments: vec![],
4285 double_colon_syntax: false,
4286 format: None,
4287 default: None,
4288 }));
4289
4290 let result = remove_precision_parameterized_types(cast_expr).unwrap();
4291 if let Expression::Cast(cast) = result {
4292 assert_eq!(
4293 cast.to,
4294 DataType::Decimal {
4295 precision: None,
4296 scale: None
4297 }
4298 );
4299 } else {
4300 panic!("Expected Cast expression");
4301 }
4302 }
4303
4304 #[test]
4305 fn test_remove_precision_parameterized_types_varchar() {
4306 let cast_expr = Expression::Cast(Box::new(Cast {
4308 this: Expression::Literal(Literal::String("hello".to_string())),
4309 to: DataType::VarChar { length: Some(10), parenthesized_length: false },
4310 trailing_comments: vec![],
4311 double_colon_syntax: false,
4312 format: None,
4313 default: None,
4314 }));
4315
4316 let result = remove_precision_parameterized_types(cast_expr).unwrap();
4317 if let Expression::Cast(cast) = result {
4318 assert_eq!(cast.to, DataType::VarChar { length: None, parenthesized_length: false });
4319 } else {
4320 panic!("Expected Cast expression");
4321 }
4322 }
4323
4324 #[test]
4325 fn test_remove_precision_direct_cast() {
4326 let cast = Expression::Cast(Box::new(Cast {
4330 this: Expression::Literal(Literal::Number("1".to_string())),
4331 to: DataType::Decimal {
4332 precision: Some(10),
4333 scale: Some(2),
4334 },
4335 trailing_comments: vec![],
4336 double_colon_syntax: false,
4337 format: None,
4338 default: None,
4339 }));
4340
4341 let transformed = remove_precision_parameterized_types(cast).unwrap();
4342 let generated = gen(&transformed);
4343
4344 assert!(generated.contains("DECIMAL"));
4346 assert!(!generated.contains("(10"));
4347 }
4348
4349 #[test]
4350 fn test_epoch_cast_to_ts() {
4351 let cast_expr = Expression::Cast(Box::new(Cast {
4353 this: Expression::Literal(Literal::String("epoch".to_string())),
4354 to: DataType::Timestamp {
4355 precision: None,
4356 timezone: false,
4357 },
4358 trailing_comments: vec![],
4359 double_colon_syntax: false,
4360 format: None,
4361 default: None,
4362 }));
4363
4364 let result = epoch_cast_to_ts(cast_expr).unwrap();
4365 if let Expression::Cast(cast) = result {
4366 if let Expression::Literal(Literal::String(s)) = cast.this {
4367 assert_eq!(s, "1970-01-01 00:00:00");
4368 } else {
4369 panic!("Expected string literal");
4370 }
4371 } else {
4372 panic!("Expected Cast expression");
4373 }
4374 }
4375
4376 #[test]
4377 fn test_epoch_cast_to_ts_preserves_non_epoch() {
4378 let cast_expr = Expression::Cast(Box::new(Cast {
4380 this: Expression::Literal(Literal::String("2024-01-15".to_string())),
4381 to: DataType::Timestamp {
4382 precision: None,
4383 timezone: false,
4384 },
4385 trailing_comments: vec![],
4386 double_colon_syntax: false,
4387 format: None,
4388 default: None,
4389 }));
4390
4391 let result = epoch_cast_to_ts(cast_expr).unwrap();
4392 if let Expression::Cast(cast) = result {
4393 if let Expression::Literal(Literal::String(s)) = cast.this {
4394 assert_eq!(s, "2024-01-15");
4395 } else {
4396 panic!("Expected string literal");
4397 }
4398 } else {
4399 panic!("Expected Cast expression");
4400 }
4401 }
4402
4403 #[test]
4404 fn test_unqualify_columns() {
4405 let col = Expression::Column(Column {
4407 name: Identifier::new("id".to_string()),
4408 table: Some(Identifier::new("users".to_string())),
4409 join_mark: false,
4410 trailing_comments: vec![],
4411 });
4412
4413 let result = unqualify_columns(col).unwrap();
4414 if let Expression::Column(c) = result {
4415 assert!(c.table.is_none());
4416 assert_eq!(c.name.name, "id");
4417 } else {
4418 panic!("Expected Column expression");
4419 }
4420 }
4421
4422 #[test]
4423 fn test_is_temporal_type() {
4424 assert!(is_temporal_type(&DataType::Date));
4425 assert!(is_temporal_type(&DataType::Timestamp {
4426 precision: None,
4427 timezone: false
4428 }));
4429 assert!(is_temporal_type(&DataType::Time { precision: None, timezone: false }));
4430 assert!(!is_temporal_type(&DataType::Int { length: None, integer_spelling: false }));
4431 assert!(!is_temporal_type(&DataType::VarChar { length: None, parenthesized_length: false }));
4432 }
4433
4434 #[test]
4435 fn test_eliminate_semi_join_basic() {
4436 use crate::expressions::{Join, TableRef};
4437
4438 let select = Expression::Select(Box::new(Select {
4440 expressions: vec![Expression::Column(Column {
4441 name: Identifier::new("a".to_string()),
4442 table: None,
4443 join_mark: false,
4444 trailing_comments: vec![],
4445 })],
4446 from: Some(From {
4447 expressions: vec![Expression::Table(TableRef::new("t1"))],
4448 }),
4449 joins: vec![Join {
4450 this: Expression::Table(TableRef::new("t2")),
4451 kind: JoinKind::Semi,
4452 on: Some(Expression::Eq(Box::new(BinaryOp {
4453 left: Expression::Column(Column {
4454 name: Identifier::new("x".to_string()),
4455 table: None,
4456 join_mark: false,
4457 trailing_comments: vec![],
4458 }),
4459 right: Expression::Column(Column {
4460 name: Identifier::new("y".to_string()),
4461 table: None,
4462 join_mark: false,
4463 trailing_comments: vec![],
4464 }),
4465 left_comments: vec![],
4466 operator_comments: vec![],
4467 trailing_comments: vec![],
4468 }))),
4469 using: vec![],
4470 use_inner_keyword: false,
4471 use_outer_keyword: false,
4472 deferred_condition: false,
4473 join_hint: None,
4474 match_condition: None,
4475 pivots: Vec::new(),
4476 }],
4477 ..Select::new()
4478 }));
4479
4480 let result = eliminate_semi_and_anti_joins(select).unwrap();
4481 if let Expression::Select(s) = result {
4482 assert!(s.joins.is_empty());
4484 assert!(s.where_clause.is_some());
4486 } else {
4487 panic!("Expected Select expression");
4488 }
4489 }
4490
4491 #[test]
4492 fn test_no_ilike_sql() {
4493 use crate::expressions::LikeOp;
4494
4495 let ilike_expr = Expression::ILike(Box::new(LikeOp {
4497 left: Expression::Column(Column {
4498 name: Identifier::new("name".to_string()),
4499 table: None,
4500 join_mark: false,
4501 trailing_comments: vec![],
4502 }),
4503 right: Expression::Literal(Literal::String("%test%".to_string())),
4504 escape: None,
4505 quantifier: None,
4506 }));
4507
4508 let result = no_ilike_sql(ilike_expr).unwrap();
4509 if let Expression::Like(like) = result {
4510 if let Expression::Function(f) = &like.left {
4512 assert_eq!(f.name, "LOWER");
4513 } else {
4514 panic!("Expected LOWER function on left");
4515 }
4516 if let Expression::Function(f) = &like.right {
4518 assert_eq!(f.name, "LOWER");
4519 } else {
4520 panic!("Expected LOWER function on right");
4521 }
4522 } else {
4523 panic!("Expected Like expression");
4524 }
4525 }
4526
4527 #[test]
4528 fn test_no_trycast_sql() {
4529 let trycast_expr = Expression::TryCast(Box::new(Cast {
4531 this: Expression::Literal(Literal::String("123".to_string())),
4532 to: DataType::Int { length: None, integer_spelling: false },
4533 trailing_comments: vec![],
4534 double_colon_syntax: false,
4535 format: None,
4536 default: None,
4537 }));
4538
4539 let result = no_trycast_sql(trycast_expr).unwrap();
4540 assert!(matches!(result, Expression::Cast(_)));
4541 }
4542
4543 #[test]
4544 fn test_no_safe_cast_sql() {
4545 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
4547 this: Expression::Literal(Literal::String("123".to_string())),
4548 to: DataType::Int { length: None, integer_spelling: false },
4549 trailing_comments: vec![],
4550 double_colon_syntax: false,
4551 format: None,
4552 default: None,
4553 }));
4554
4555 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
4556 assert!(matches!(result, Expression::Cast(_)));
4557 }
4558
4559 #[test]
4560 fn test_explode_to_unnest_presto() {
4561 let spark = Dialect::get(DialectType::Spark);
4562 let result = spark.transpile_to("SELECT EXPLODE(x) FROM tbl", DialectType::Presto).unwrap();
4563 assert_eq!(
4564 result[0],
4565 "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))"
4566 );
4567 }
4568
4569 #[test]
4570 fn test_explode_to_unnest_bigquery() {
4571 let spark = Dialect::get(DialectType::Spark);
4572 let result = spark.transpile_to("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery).unwrap();
4573 assert_eq!(
4574 result[0],
4575 "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))"
4576 );
4577 }
4578
4579}