1use crate::dialects::transform_recursive;
10use crate::dialects::{Dialect, DialectType};
11use crate::error::Result;
12use crate::expressions::{
13 Alias, BinaryOp, BooleanLiteral, Cast, DataType, Exists, Expression, From, Function,
14 Identifier, Join, JoinKind, Lateral, LateralView, Literal, NamedArgSeparator, NamedArgument,
15 Over, Select, StructField, Subquery, UnaryFunc, UnnestFunc, Where, WindowFunction, With,
16 WithinGroup,
17};
18use std::cell::RefCell;
19
20pub fn preprocess<F>(expr: Expression, transforms: &[F]) -> Result<Expression>
29where
30 F: Fn(Expression) -> Result<Expression>,
31{
32 let mut result = expr;
33 for transform in transforms {
34 result = transform(result)?;
35 }
36 Ok(result)
37}
38
39pub fn grouped_percentiles_to_tsql_windows(expr: Expression) -> Result<Expression> {
47 transform_recursive(expr, &grouped_percentiles_to_tsql_windows_inner)
48}
49
50fn grouped_percentiles_to_tsql_windows_inner(expr: Expression) -> Result<Expression> {
51 let Expression::Select(select) = expr else {
52 return Ok(expr);
53 };
54
55 rewrite_grouped_percentile_select(*select).map(|select| Expression::Select(Box::new(select)))
56}
57
58fn rewrite_grouped_percentile_select(select: Select) -> Result<Select> {
59 let Some(group_by) = &select.group_by else {
60 return Ok(select);
61 };
62
63 if select.having.is_some()
64 || group_by.all.is_some()
65 || group_by.totals
66 || group_by.expressions.is_empty()
67 || group_by.expressions.iter().any(is_complex_grouping_expr)
68 {
69 return Ok(select);
70 }
71
72 let partition_by = group_by.expressions.clone();
73 let mut changed = false;
74 let mut rewritten_expressions = Vec::with_capacity(select.expressions.len());
75
76 for expression in &select.expressions {
77 if is_group_projection(expression, &partition_by) {
78 rewritten_expressions.push(expression.clone());
79 continue;
80 }
81
82 let Some(rewritten) = rewrite_grouped_percentile_projection(expression, &partition_by)
83 else {
84 return Ok(select);
85 };
86
87 changed = true;
88 rewritten_expressions.push(rewritten);
89 }
90
91 if !changed {
92 return Ok(select);
93 }
94
95 let mut rewritten = select;
96 rewritten.expressions = rewritten_expressions;
97 rewritten.group_by = None;
98 rewritten.distinct = true;
99 Ok(rewritten)
100}
101
102fn is_complex_grouping_expr(expr: &Expression) -> bool {
103 matches!(
104 expr,
105 Expression::Cube(_) | Expression::Rollup(_) | Expression::GroupingSets(_)
106 ) || matches!(expr, Expression::Function(f) if f.name.eq_ignore_ascii_case("GROUPING SETS"))
107}
108
109fn is_group_projection(expr: &Expression, group_by: &[Expression]) -> bool {
110 let inner = match expr {
111 Expression::Alias(alias) => &alias.this,
112 other => other,
113 };
114
115 group_by.iter().any(|group_expr| inner == group_expr)
116}
117
118fn rewrite_grouped_percentile_projection(
119 expr: &Expression,
120 partition_by: &[Expression],
121) -> Option<Expression> {
122 match expr {
123 Expression::Alias(alias) => {
124 let rewritten = rewrite_grouped_percentile_expr(&alias.this, partition_by)?;
125 let mut alias = alias.as_ref().clone();
126 alias.this = rewritten;
127 Some(Expression::Alias(Box::new(alias)))
128 }
129 other => rewrite_grouped_percentile_expr(other, partition_by),
130 }
131}
132
133fn rewrite_grouped_percentile_expr(
134 expr: &Expression,
135 partition_by: &[Expression],
136) -> Option<Expression> {
137 let Expression::WithinGroup(within_group) = expr else {
138 return None;
139 };
140
141 if !is_percentile_ordered_set(&within_group.this) || within_group.order_by.len() != 1 {
142 return None;
143 }
144
145 let mut order_by = within_group.order_by.clone();
146 order_by[0].nulls_first = None;
150
151 Some(Expression::WindowFunction(Box::new(WindowFunction {
152 this: Expression::WithinGroup(Box::new(WithinGroup {
153 this: within_group.this.clone(),
154 order_by,
155 })),
156 over: Over {
157 window_name: None,
158 partition_by: partition_by.to_vec(),
159 order_by: Vec::new(),
160 frame: None,
161 alias: None,
162 },
163 keep: None,
164 inferred_type: None,
165 })))
166}
167
168fn is_percentile_ordered_set(expr: &Expression) -> bool {
169 match expr {
170 Expression::Function(function) => is_percentile_name(&function.name),
171 Expression::AggregateFunction(function) => is_percentile_name(&function.name),
172 Expression::PercentileCont(_) | Expression::PercentileDisc(_) => true,
173 _ => false,
174 }
175}
176
177fn is_percentile_name(name: &str) -> bool {
178 name.eq_ignore_ascii_case("PERCENTILE_CONT") || name.eq_ignore_ascii_case("PERCENTILE_DISC")
179}
180
181pub fn unnest_to_explode(expr: Expression) -> Result<Expression> {
185 match expr {
186 Expression::Unnest(unnest) => {
187 Ok(Expression::Explode(Box::new(UnaryFunc::new(unnest.this))))
188 }
189 _ => Ok(expr),
190 }
191}
192
193pub fn unnest_to_explode_select(expr: Expression) -> Result<Expression> {
203 transform_recursive(expr, &unnest_to_explode_select_inner)
204}
205
206fn make_udtf_expr(unnest: &UnnestFunc) -> Expression {
209 let has_multi_expr = !unnest.expressions.is_empty();
210 if has_multi_expr {
211 let mut all_args = vec![unnest.this.clone()];
213 all_args.extend(unnest.expressions.iter().cloned());
214 let arrays_zip =
215 Expression::Function(Box::new(Function::new("ARRAYS_ZIP".to_string(), all_args)));
216 Expression::Function(Box::new(Function::new(
217 "INLINE".to_string(),
218 vec![arrays_zip],
219 )))
220 } else {
221 Expression::Explode(Box::new(UnaryFunc::new(unnest.this.clone())))
223 }
224}
225
226fn unnest_to_explode_select_inner(expr: Expression) -> Result<Expression> {
227 let Expression::Select(mut select) = expr else {
228 return Ok(expr);
229 };
230
231 if let Some(ref mut from) = select.from {
233 if from.expressions.len() >= 1 {
234 let mut new_from_exprs = Vec::new();
235 let mut new_lateral_views = Vec::new();
236 let first_is_unnest = is_unnest_expr(&from.expressions[0]);
237
238 for (idx, from_item) in from.expressions.drain(..).enumerate() {
239 if idx == 0 && first_is_unnest {
240 let replaced = replace_from_unnest(from_item);
243 new_from_exprs.push(replaced);
244 } else if idx > 0 && is_unnest_expr(&from_item) {
245 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(from_item);
247 let udtf = make_udtf_expr(&unnest_func);
248 new_lateral_views.push(LateralView {
249 this: udtf,
250 table_alias: alias_name,
251 column_aliases,
252 outer: false,
253 });
254 } else {
255 new_from_exprs.push(from_item);
256 }
257 }
258
259 from.expressions = new_from_exprs;
260 select.lateral_views.extend(new_lateral_views);
262 }
263 }
264
265 let mut remaining_joins = Vec::new();
267 for join in select.joins.drain(..) {
268 if matches!(join.kind, JoinKind::Cross | JoinKind::Inner) {
269 let (is_unnest, is_lateral) = check_join_unnest(&join.this);
270 if is_unnest {
271 let (lateral_alias, lateral_col_aliases, join_expr) = if is_lateral {
273 if let Expression::Lateral(lat) = join.this {
274 let alias = lat.alias.map(|s| Identifier::new(&s));
276 let col_aliases: Vec<Identifier> = lat
277 .column_aliases
278 .iter()
279 .map(|s| Identifier::new(s))
280 .collect();
281 (alias, col_aliases, *lat.this)
282 } else {
283 (None, Vec::new(), join.this)
284 }
285 } else {
286 (None, Vec::new(), join.this)
287 };
288
289 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(join_expr);
290
291 let final_alias = lateral_alias.or(alias_name);
293 let final_col_aliases = if !lateral_col_aliases.is_empty() {
294 lateral_col_aliases
295 } else {
296 column_aliases
297 };
298
299 let table_alias = final_alias.or_else(|| Some(Identifier::new("unnest")));
301 let col_aliases = if final_col_aliases.is_empty() {
302 vec![Identifier::new("unnest")]
303 } else {
304 final_col_aliases
305 };
306
307 let udtf = make_udtf_expr(&unnest_func);
308 select.lateral_views.push(LateralView {
309 this: udtf,
310 table_alias,
311 column_aliases: col_aliases,
312 outer: false,
313 });
314 } else {
315 remaining_joins.push(join);
316 }
317 } else {
318 remaining_joins.push(join);
319 }
320 }
321 select.joins = remaining_joins;
322
323 Ok(Expression::Select(select))
324}
325
326fn is_unnest_expr(expr: &Expression) -> bool {
328 match expr {
329 Expression::Unnest(_) => true,
330 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
331 _ => false,
332 }
333}
334
335fn check_join_unnest(expr: &Expression) -> (bool, bool) {
337 match expr {
338 Expression::Unnest(_) => (true, false),
339 Expression::Alias(a) => {
340 if matches!(a.this, Expression::Unnest(_)) {
341 (true, false)
342 } else {
343 (false, false)
344 }
345 }
346 Expression::Lateral(lat) => match &*lat.this {
347 Expression::Unnest(_) => (true, true),
348 Expression::Alias(a) => {
349 if matches!(a.this, Expression::Unnest(_)) {
350 (true, true)
351 } else {
352 (false, true)
353 }
354 }
355 _ => (false, true),
356 },
357 _ => (false, false),
358 }
359}
360
361fn replace_from_unnest(from_item: Expression) -> Expression {
363 match from_item {
364 Expression::Alias(mut a) => {
365 if let Expression::Unnest(unnest) = a.this {
366 a.this = make_udtf_expr(&unnest);
367 }
368 Expression::Alias(a)
369 }
370 Expression::Unnest(unnest) => make_udtf_expr(&unnest),
371 other => other,
372 }
373}
374
375fn extract_unnest_info(expr: Expression) -> (Option<Identifier>, Vec<Identifier>, UnnestFunc) {
377 match expr {
378 Expression::Alias(a) => {
379 if let Expression::Unnest(unnest) = a.this {
380 (Some(a.alias), a.column_aliases, *unnest)
381 } else {
382 (
384 Some(a.alias),
385 a.column_aliases,
386 UnnestFunc {
387 this: a.this,
388 expressions: Vec::new(),
389 with_ordinality: false,
390 alias: None,
391 offset_alias: None,
392 },
393 )
394 }
395 }
396 Expression::Unnest(unnest) => {
397 let alias = unnest.alias.clone();
398 (alias, Vec::new(), *unnest)
399 }
400 _ => (
401 None,
402 Vec::new(),
403 UnnestFunc {
404 this: expr,
405 expressions: Vec::new(),
406 with_ordinality: false,
407 alias: None,
408 offset_alias: None,
409 },
410 ),
411 }
412}
413
414pub fn explode_to_unnest(expr: Expression) -> Result<Expression> {
416 match expr {
417 Expression::Explode(explode) => Ok(Expression::Unnest(Box::new(UnnestFunc {
418 this: explode.this,
419 expressions: Vec::new(),
420 with_ordinality: false,
421 alias: None,
422 offset_alias: None,
423 }))),
424 _ => Ok(expr),
425 }
426}
427
428pub fn replace_bool_with_int(expr: Expression) -> Result<Expression> {
432 match expr {
433 Expression::Boolean(b) => {
434 let value = if b.value { "1" } else { "0" };
435 Ok(Expression::Literal(Box::new(Literal::Number(
436 value.to_string(),
437 ))))
438 }
439 _ => Ok(expr),
440 }
441}
442
443pub fn replace_int_with_bool(expr: Expression) -> Result<Expression> {
447 match expr {
448 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(n) if n == "1" || n == "0") =>
449 {
450 let Literal::Number(n) = lit.as_ref() else {
451 unreachable!()
452 };
453 Ok(Expression::Boolean(BooleanLiteral { value: n == "1" }))
454 }
455 _ => Ok(expr),
456 }
457}
458
459pub fn remove_precision_parameterized_types(expr: Expression) -> Result<Expression> {
464 Ok(strip_type_params_recursive(expr))
465}
466
467fn strip_type_params_recursive(expr: Expression) -> Expression {
469 match expr {
470 Expression::Cast(mut cast) => {
472 cast.to = strip_data_type_params(cast.to);
473 cast.this = strip_type_params_recursive(cast.this);
475 Expression::Cast(cast)
476 }
477 Expression::TryCast(mut try_cast) => {
479 try_cast.to = strip_data_type_params(try_cast.to);
480 try_cast.this = strip_type_params_recursive(try_cast.this);
481 Expression::TryCast(try_cast)
482 }
483 Expression::SafeCast(mut safe_cast) => {
485 safe_cast.to = strip_data_type_params(safe_cast.to);
486 safe_cast.this = strip_type_params_recursive(safe_cast.this);
487 Expression::SafeCast(safe_cast)
488 }
489 _ => expr,
492 }
493}
494
495fn strip_data_type_params(dt: DataType) -> DataType {
497 match dt {
498 DataType::Decimal { .. } => DataType::Decimal {
500 precision: None,
501 scale: None,
502 },
503 DataType::TinyInt { .. } => DataType::TinyInt { length: None },
504 DataType::SmallInt { .. } => DataType::SmallInt { length: None },
505 DataType::Int { .. } => DataType::Int {
506 length: None,
507 integer_spelling: false,
508 },
509 DataType::BigInt { .. } => DataType::BigInt { length: None },
510
511 DataType::Char { .. } => DataType::Char { length: None },
513 DataType::VarChar { .. } => DataType::VarChar {
514 length: None,
515 parenthesized_length: false,
516 },
517
518 DataType::Binary { .. } => DataType::Binary { length: None },
520 DataType::VarBinary { .. } => DataType::VarBinary { length: None },
521
522 DataType::Bit { .. } => DataType::Bit { length: None },
524 DataType::VarBit { .. } => DataType::VarBit { length: None },
525
526 DataType::Time { .. } => DataType::Time {
528 precision: None,
529 timezone: false,
530 },
531 DataType::Timestamp { timezone, .. } => DataType::Timestamp {
532 precision: None,
533 timezone,
534 },
535
536 DataType::Array {
538 element_type,
539 dimension,
540 } => DataType::Array {
541 element_type: Box::new(strip_data_type_params(*element_type)),
542 dimension,
543 },
544
545 DataType::Map {
547 key_type,
548 value_type,
549 } => DataType::Map {
550 key_type: Box::new(strip_data_type_params(*key_type)),
551 value_type: Box::new(strip_data_type_params(*value_type)),
552 },
553
554 DataType::Struct { fields, nested } => DataType::Struct {
556 fields: fields
557 .into_iter()
558 .map(|f| {
559 StructField::with_options(
560 f.name,
561 strip_data_type_params(f.data_type),
562 f.options,
563 )
564 })
565 .collect(),
566 nested,
567 },
568
569 DataType::Vector { element_type, .. } => DataType::Vector {
571 element_type: element_type.map(|et| Box::new(strip_data_type_params(*et))),
572 dimension: None,
573 },
574
575 DataType::Object { fields, modifier } => DataType::Object {
577 fields: fields
578 .into_iter()
579 .map(|(name, ty, not_null)| (name, strip_data_type_params(ty), not_null))
580 .collect(),
581 modifier,
582 },
583
584 other => other,
586 }
587}
588
589pub fn eliminate_qualify(expr: Expression) -> Result<Expression> {
604 match expr {
605 Expression::Select(mut select) => {
606 if let Some(qualify) = select.qualify.take() {
607 let qualify_filter = qualify.this;
614 let window_alias_name = "_w".to_string();
615 let window_alias_ident = Identifier::new(window_alias_name.clone());
616
617 let (window_expr, outer_where) =
620 extract_window_from_condition(qualify_filter.clone(), &window_alias_ident);
621
622 if let Some(win_expr) = window_expr {
623 let window_alias_expr =
625 Expression::Alias(Box::new(crate::expressions::Alias {
626 this: win_expr,
627 alias: window_alias_ident.clone(),
628 column_aliases: vec![],
629 alias_explicit_as: false,
630 alias_keyword: None,
631 pre_alias_comments: vec![],
632 trailing_comments: vec![],
633 inferred_type: None,
634 }));
635
636 let outer_exprs: Vec<Expression> = select
640 .expressions
641 .iter()
642 .map(|expr| {
643 if let Expression::Alias(a) = expr {
644 Expression::Column(Box::new(crate::expressions::Column {
646 name: a.alias.clone(),
647 table: None,
648 join_mark: false,
649 trailing_comments: vec![],
650 span: None,
651 inferred_type: None,
652 }))
653 } else {
654 expr.clone()
655 }
656 })
657 .collect();
658 select.expressions.push(window_alias_expr);
659
660 let inner_select = Expression::Select(select);
662 let subquery = Subquery {
663 this: inner_select,
664 alias: Some(Identifier::new("_t".to_string())),
665 column_aliases: vec![],
666 alias_explicit_as: false,
667 alias_keyword: None,
668 order_by: None,
669 limit: None,
670 offset: None,
671 distribute_by: None,
672 sort_by: None,
673 cluster_by: None,
674 lateral: false,
675 modifiers_inside: false,
676 trailing_comments: vec![],
677 inferred_type: None,
678 };
679
680 let outer_select = Select {
682 expressions: outer_exprs,
683 from: Some(From {
684 expressions: vec![Expression::Subquery(Box::new(subquery))],
685 }),
686 where_clause: Some(Where { this: outer_where }),
687 ..Select::new()
688 };
689
690 return Ok(Expression::Select(Box::new(outer_select)));
691 } else {
692 let qualify_alias = Expression::Alias(Box::new(crate::expressions::Alias {
694 this: qualify_filter.clone(),
695 alias: window_alias_ident.clone(),
696 column_aliases: vec![],
697 alias_explicit_as: false,
698 alias_keyword: None,
699 pre_alias_comments: vec![],
700 trailing_comments: vec![],
701 inferred_type: None,
702 }));
703
704 let original_exprs = select.expressions.clone();
705 select.expressions.push(qualify_alias);
706
707 let inner_select = Expression::Select(select);
708 let subquery = Subquery {
709 this: inner_select,
710 alias: Some(Identifier::new("_t".to_string())),
711 column_aliases: vec![],
712 alias_explicit_as: false,
713 alias_keyword: None,
714 order_by: None,
715 limit: None,
716 offset: None,
717 distribute_by: None,
718 sort_by: None,
719 cluster_by: None,
720 lateral: false,
721 modifiers_inside: false,
722 trailing_comments: vec![],
723 inferred_type: None,
724 };
725
726 let outer_select = Select {
727 expressions: original_exprs,
728 from: Some(From {
729 expressions: vec![Expression::Subquery(Box::new(subquery))],
730 }),
731 where_clause: Some(Where {
732 this: Expression::Column(Box::new(crate::expressions::Column {
733 name: window_alias_ident,
734 table: None,
735 join_mark: false,
736 trailing_comments: vec![],
737 span: None,
738 inferred_type: None,
739 })),
740 }),
741 ..Select::new()
742 };
743
744 return Ok(Expression::Select(Box::new(outer_select)));
745 }
746 }
747 Ok(Expression::Select(select))
748 }
749 other => Ok(other),
750 }
751}
752
753fn extract_window_from_condition(
757 condition: Expression,
758 alias: &Identifier,
759) -> (Option<Expression>, Expression) {
760 let alias_col = Expression::Column(Box::new(crate::expressions::Column {
761 name: alias.clone(),
762 table: None,
763 join_mark: false,
764 trailing_comments: vec![],
765 span: None,
766 inferred_type: None,
767 }));
768
769 match condition {
771 Expression::Eq(ref op) => {
773 if is_window_expr(&op.left) {
774 (
775 Some(op.left.clone()),
776 Expression::Eq(Box::new(BinaryOp {
777 left: alias_col,
778 right: op.right.clone(),
779 ..(**op).clone()
780 })),
781 )
782 } else if is_window_expr(&op.right) {
783 (
784 Some(op.right.clone()),
785 Expression::Eq(Box::new(BinaryOp {
786 left: op.left.clone(),
787 right: alias_col,
788 ..(**op).clone()
789 })),
790 )
791 } else {
792 (None, condition)
793 }
794 }
795 Expression::Neq(ref op) => {
796 if is_window_expr(&op.left) {
797 (
798 Some(op.left.clone()),
799 Expression::Neq(Box::new(BinaryOp {
800 left: alias_col,
801 right: op.right.clone(),
802 ..(**op).clone()
803 })),
804 )
805 } else if is_window_expr(&op.right) {
806 (
807 Some(op.right.clone()),
808 Expression::Neq(Box::new(BinaryOp {
809 left: op.left.clone(),
810 right: alias_col,
811 ..(**op).clone()
812 })),
813 )
814 } else {
815 (None, condition)
816 }
817 }
818 Expression::Lt(ref op) => {
819 if is_window_expr(&op.left) {
820 (
821 Some(op.left.clone()),
822 Expression::Lt(Box::new(BinaryOp {
823 left: alias_col,
824 right: op.right.clone(),
825 ..(**op).clone()
826 })),
827 )
828 } else if is_window_expr(&op.right) {
829 (
830 Some(op.right.clone()),
831 Expression::Lt(Box::new(BinaryOp {
832 left: op.left.clone(),
833 right: alias_col,
834 ..(**op).clone()
835 })),
836 )
837 } else {
838 (None, condition)
839 }
840 }
841 Expression::Lte(ref op) => {
842 if is_window_expr(&op.left) {
843 (
844 Some(op.left.clone()),
845 Expression::Lte(Box::new(BinaryOp {
846 left: alias_col,
847 right: op.right.clone(),
848 ..(**op).clone()
849 })),
850 )
851 } else if is_window_expr(&op.right) {
852 (
853 Some(op.right.clone()),
854 Expression::Lte(Box::new(BinaryOp {
855 left: op.left.clone(),
856 right: alias_col,
857 ..(**op).clone()
858 })),
859 )
860 } else {
861 (None, condition)
862 }
863 }
864 Expression::Gt(ref op) => {
865 if is_window_expr(&op.left) {
866 (
867 Some(op.left.clone()),
868 Expression::Gt(Box::new(BinaryOp {
869 left: alias_col,
870 right: op.right.clone(),
871 ..(**op).clone()
872 })),
873 )
874 } else if is_window_expr(&op.right) {
875 (
876 Some(op.right.clone()),
877 Expression::Gt(Box::new(BinaryOp {
878 left: op.left.clone(),
879 right: alias_col,
880 ..(**op).clone()
881 })),
882 )
883 } else {
884 (None, condition)
885 }
886 }
887 Expression::Gte(ref op) => {
888 if is_window_expr(&op.left) {
889 (
890 Some(op.left.clone()),
891 Expression::Gte(Box::new(BinaryOp {
892 left: alias_col,
893 right: op.right.clone(),
894 ..(**op).clone()
895 })),
896 )
897 } else if is_window_expr(&op.right) {
898 (
899 Some(op.right.clone()),
900 Expression::Gte(Box::new(BinaryOp {
901 left: op.left.clone(),
902 right: alias_col,
903 ..(**op).clone()
904 })),
905 )
906 } else {
907 (None, condition)
908 }
909 }
910 _ if is_window_expr(&condition) => (Some(condition), alias_col),
912 _ => (None, condition),
914 }
915}
916
917fn is_window_expr(expr: &Expression) -> bool {
919 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
920}
921
922pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
941 eliminate_distinct_on_for_dialect(expr, None, None)
942}
943
944pub fn strip_cte_materialization(expr: Expression) -> Result<Expression> {
947 transform_recursive(expr, &strip_cte_materialization_single)
948}
949
950fn strip_cte_materialization_single(expr: Expression) -> Result<Expression> {
951 Ok(match expr {
952 Expression::Select(mut select) => {
953 strip_with_cte_materialization(&mut select.with);
954 Expression::Select(select)
955 }
956 Expression::Union(mut union) => {
957 strip_with_cte_materialization(&mut union.with);
958 Expression::Union(union)
959 }
960 Expression::Intersect(mut intersect) => {
961 strip_with_cte_materialization(&mut intersect.with);
962 Expression::Intersect(intersect)
963 }
964 Expression::Except(mut except) => {
965 strip_with_cte_materialization(&mut except.with);
966 Expression::Except(except)
967 }
968 Expression::Pivot(mut pivot) => {
969 strip_with_cte_materialization(&mut pivot.with);
970 Expression::Pivot(pivot)
971 }
972 Expression::Insert(mut insert) => {
973 strip_with_cte_materialization(&mut insert.with);
974 Expression::Insert(insert)
975 }
976 Expression::Update(mut update) => {
977 strip_with_cte_materialization(&mut update.with);
978 Expression::Update(update)
979 }
980 Expression::Delete(mut delete) => {
981 strip_with_cte_materialization(&mut delete.with);
982 Expression::Delete(delete)
983 }
984 Expression::CreateTable(mut create_table) => {
985 strip_with_cte_materialization(&mut create_table.with_cte);
986 Expression::CreateTable(create_table)
987 }
988 Expression::With(mut with) => {
989 strip_cte_materialization_in_with(&mut with);
990 Expression::With(with)
991 }
992 Expression::Cte(mut cte) => {
993 cte.materialized = None;
994 Expression::Cte(cte)
995 }
996 _ => expr,
997 })
998}
999
1000fn strip_with_cte_materialization(with: &mut Option<With>) {
1001 if let Some(with) = with {
1002 strip_cte_materialization_in_with(with);
1003 }
1004}
1005
1006fn strip_cte_materialization_in_with(with: &mut With) {
1007 for cte in &mut with.ctes {
1008 cte.materialized = None;
1009 }
1010}
1011
1012#[derive(Clone, Copy)]
1013enum DistinctOnNullsMode {
1014 None,
1015 NullsFirst,
1016 CaseExpr,
1017}
1018
1019pub fn eliminate_distinct_on_for_dialect(
1024 expr: Expression,
1025 target: Option<DialectType>,
1026 source: Option<DialectType>,
1027) -> Result<Expression> {
1028 if matches!(
1030 target,
1031 Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)
1032 ) {
1033 return Ok(expr);
1034 }
1035
1036 let nulls_mode = match target {
1041 Some(DialectType::MySQL)
1042 | Some(DialectType::SingleStore)
1043 | Some(DialectType::TSQL)
1044 | Some(DialectType::Fabric) => DistinctOnNullsMode::CaseExpr,
1045 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => {
1046 DistinctOnNullsMode::None
1047 }
1048 Some(DialectType::StarRocks) => {
1049 if matches!(source, Some(DialectType::Redshift)) {
1050 DistinctOnNullsMode::CaseExpr
1051 } else {
1052 DistinctOnNullsMode::None
1053 }
1054 }
1055 _ => DistinctOnNullsMode::NullsFirst,
1057 };
1058
1059 transform_recursive(expr, &|expr| eliminate_distinct_on_select(expr, nulls_mode))
1060}
1061
1062fn eliminate_distinct_on_select(
1063 expr: Expression,
1064 nulls_mode: DistinctOnNullsMode,
1065) -> Result<Expression> {
1066 use crate::expressions::Case;
1067
1068 match expr {
1069 Expression::Select(mut select) => {
1070 if let Some(distinct_cols) = select.distinct_on.take() {
1071 if !distinct_cols.is_empty() {
1072 let row_number_alias = Identifier::new("_row_number".to_string());
1074
1075 let order_exprs = if let Some(ref order_by) = select.order_by {
1077 let mut exprs = order_by.expressions.clone();
1078 match nulls_mode {
1080 DistinctOnNullsMode::NullsFirst => {
1081 for ord in &mut exprs {
1082 if ord.desc && ord.nulls_first.is_none() {
1083 ord.nulls_first = Some(true);
1084 }
1085 }
1086 }
1087 DistinctOnNullsMode::CaseExpr => {
1088 let mut new_exprs = Vec::new();
1091 for ord in &exprs {
1092 if ord.desc && ord.nulls_first.is_none() {
1093 let null_check = Expression::Case(Box::new(Case {
1095 operand: None,
1096 whens: vec![(
1097 Expression::IsNull(Box::new(
1098 crate::expressions::IsNull {
1099 this: ord.this.clone(),
1100 not: false,
1101 postfix_form: false,
1102 },
1103 )),
1104 Expression::Literal(Box::new(Literal::Number(
1105 "1".to_string(),
1106 ))),
1107 )],
1108 else_: Some(Expression::Literal(Box::new(
1109 Literal::Number("0".to_string()),
1110 ))),
1111 comments: Vec::new(),
1112 inferred_type: None,
1113 }));
1114 new_exprs.push(crate::expressions::Ordered {
1115 this: null_check,
1116 desc: true,
1117 nulls_first: None,
1118 explicit_asc: false,
1119 with_fill: None,
1120 });
1121 }
1122 new_exprs.push(ord.clone());
1123 }
1124 exprs = new_exprs;
1125 }
1126 DistinctOnNullsMode::None => {}
1127 }
1128 exprs
1129 } else {
1130 distinct_cols
1131 .iter()
1132 .map(|e| crate::expressions::Ordered {
1133 this: e.clone(),
1134 desc: false,
1135 nulls_first: None,
1136 explicit_asc: false,
1137 with_fill: None,
1138 })
1139 .collect()
1140 };
1141
1142 let row_number_func =
1144 Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
1145 this: Expression::RowNumber(crate::expressions::RowNumber),
1146 over: Over {
1147 partition_by: distinct_cols,
1148 order_by: order_exprs,
1149 frame: None,
1150 window_name: None,
1151 alias: None,
1152 },
1153 keep: None,
1154 inferred_type: None,
1155 }));
1156
1157 let mut inner_aliased_exprs = Vec::new();
1161 let mut outer_select_exprs = Vec::new();
1162 for orig_expr in &select.expressions {
1163 match orig_expr {
1164 Expression::Alias(alias) => {
1165 inner_aliased_exprs.push(orig_expr.clone());
1167 outer_select_exprs.push(Expression::Column(Box::new(
1168 crate::expressions::Column {
1169 name: alias.alias.clone(),
1170 table: None,
1171 join_mark: false,
1172 trailing_comments: vec![],
1173 span: None,
1174 inferred_type: None,
1175 },
1176 )));
1177 }
1178 Expression::Column(col) => {
1179 inner_aliased_exprs.push(Expression::Alias(Box::new(
1181 crate::expressions::Alias {
1182 this: orig_expr.clone(),
1183 alias: col.name.clone(),
1184 column_aliases: vec![],
1185 alias_explicit_as: false,
1186 alias_keyword: None,
1187 pre_alias_comments: vec![],
1188 trailing_comments: vec![],
1189 inferred_type: None,
1190 },
1191 )));
1192 outer_select_exprs.push(Expression::Column(Box::new(
1193 crate::expressions::Column {
1194 name: col.name.clone(),
1195 table: None,
1196 join_mark: false,
1197 trailing_comments: vec![],
1198 span: None,
1199 inferred_type: None,
1200 },
1201 )));
1202 }
1203 _ => {
1204 inner_aliased_exprs.push(orig_expr.clone());
1206 outer_select_exprs.push(orig_expr.clone());
1207 }
1208 }
1209 }
1210
1211 let row_number_alias_expr =
1213 Expression::Alias(Box::new(crate::expressions::Alias {
1214 this: row_number_func,
1215 alias: row_number_alias.clone(),
1216 column_aliases: vec![],
1217 alias_explicit_as: false,
1218 alias_keyword: None,
1219 pre_alias_comments: vec![],
1220 trailing_comments: vec![],
1221 inferred_type: None,
1222 }));
1223 inner_aliased_exprs.push(row_number_alias_expr);
1224
1225 select.expressions = inner_aliased_exprs;
1227
1228 let _inner_order_by = select.order_by.take();
1230
1231 select.distinct = false;
1233
1234 let inner_select = Expression::Select(select);
1236 let subquery = Subquery {
1237 this: inner_select,
1238 alias: Some(Identifier::new("_t".to_string())),
1239 column_aliases: vec![],
1240 alias_explicit_as: false,
1241 alias_keyword: None,
1242 order_by: None,
1243 limit: None,
1244 offset: None,
1245 distribute_by: None,
1246 sort_by: None,
1247 cluster_by: None,
1248 lateral: false,
1249 modifiers_inside: false,
1250 trailing_comments: vec![],
1251 inferred_type: None,
1252 };
1253
1254 let outer_select = Select {
1257 expressions: outer_select_exprs,
1258 from: Some(From {
1259 expressions: vec![Expression::Subquery(Box::new(subquery))],
1260 }),
1261 where_clause: Some(Where {
1262 this: Expression::Eq(Box::new(BinaryOp {
1263 left: Expression::Column(Box::new(crate::expressions::Column {
1264 name: row_number_alias,
1265 table: None,
1266 join_mark: false,
1267 trailing_comments: vec![],
1268 span: None,
1269 inferred_type: None,
1270 })),
1271 right: Expression::Literal(Box::new(Literal::Number(
1272 "1".to_string(),
1273 ))),
1274 left_comments: vec![],
1275 operator_comments: vec![],
1276 trailing_comments: vec![],
1277 inferred_type: None,
1278 })),
1279 }),
1280 ..Select::new()
1281 };
1282
1283 return Ok(Expression::Select(Box::new(outer_select)));
1284 }
1285 }
1286 Ok(Expression::Select(select))
1287 }
1288 other => Ok(other),
1289 }
1290}
1291
1292pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
1300 match expr {
1301 Expression::Select(mut select) => {
1302 let mut new_joins = Vec::new();
1303 let mut extra_where_conditions = Vec::new();
1304
1305 for join in select.joins.drain(..) {
1306 match join.kind {
1307 JoinKind::Semi | JoinKind::LeftSemi => {
1308 if let Some(on_condition) = join.on {
1309 let subquery_select = Select {
1311 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1312 "1".to_string(),
1313 )))],
1314 from: Some(From {
1315 expressions: vec![join.this],
1316 }),
1317 where_clause: Some(Where { this: on_condition }),
1318 ..Select::new()
1319 };
1320
1321 let exists = Expression::Exists(Box::new(Exists {
1322 this: Expression::Subquery(Box::new(Subquery {
1323 this: Expression::Select(Box::new(subquery_select)),
1324 alias: None,
1325 column_aliases: vec![],
1326 alias_explicit_as: false,
1327 alias_keyword: None,
1328 order_by: None,
1329 limit: None,
1330 offset: None,
1331 distribute_by: None,
1332 sort_by: None,
1333 cluster_by: None,
1334 lateral: false,
1335 modifiers_inside: false,
1336 trailing_comments: vec![],
1337 inferred_type: None,
1338 })),
1339 not: false,
1340 }));
1341
1342 extra_where_conditions.push(exists);
1343 }
1344 }
1345 JoinKind::Anti | JoinKind::LeftAnti => {
1346 if let Some(on_condition) = join.on {
1347 let subquery_select = Select {
1349 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1350 "1".to_string(),
1351 )))],
1352 from: Some(From {
1353 expressions: vec![join.this],
1354 }),
1355 where_clause: Some(Where { this: on_condition }),
1356 ..Select::new()
1357 };
1358
1359 let not_exists = Expression::Exists(Box::new(Exists {
1361 this: Expression::Subquery(Box::new(Subquery {
1362 this: Expression::Select(Box::new(subquery_select)),
1363 alias: None,
1364 column_aliases: vec![],
1365 alias_explicit_as: false,
1366 alias_keyword: None,
1367 order_by: None,
1368 limit: None,
1369 offset: None,
1370 distribute_by: None,
1371 sort_by: None,
1372 cluster_by: None,
1373 lateral: false,
1374 modifiers_inside: false,
1375 trailing_comments: vec![],
1376 inferred_type: None,
1377 })),
1378 not: true,
1379 }));
1380
1381 extra_where_conditions.push(not_exists);
1382 }
1383 }
1384 _ => {
1385 new_joins.push(join);
1387 }
1388 }
1389 }
1390
1391 select.joins = new_joins;
1392
1393 if !extra_where_conditions.is_empty() {
1395 let combined = extra_where_conditions
1396 .into_iter()
1397 .reduce(|acc, cond| {
1398 Expression::And(Box::new(BinaryOp {
1399 left: acc,
1400 right: cond,
1401 left_comments: vec![],
1402 operator_comments: vec![],
1403 trailing_comments: vec![],
1404 inferred_type: None,
1405 }))
1406 })
1407 .unwrap();
1408
1409 select.where_clause = match select.where_clause {
1410 Some(Where { this: existing }) => Some(Where {
1411 this: Expression::And(Box::new(BinaryOp {
1412 left: existing,
1413 right: combined,
1414 left_comments: vec![],
1415 operator_comments: vec![],
1416 trailing_comments: vec![],
1417 inferred_type: None,
1418 })),
1419 }),
1420 None => Some(Where { this: combined }),
1421 };
1422 }
1423
1424 Ok(Expression::Select(select))
1425 }
1426 other => Ok(other),
1427 }
1428}
1429
1430pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
1448 match expr {
1449 Expression::Select(mut select) => {
1450 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
1452
1453 if let Some(idx) = full_outer_join_idx {
1454 let full_join_count = select
1456 .joins
1457 .iter()
1458 .filter(|j| j.kind == JoinKind::Full)
1459 .count();
1460 if full_join_count != 1 {
1461 return Ok(Expression::Select(select));
1462 }
1463
1464 let mut right_select = select.clone();
1466
1467 let full_join = &select.joins[idx];
1469 let join_condition = full_join.on.clone();
1470
1471 select.joins[idx].kind = JoinKind::Left;
1473
1474 right_select.joins[idx].kind = JoinKind::Right;
1476
1477 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
1479 if !from.expressions.is_empty() {
1480 let anti_subquery = Expression::Select(Box::new(Select {
1481 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1482 "1".to_string(),
1483 )))],
1484 from: Some(from.clone()),
1485 where_clause: Some(Where {
1486 this: join_cond.clone(),
1487 }),
1488 ..Select::new()
1489 }));
1490
1491 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
1492 inferred_type: None,
1493 this: Expression::Exists(Box::new(Exists {
1494 this: Expression::Subquery(Box::new(Subquery {
1495 this: anti_subquery,
1496 alias: None,
1497 column_aliases: vec![],
1498 alias_explicit_as: false,
1499 alias_keyword: None,
1500 order_by: None,
1501 limit: None,
1502 offset: None,
1503 distribute_by: None,
1504 sort_by: None,
1505 cluster_by: None,
1506 lateral: false,
1507 modifiers_inside: false,
1508 trailing_comments: vec![],
1509 inferred_type: None,
1510 })),
1511 not: false,
1512 })),
1513 }));
1514
1515 right_select.where_clause = Some(Where {
1517 this: match right_select.where_clause {
1518 Some(w) => Expression::And(Box::new(BinaryOp {
1519 left: w.this,
1520 right: not_exists,
1521 left_comments: vec![],
1522 operator_comments: vec![],
1523 trailing_comments: vec![],
1524 inferred_type: None,
1525 })),
1526 None => not_exists,
1527 },
1528 });
1529 }
1530 }
1531
1532 right_select.with = None;
1534
1535 let order_by = select.order_by.take();
1537
1538 let union = crate::expressions::Union {
1540 left: Expression::Select(select),
1541 right: Expression::Select(right_select),
1542 all: true, distinct: false,
1544 with: None,
1545 order_by,
1546 limit: None,
1547 offset: None,
1548 distribute_by: None,
1549 sort_by: None,
1550 cluster_by: None,
1551 by_name: false,
1552 side: None,
1553 kind: None,
1554 corresponding: false,
1555 strict: false,
1556 on_columns: Vec::new(),
1557 };
1558
1559 return Ok(Expression::Union(Box::new(union)));
1560 }
1561
1562 Ok(Expression::Select(select))
1563 }
1564 other => Ok(other),
1565 }
1566}
1567
1568pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
1581 match expr {
1582 Expression::Select(mut select) => {
1583 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
1585 let mut has_recursive = false;
1586
1587 collect_nested_ctes(
1588 &Expression::Select(select.clone()),
1589 &mut collected_ctes,
1590 &mut has_recursive,
1591 true,
1592 );
1593
1594 let mut cte_body_collected: Vec<(String, Vec<crate::expressions::Cte>)> = Vec::new();
1597 if let Some(ref with) = select.with {
1598 for cte in &with.ctes {
1599 let mut body_ctes: Vec<crate::expressions::Cte> = Vec::new();
1600 collect_ctes_from_cte_body(&cte.this, &mut body_ctes, &mut has_recursive);
1601 if !body_ctes.is_empty() {
1602 cte_body_collected.push((cte.alias.name.clone(), body_ctes));
1603 }
1604 }
1605 }
1606
1607 let has_subquery_ctes = !collected_ctes.is_empty();
1608 let has_body_ctes = !cte_body_collected.is_empty();
1609
1610 if has_subquery_ctes || has_body_ctes {
1611 strip_nested_with_clauses(&mut select, true);
1613
1614 if has_body_ctes {
1616 if let Some(ref mut with) = select.with {
1617 for cte in with.ctes.iter_mut() {
1618 strip_with_from_cte_body(&mut cte.this);
1619 }
1620 }
1621 }
1622
1623 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
1624 ctes: Vec::new(),
1625 recursive: false,
1626 leading_comments: vec![],
1627 search: None,
1628 });
1629
1630 if has_recursive {
1631 top_with.recursive = true;
1632 }
1633
1634 if has_body_ctes {
1636 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
1637 for mut cte in top_with.ctes.drain(..) {
1638 if let Some(pos) = cte_body_collected
1640 .iter()
1641 .position(|(name, _)| *name == cte.alias.name)
1642 {
1643 let (_, mut nested) = cte_body_collected.remove(pos);
1644 for nested_cte in nested.iter_mut() {
1646 strip_with_from_cte_body(&mut nested_cte.this);
1647 }
1648 new_ctes.extend(nested);
1649 }
1650 strip_with_from_cte_body(&mut cte.this);
1652 new_ctes.push(cte);
1653 }
1654 top_with.ctes = new_ctes;
1655 }
1656
1657 top_with.ctes.extend(collected_ctes);
1659 }
1660
1661 Ok(Expression::Select(select))
1662 }
1663 other => Ok(other),
1664 }
1665}
1666
1667fn collect_ctes_from_cte_body(
1669 expr: &Expression,
1670 collected: &mut Vec<crate::expressions::Cte>,
1671 has_recursive: &mut bool,
1672) {
1673 if let Expression::Select(select) = expr {
1674 if let Some(ref with) = select.with {
1675 if with.recursive {
1676 *has_recursive = true;
1677 }
1678 for cte in &with.ctes {
1679 collect_ctes_from_cte_body(&cte.this, collected, has_recursive);
1681 collected.push(cte.clone());
1683 }
1684 }
1685 }
1686}
1687
1688fn strip_with_from_cte_body(expr: &mut Expression) {
1690 if let Expression::Select(ref mut select) = expr {
1691 select.with = None;
1692 }
1693}
1694
1695fn strip_nested_with_clauses(select: &mut Select, _is_top_level: bool) {
1697 if let Some(ref mut from) = select.from {
1699 for expr in from.expressions.iter_mut() {
1700 strip_with_from_expr(expr);
1701 }
1702 }
1703 for join in select.joins.iter_mut() {
1705 strip_with_from_expr(&mut join.this);
1706 }
1707 for expr in select.expressions.iter_mut() {
1709 strip_with_from_expr(expr);
1710 }
1711 if let Some(ref mut w) = select.where_clause {
1713 strip_with_from_expr(&mut w.this);
1714 }
1715}
1716
1717fn strip_with_from_expr(expr: &mut Expression) {
1718 match expr {
1719 Expression::Subquery(ref mut subquery) => {
1720 strip_with_from_inner_query(&mut subquery.this);
1721 }
1722 Expression::Alias(ref mut alias) => {
1723 strip_with_from_expr(&mut alias.this);
1724 }
1725 Expression::Select(ref mut select) => {
1726 select.with = None;
1728 strip_nested_with_clauses(select, false);
1730 }
1731 _ => {}
1732 }
1733}
1734
1735fn strip_with_from_inner_query(expr: &mut Expression) {
1736 if let Expression::Select(ref mut select) = expr {
1737 select.with = None;
1738 strip_nested_with_clauses(select, false);
1739 }
1740}
1741
1742fn collect_nested_ctes(
1744 expr: &Expression,
1745 collected: &mut Vec<crate::expressions::Cte>,
1746 has_recursive: &mut bool,
1747 is_top_level: bool,
1748) {
1749 match expr {
1750 Expression::Select(select) => {
1751 if !is_top_level {
1753 if let Some(ref with) = select.with {
1754 if with.recursive {
1755 *has_recursive = true;
1756 }
1757 collected.extend(with.ctes.clone());
1758 }
1759 }
1760
1761 if let Some(ref from) = select.from {
1763 for expr in &from.expressions {
1764 collect_nested_ctes(expr, collected, has_recursive, false);
1765 }
1766 }
1767
1768 for join in &select.joins {
1770 collect_nested_ctes(&join.this, collected, has_recursive, false);
1771 }
1772
1773 for sel_expr in &select.expressions {
1775 collect_nested_ctes(sel_expr, collected, has_recursive, false);
1776 }
1777
1778 if let Some(ref where_clause) = select.where_clause {
1780 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
1781 }
1782 }
1783 Expression::Subquery(subquery) => {
1784 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
1786 }
1787 Expression::Alias(alias) => {
1788 collect_nested_ctes(&alias.this, collected, has_recursive, false);
1789 }
1790 _ => {}
1792 }
1793}
1794
1795pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
1811 match expr {
1812 Expression::Select(mut select) => {
1813 if let Some(named_windows) = select.windows.take() {
1814 let window_map: std::collections::HashMap<String, &Over> = named_windows
1816 .iter()
1817 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
1818 .collect();
1819
1820 select.expressions = select
1822 .expressions
1823 .into_iter()
1824 .map(|e| inline_window_refs(e, &window_map))
1825 .collect();
1826 }
1827 Ok(Expression::Select(select))
1828 }
1829 other => Ok(other),
1830 }
1831}
1832
1833fn inline_window_refs(
1835 expr: Expression,
1836 window_map: &std::collections::HashMap<String, &Over>,
1837) -> Expression {
1838 match expr {
1839 Expression::WindowFunction(mut wf) => {
1840 if let Some(ref name) = wf.over.window_name {
1842 let key = name.name.to_lowercase();
1843 if let Some(named_spec) = window_map.get(&key) {
1844 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
1846 wf.over.partition_by = named_spec.partition_by.clone();
1847 }
1848 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
1849 wf.over.order_by = named_spec.order_by.clone();
1850 }
1851 if wf.over.frame.is_none() && named_spec.frame.is_some() {
1852 wf.over.frame = named_spec.frame.clone();
1853 }
1854 wf.over.window_name = None;
1856 }
1857 }
1858 Expression::WindowFunction(wf)
1859 }
1860 Expression::Alias(mut alias) => {
1861 alias.this = inline_window_refs(alias.this, window_map);
1863 Expression::Alias(alias)
1864 }
1865 other => other,
1868 }
1869}
1870
1871pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
1885 match expr {
1886 Expression::Select(mut select) => {
1887 let has_join_marks = select
1889 .where_clause
1890 .as_ref()
1891 .map_or(false, |w| contains_join_mark(&w.this));
1892
1893 if !has_join_marks {
1894 return Ok(Expression::Select(select));
1895 }
1896
1897 let from_tables: Vec<String> = select
1899 .from
1900 .as_ref()
1901 .map(|f| {
1902 f.expressions
1903 .iter()
1904 .filter_map(|e| get_table_name(e))
1905 .collect()
1906 })
1907 .unwrap_or_default();
1908
1909 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
1911 std::collections::HashMap::new();
1912 let mut remaining_conditions: Vec<Expression> = Vec::new();
1913
1914 if let Some(ref where_clause) = select.where_clause {
1915 extract_join_mark_conditions(
1916 &where_clause.this,
1917 &mut join_conditions,
1918 &mut remaining_conditions,
1919 );
1920 }
1921
1922 let mut new_joins = select.joins.clone();
1924 for (table_name, conditions) in join_conditions {
1925 let table_in_from = from_tables.contains(&table_name);
1927
1928 if table_in_from && !conditions.is_empty() {
1929 let combined_condition = conditions.into_iter().reduce(|a, b| {
1931 Expression::And(Box::new(BinaryOp {
1932 left: a,
1933 right: b,
1934 left_comments: vec![],
1935 operator_comments: vec![],
1936 trailing_comments: vec![],
1937 inferred_type: None,
1938 }))
1939 });
1940
1941 if let Some(ref mut from) = select.from {
1943 if let Some(pos) = from
1944 .expressions
1945 .iter()
1946 .position(|e| get_table_name(e).map_or(false, |n| n == table_name))
1947 {
1948 if from.expressions.len() > 1 {
1949 let join_table = from.expressions.remove(pos);
1950 new_joins.push(crate::expressions::Join {
1951 this: join_table,
1952 kind: JoinKind::Left,
1953 on: combined_condition,
1954 using: vec![],
1955 use_inner_keyword: false,
1956 use_outer_keyword: true,
1957 deferred_condition: false,
1958 join_hint: None,
1959 match_condition: None,
1960 pivots: Vec::new(),
1961 comments: Vec::new(),
1962 nesting_group: 0,
1963 directed: false,
1964 });
1965 }
1966 }
1967 }
1968 }
1969 }
1970
1971 select.joins = new_joins;
1972
1973 if remaining_conditions.is_empty() {
1975 select.where_clause = None;
1976 } else {
1977 let combined = remaining_conditions.into_iter().reduce(|a, b| {
1978 Expression::And(Box::new(BinaryOp {
1979 left: a,
1980 right: b,
1981 left_comments: vec![],
1982 operator_comments: vec![],
1983 trailing_comments: vec![],
1984 inferred_type: None,
1985 }))
1986 });
1987 select.where_clause = combined.map(|c| Where { this: c });
1988 }
1989
1990 clear_join_marks(&mut Expression::Select(select.clone()));
1992
1993 Ok(Expression::Select(select))
1994 }
1995 other => Ok(other),
1996 }
1997}
1998
1999fn contains_join_mark(expr: &Expression) -> bool {
2001 match expr {
2002 Expression::Column(col) => col.join_mark,
2003 Expression::And(op) | Expression::Or(op) => {
2004 contains_join_mark(&op.left) || contains_join_mark(&op.right)
2005 }
2006 Expression::Eq(op)
2007 | Expression::Neq(op)
2008 | Expression::Lt(op)
2009 | Expression::Lte(op)
2010 | Expression::Gt(op)
2011 | Expression::Gte(op) => contains_join_mark(&op.left) || contains_join_mark(&op.right),
2012 Expression::Not(op) => contains_join_mark(&op.this),
2013 _ => false,
2014 }
2015}
2016
2017fn get_table_name(expr: &Expression) -> Option<String> {
2019 match expr {
2020 Expression::Table(t) => Some(t.name.name.clone()),
2021 Expression::Alias(a) => Some(a.alias.name.clone()),
2022 _ => None,
2023 }
2024}
2025
2026fn extract_join_mark_conditions(
2028 expr: &Expression,
2029 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
2030 remaining: &mut Vec<Expression>,
2031) {
2032 match expr {
2033 Expression::And(op) => {
2034 extract_join_mark_conditions(&op.left, join_conditions, remaining);
2035 extract_join_mark_conditions(&op.right, join_conditions, remaining);
2036 }
2037 _ => {
2038 if let Some(table) = get_join_mark_table(expr) {
2039 join_conditions
2040 .entry(table)
2041 .or_insert_with(Vec::new)
2042 .push(expr.clone());
2043 } else {
2044 remaining.push(expr.clone());
2045 }
2046 }
2047 }
2048}
2049
2050fn get_join_mark_table(expr: &Expression) -> Option<String> {
2052 match expr {
2053 Expression::Eq(op)
2054 | Expression::Neq(op)
2055 | Expression::Lt(op)
2056 | Expression::Lte(op)
2057 | Expression::Gt(op)
2058 | Expression::Gte(op) => {
2059 if let Expression::Column(col) = &op.left {
2061 if col.join_mark {
2062 return col.table.as_ref().map(|t| t.name.clone());
2063 }
2064 }
2065 if let Expression::Column(col) = &op.right {
2066 if col.join_mark {
2067 return col.table.as_ref().map(|t| t.name.clone());
2068 }
2069 }
2070 None
2071 }
2072 _ => None,
2073 }
2074}
2075
2076fn clear_join_marks(expr: &mut Expression) {
2078 match expr {
2079 Expression::Column(col) => col.join_mark = false,
2080 Expression::Select(select) => {
2081 if let Some(ref mut w) = select.where_clause {
2082 clear_join_marks(&mut w.this);
2083 }
2084 for sel_expr in &mut select.expressions {
2085 clear_join_marks(sel_expr);
2086 }
2087 }
2088 Expression::And(op) | Expression::Or(op) => {
2089 clear_join_marks(&mut op.left);
2090 clear_join_marks(&mut op.right);
2091 }
2092 Expression::Eq(op)
2093 | Expression::Neq(op)
2094 | Expression::Lt(op)
2095 | Expression::Lte(op)
2096 | Expression::Gt(op)
2097 | Expression::Gte(op) => {
2098 clear_join_marks(&mut op.left);
2099 clear_join_marks(&mut op.right);
2100 }
2101 _ => {}
2102 }
2103}
2104
2105pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
2112 match expr {
2113 Expression::Select(mut select) => {
2114 if let Some(ref mut with) = select.with {
2115 if with.recursive {
2116 let mut counter = 0;
2117 for cte in &mut with.ctes {
2118 if cte.columns.is_empty() {
2119 if let Expression::Select(ref cte_select) = cte.this {
2121 let names: Vec<Identifier> = cte_select
2122 .expressions
2123 .iter()
2124 .map(|e| match e {
2125 Expression::Alias(a) => a.alias.clone(),
2126 Expression::Column(c) => c.name.clone(),
2127 _ => {
2128 counter += 1;
2129 Identifier::new(format!("_c_{}", counter))
2130 }
2131 })
2132 .collect();
2133 cte.columns = names;
2134 }
2135 }
2136 }
2137 }
2138 }
2139 Ok(Expression::Select(select))
2140 }
2141 other => Ok(other),
2142 }
2143}
2144
2145pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
2152 match expr {
2153 Expression::Cast(mut cast) => {
2154 if let Expression::Literal(ref lit) = cast.this {
2155 if let Literal::String(ref s) = lit.as_ref() {
2156 if s.to_lowercase() == "epoch" {
2157 if is_temporal_type(&cast.to) {
2158 cast.this = Expression::Literal(Box::new(Literal::String(
2159 "1970-01-01 00:00:00".to_string(),
2160 )));
2161 }
2162 }
2163 }
2164 }
2165 Ok(Expression::Cast(cast))
2166 }
2167 Expression::TryCast(mut try_cast) => {
2168 if let Expression::Literal(ref lit) = try_cast.this {
2169 if let Literal::String(ref s) = lit.as_ref() {
2170 if s.to_lowercase() == "epoch" {
2171 if is_temporal_type(&try_cast.to) {
2172 try_cast.this = Expression::Literal(Box::new(Literal::String(
2173 "1970-01-01 00:00:00".to_string(),
2174 )));
2175 }
2176 }
2177 }
2178 }
2179 Ok(Expression::TryCast(try_cast))
2180 }
2181 other => Ok(other),
2182 }
2183}
2184
2185fn is_temporal_type(dt: &DataType) -> bool {
2187 matches!(
2188 dt,
2189 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
2190 )
2191}
2192
2193pub fn ensure_bools(expr: Expression) -> Result<Expression> {
2218 let expr = ensure_bools_in_value_context(expr);
2219
2220 Ok(match expr {
2221 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => ensure_bool_condition(expr),
2223 other => other,
2224 })
2225}
2226
2227fn ensure_bools_in_value_context(expr: Expression) -> Expression {
2231 match expr {
2232 Expression::Case(mut case) => {
2233 case.whens = case
2234 .whens
2235 .into_iter()
2236 .map(|(condition, result)| {
2237 let new_condition =
2238 ensure_bool_condition(ensure_bools_in_value_context(condition));
2239 let new_result = ensure_bools_in_value_context(result);
2240 (new_condition, new_result)
2241 })
2242 .collect();
2243 if let Some(else_expr) = case.else_ {
2244 case.else_ = Some(ensure_bools_in_value_context(else_expr));
2245 }
2246 Expression::Case(Box::new(*case))
2247 }
2248 Expression::Select(select) => Expression::Select(Box::new(ensure_bools_in_select(*select))),
2249 Expression::Subquery(mut subquery) => {
2250 subquery.this = ensure_bools_in_value_context(subquery.this);
2251 Expression::Subquery(subquery)
2252 }
2253 Expression::Union(mut union) => {
2254 let left = std::mem::replace(&mut union.left, Expression::null());
2255 let right = std::mem::replace(&mut union.right, Expression::null());
2256 union.left = ensure_bools_in_value_context(left);
2257 union.right = ensure_bools_in_value_context(right);
2258 if let Some(with) = union.with.take() {
2259 union.with = Some(ensure_bools_in_with(with));
2260 }
2261 Expression::Union(union)
2262 }
2263 Expression::Intersect(mut intersect) => {
2264 let left = std::mem::replace(&mut intersect.left, Expression::null());
2265 let right = std::mem::replace(&mut intersect.right, Expression::null());
2266 intersect.left = ensure_bools_in_value_context(left);
2267 intersect.right = ensure_bools_in_value_context(right);
2268 if let Some(with) = intersect.with.take() {
2269 intersect.with = Some(ensure_bools_in_with(with));
2270 }
2271 Expression::Intersect(intersect)
2272 }
2273 Expression::Except(mut except) => {
2274 let left = std::mem::replace(&mut except.left, Expression::null());
2275 let right = std::mem::replace(&mut except.right, Expression::null());
2276 except.left = ensure_bools_in_value_context(left);
2277 except.right = ensure_bools_in_value_context(right);
2278 if let Some(with) = except.with.take() {
2279 except.with = Some(ensure_bools_in_with(with));
2280 }
2281 Expression::Except(except)
2282 }
2283 Expression::Alias(mut alias) => {
2284 alias.this = ensure_bools_in_value_context(alias.this);
2285 Expression::Alias(alias)
2286 }
2287 Expression::Paren(mut paren) => {
2288 paren.this = ensure_bools_in_value_context(paren.this);
2289 Expression::Paren(paren)
2290 }
2291 other => other,
2292 }
2293}
2294
2295fn ensure_bools_in_select(mut select: Select) -> Select {
2296 select.expressions = select
2297 .expressions
2298 .into_iter()
2299 .map(ensure_bools_in_value_context)
2300 .collect();
2301
2302 if let Some(from) = select.from.take() {
2303 select.from = Some(crate::expressions::From {
2304 expressions: from
2305 .expressions
2306 .into_iter()
2307 .map(ensure_bools_in_value_context)
2308 .collect(),
2309 });
2310 }
2311
2312 select.joins = select.joins.into_iter().map(ensure_bools_in_join).collect();
2313
2314 if let Some(mut where_clause) = select.where_clause.take() {
2315 where_clause.this = ensure_bool_condition(ensure_bools_in_value_context(where_clause.this));
2316 select.where_clause = Some(where_clause);
2317 }
2318
2319 if let Some(mut having) = select.having.take() {
2320 having.this = ensure_bool_condition(ensure_bools_in_value_context(having.this));
2321 select.having = Some(having);
2322 }
2323
2324 if let Some(with) = select.with.take() {
2325 select.with = Some(ensure_bools_in_with(with));
2326 }
2327
2328 select
2329}
2330
2331fn ensure_bools_in_join(mut join: Join) -> Join {
2332 join.this = ensure_bools_in_value_context(join.this);
2333
2334 if let Some(on) = join.on.take() {
2335 join.on = Some(ensure_bool_condition(ensure_bools_in_value_context(on)));
2336 }
2337
2338 join.pivots = join
2339 .pivots
2340 .into_iter()
2341 .map(ensure_bools_in_value_context)
2342 .collect();
2343
2344 join
2345}
2346
2347fn ensure_bools_in_with(mut with: With) -> With {
2348 with.ctes = with
2349 .ctes
2350 .into_iter()
2351 .map(|mut cte| {
2352 cte.this = ensure_bools_in_value_context(cte.this);
2353 cte
2354 })
2355 .collect();
2356 with
2357}
2358
2359fn is_boolean_expression(expr: &Expression) -> bool {
2362 matches!(
2363 expr,
2364 Expression::Eq(_)
2365 | Expression::Neq(_)
2366 | Expression::Lt(_)
2367 | Expression::Lte(_)
2368 | Expression::Gt(_)
2369 | Expression::Gte(_)
2370 | Expression::Is(_)
2371 | Expression::IsNull(_)
2372 | Expression::IsTrue(_)
2373 | Expression::IsFalse(_)
2374 | Expression::Like(_)
2375 | Expression::ILike(_)
2376 | Expression::SimilarTo(_)
2377 | Expression::Glob(_)
2378 | Expression::RegexpLike(_)
2379 | Expression::In(_)
2380 | Expression::Between(_)
2381 | Expression::Exists(_)
2382 | Expression::And(_)
2383 | Expression::Or(_)
2384 | Expression::Not(_)
2385 | Expression::Any(_)
2386 | Expression::All(_)
2387 | Expression::NullSafeEq(_)
2388 | Expression::NullSafeNeq(_)
2389 | Expression::EqualNull(_)
2390 )
2391}
2392
2393fn wrap_neq_zero(expr: Expression) -> Expression {
2395 Expression::Neq(Box::new(BinaryOp {
2396 left: expr,
2397 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2398 left_comments: vec![],
2399 operator_comments: vec![],
2400 trailing_comments: vec![],
2401 inferred_type: None,
2402 }))
2403}
2404
2405fn ensure_bool_condition(expr: Expression) -> Expression {
2411 match expr {
2412 Expression::And(op) => {
2414 let new_op = BinaryOp {
2415 left: ensure_bool_condition(op.left.clone()),
2416 right: ensure_bool_condition(op.right.clone()),
2417 left_comments: op.left_comments.clone(),
2418 operator_comments: op.operator_comments.clone(),
2419 trailing_comments: op.trailing_comments.clone(),
2420 inferred_type: None,
2421 };
2422 Expression::And(Box::new(new_op))
2423 }
2424 Expression::Or(op) => {
2425 let new_op = BinaryOp {
2426 left: ensure_bool_condition(op.left.clone()),
2427 right: ensure_bool_condition(op.right.clone()),
2428 left_comments: op.left_comments.clone(),
2429 operator_comments: op.operator_comments.clone(),
2430 trailing_comments: op.trailing_comments.clone(),
2431 inferred_type: None,
2432 };
2433 Expression::Or(Box::new(new_op))
2434 }
2435 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
2437 this: ensure_bool_condition(op.this.clone()),
2438 inferred_type: None,
2439 })),
2440 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
2442 this: ensure_bool_condition(paren.this.clone()),
2443 trailing_comments: paren.trailing_comments.clone(),
2444 })),
2445 Expression::Boolean(BooleanLiteral { value: true }) => {
2447 Expression::Paren(Box::new(crate::expressions::Paren {
2448 this: Expression::Eq(Box::new(BinaryOp {
2449 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2450 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2451 left_comments: vec![],
2452 operator_comments: vec![],
2453 trailing_comments: vec![],
2454 inferred_type: None,
2455 })),
2456 trailing_comments: vec![],
2457 }))
2458 }
2459 Expression::Boolean(BooleanLiteral { value: false }) => {
2460 Expression::Paren(Box::new(crate::expressions::Paren {
2461 this: Expression::Eq(Box::new(BinaryOp {
2462 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2463 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2464 left_comments: vec![],
2465 operator_comments: vec![],
2466 trailing_comments: vec![],
2467 inferred_type: None,
2468 })),
2469 trailing_comments: vec![],
2470 }))
2471 }
2472 ref e if is_boolean_expression(e) => expr,
2474 _ => wrap_neq_zero(expr),
2477 }
2478}
2479
2480pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
2486 Ok(unqualify_columns_recursive(expr))
2487}
2488
2489fn unqualify_columns_recursive(expr: Expression) -> Expression {
2491 match expr {
2492 Expression::Column(mut col) => {
2493 col.table = None;
2494 Expression::Column(col)
2495 }
2496 Expression::Select(mut select) => {
2497 select.expressions = select
2498 .expressions
2499 .into_iter()
2500 .map(unqualify_columns_recursive)
2501 .collect();
2502 if let Some(ref mut where_clause) = select.where_clause {
2503 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
2504 }
2505 if let Some(ref mut having) = select.having {
2506 having.this = unqualify_columns_recursive(having.this.clone());
2507 }
2508 if let Some(ref mut group_by) = select.group_by {
2509 group_by.expressions = group_by
2510 .expressions
2511 .iter()
2512 .cloned()
2513 .map(unqualify_columns_recursive)
2514 .collect();
2515 }
2516 if let Some(ref mut order_by) = select.order_by {
2517 order_by.expressions = order_by
2518 .expressions
2519 .iter()
2520 .map(|o| crate::expressions::Ordered {
2521 this: unqualify_columns_recursive(o.this.clone()),
2522 desc: o.desc,
2523 nulls_first: o.nulls_first,
2524 explicit_asc: o.explicit_asc,
2525 with_fill: o.with_fill.clone(),
2526 })
2527 .collect();
2528 }
2529 for join in &mut select.joins {
2530 if let Some(ref mut on) = join.on {
2531 *on = unqualify_columns_recursive(on.clone());
2532 }
2533 }
2534 Expression::Select(select)
2535 }
2536 Expression::Alias(mut alias) => {
2537 alias.this = unqualify_columns_recursive(alias.this);
2538 Expression::Alias(alias)
2539 }
2540 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
2542 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
2543 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
2544 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
2545 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
2546 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
2547 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
2548 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
2549 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
2550 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
2551 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
2552 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
2553 Expression::Function(mut func) => {
2555 func.args = func
2556 .args
2557 .into_iter()
2558 .map(unqualify_columns_recursive)
2559 .collect();
2560 Expression::Function(func)
2561 }
2562 Expression::AggregateFunction(mut func) => {
2563 func.args = func
2564 .args
2565 .into_iter()
2566 .map(unqualify_columns_recursive)
2567 .collect();
2568 Expression::AggregateFunction(func)
2569 }
2570 Expression::Case(mut case) => {
2571 case.whens = case
2572 .whens
2573 .into_iter()
2574 .map(|(cond, result)| {
2575 (
2576 unqualify_columns_recursive(cond),
2577 unqualify_columns_recursive(result),
2578 )
2579 })
2580 .collect();
2581 if let Some(else_expr) = case.else_ {
2582 case.else_ = Some(unqualify_columns_recursive(else_expr));
2583 }
2584 Expression::Case(case)
2585 }
2586 other => other,
2588 }
2589}
2590
2591fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
2593 op.left = unqualify_columns_recursive(op.left);
2594 op.right = unqualify_columns_recursive(op.right);
2595 op
2596}
2597
2598pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
2618 match expr {
2619 Expression::Select(mut select) => {
2620 let mut cte_count = 0;
2621 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2622
2623 if let Some(ref mut with) = select.with {
2625 for cte in &mut with.ctes {
2626 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
2627 }
2628 }
2629
2630 if let Some(ref mut from) = select.from {
2632 for table_expr in &mut from.expressions {
2633 if let Some((cte, replacement)) =
2634 try_convert_generate_date_array(table_expr, &mut cte_count)
2635 {
2636 new_ctes.push(cte);
2637 *table_expr = replacement;
2638 }
2639 }
2640 }
2641
2642 for join in &mut select.joins {
2644 if let Some((cte, replacement)) =
2645 try_convert_generate_date_array(&join.this, &mut cte_count)
2646 {
2647 new_ctes.push(cte);
2648 join.this = replacement;
2649 }
2650 }
2651
2652 if !new_ctes.is_empty() {
2654 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
2655 ctes: Vec::new(),
2656 recursive: true, leading_comments: vec![],
2658 search: None,
2659 });
2660 with_clause.recursive = true;
2661
2662 let mut all_ctes = new_ctes;
2664 all_ctes.append(&mut with_clause.ctes);
2665 with_clause.ctes = all_ctes;
2666 }
2667
2668 Ok(Expression::Select(select))
2669 }
2670 other => Ok(other),
2671 }
2672}
2673
2674fn process_expression_for_gda(
2677 expr: &mut Expression,
2678 cte_count: &mut usize,
2679 new_ctes: &mut Vec<crate::expressions::Cte>,
2680) {
2681 match expr {
2682 Expression::Select(ref mut select) => {
2683 if let Some(ref mut from) = select.from {
2685 for table_expr in &mut from.expressions {
2686 if let Some((cte, replacement)) =
2687 try_convert_generate_date_array(table_expr, cte_count)
2688 {
2689 new_ctes.push(cte);
2690 *table_expr = replacement;
2691 }
2692 }
2693 }
2694 for join in &mut select.joins {
2696 if let Some((cte, replacement)) =
2697 try_convert_generate_date_array(&join.this, cte_count)
2698 {
2699 new_ctes.push(cte);
2700 join.this = replacement;
2701 }
2702 }
2703 }
2704 Expression::Union(ref mut u) => {
2705 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
2706 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
2707 }
2708 Expression::Subquery(ref mut sq) => {
2709 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
2710 }
2711 _ => {}
2712 }
2713}
2714
2715fn try_convert_generate_date_array(
2718 expr: &Expression,
2719 cte_count: &mut usize,
2720) -> Option<(crate::expressions::Cte, Expression)> {
2721 try_convert_generate_date_array_with_name(expr, cte_count, None)
2722}
2723
2724fn try_convert_generate_date_array_with_name(
2725 expr: &Expression,
2726 cte_count: &mut usize,
2727 column_name_override: Option<&str>,
2728) -> Option<(crate::expressions::Cte, Expression)> {
2729 fn extract_gda_args(
2731 inner: &Expression,
2732 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
2733 match inner {
2734 Expression::GenerateDateArray(gda) => {
2735 let start = gda.start.as_ref()?;
2736 let end = gda.end.as_ref()?;
2737 let step = gda.step.as_deref();
2738 Some((start, end, step))
2739 }
2740 Expression::GenerateSeries(gs) => {
2741 let start = gs.start.as_deref()?;
2742 let end = gs.end.as_deref()?;
2743 let step = gs.step.as_deref();
2744 Some((start, end, step))
2745 }
2746 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
2747 if f.args.len() >= 2 {
2748 let start = &f.args[0];
2749 let end = &f.args[1];
2750 let step = f.args.get(2);
2751 Some((start, end, step))
2752 } else {
2753 None
2754 }
2755 }
2756 _ => None,
2757 }
2758 }
2759
2760 if let Expression::Unnest(unnest) = expr {
2762 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
2763 let start = start;
2764 let end = end;
2765 let step: Option<&Expression> = step_opt;
2766
2767 let cte_name = if *cte_count == 0 {
2769 "_generated_dates".to_string()
2770 } else {
2771 format!("_generated_dates_{}", cte_count)
2772 };
2773 *cte_count += 1;
2774
2775 let column_name =
2776 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
2777
2778 let cast_to_date = |expr: &Expression| -> Expression {
2780 match expr {
2781 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
2782 if let Expression::Literal(lit) = expr {
2784 if let Literal::Date(d) = lit.as_ref() {
2785 Expression::Cast(Box::new(Cast {
2786 this: Expression::Literal(Box::new(Literal::String(d.clone()))),
2787 to: DataType::Date,
2788 trailing_comments: vec![],
2789 double_colon_syntax: false,
2790 format: None,
2791 default: None,
2792 inferred_type: None,
2793 }))
2794 } else {
2795 expr.clone()
2796 }
2797 } else {
2798 unreachable!()
2799 }
2800 }
2801 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
2802 _ => Expression::Cast(Box::new(Cast {
2803 this: expr.clone(),
2804 to: DataType::Date,
2805 trailing_comments: vec![],
2806 double_colon_syntax: false,
2807 format: None,
2808 default: None,
2809 inferred_type: None,
2810 })),
2811 }
2812 };
2813
2814 let base_select = Select {
2816 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
2817 this: cast_to_date(start),
2818 alias: column_name.clone(),
2819 column_aliases: vec![],
2820 alias_explicit_as: false,
2821 alias_keyword: None,
2822 pre_alias_comments: vec![],
2823 trailing_comments: vec![],
2824 inferred_type: None,
2825 }))],
2826 ..Select::new()
2827 };
2828
2829 let normalize_interval = |expr: &Expression| -> Expression {
2831 if let Expression::Interval(ref iv) = expr {
2832 let mut iv_clone = iv.as_ref().clone();
2833 if let Some(Expression::Literal(ref lit)) = iv_clone.this {
2834 if let Literal::String(ref s) = lit.as_ref() {
2835 if s.parse::<f64>().is_ok() {
2837 iv_clone.this =
2838 Some(Expression::Literal(Box::new(Literal::Number(s.clone()))));
2839 }
2840 }
2841 }
2842 Expression::Interval(Box::new(iv_clone))
2843 } else {
2844 expr.clone()
2845 }
2846 };
2847
2848 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
2851 Expression::Interval(Box::new(crate::expressions::Interval {
2852 this: Some(Expression::Literal(Box::new(Literal::Number(
2853 "1".to_string(),
2854 )))),
2855 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
2856 unit: crate::expressions::IntervalUnit::Day,
2857 use_plural: false,
2858 }),
2859 }))
2860 });
2861
2862 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
2864
2865 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
2866 this: Expression::Column(Box::new(crate::expressions::Column {
2867 name: column_name.clone(),
2868 table: None,
2869 join_mark: false,
2870 trailing_comments: vec![],
2871 span: None,
2872 inferred_type: None,
2873 })),
2874 interval: add_count,
2875 unit: add_unit,
2876 }));
2877
2878 let cast_date_add = Expression::Cast(Box::new(Cast {
2879 this: date_add_expr.clone(),
2880 to: DataType::Date,
2881 trailing_comments: vec![],
2882 double_colon_syntax: false,
2883 format: None,
2884 default: None,
2885 inferred_type: None,
2886 }));
2887
2888 let recursive_select = Select {
2889 expressions: vec![cast_date_add.clone()],
2890 from: Some(From {
2891 expressions: vec![Expression::Table(Box::new(
2892 crate::expressions::TableRef::new(&cte_name),
2893 ))],
2894 }),
2895 where_clause: Some(Where {
2896 this: Expression::Lte(Box::new(BinaryOp {
2897 left: cast_date_add,
2898 right: cast_to_date(end),
2899 left_comments: vec![],
2900 operator_comments: vec![],
2901 trailing_comments: vec![],
2902 inferred_type: None,
2903 })),
2904 }),
2905 ..Select::new()
2906 };
2907
2908 let union = crate::expressions::Union {
2910 left: Expression::Select(Box::new(base_select)),
2911 right: Expression::Select(Box::new(recursive_select)),
2912 all: true, distinct: false,
2914 with: None,
2915 order_by: None,
2916 limit: None,
2917 offset: None,
2918 distribute_by: None,
2919 sort_by: None,
2920 cluster_by: None,
2921 by_name: false,
2922 side: None,
2923 kind: None,
2924 corresponding: false,
2925 strict: false,
2926 on_columns: Vec::new(),
2927 };
2928
2929 let cte = crate::expressions::Cte {
2931 this: Expression::Union(Box::new(union)),
2932 alias: Identifier::new(cte_name.clone()),
2933 columns: vec![column_name.clone()],
2934 materialized: None,
2935 key_expressions: Vec::new(),
2936 alias_first: true,
2937 comments: Vec::new(),
2938 };
2939
2940 let replacement_select = Select {
2942 expressions: vec![Expression::Column(Box::new(crate::expressions::Column {
2943 name: column_name,
2944 table: None,
2945 join_mark: false,
2946 trailing_comments: vec![],
2947 span: None,
2948 inferred_type: None,
2949 }))],
2950 from: Some(From {
2951 expressions: vec![Expression::Table(Box::new(
2952 crate::expressions::TableRef::new(&cte_name),
2953 ))],
2954 }),
2955 ..Select::new()
2956 };
2957
2958 let replacement = Expression::Subquery(Box::new(Subquery {
2959 this: Expression::Select(Box::new(replacement_select)),
2960 alias: Some(Identifier::new(cte_name)),
2961 column_aliases: vec![],
2962 alias_explicit_as: false,
2963 alias_keyword: None,
2964 order_by: None,
2965 limit: None,
2966 offset: None,
2967 distribute_by: None,
2968 sort_by: None,
2969 cluster_by: None,
2970 lateral: false,
2971 modifiers_inside: false,
2972 trailing_comments: vec![],
2973 inferred_type: None,
2974 }));
2975
2976 return Some((cte, replacement));
2977 }
2978 }
2979
2980 if let Expression::Alias(alias) = expr {
2982 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
2984 if let Some((cte, replacement)) =
2985 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
2986 {
2987 if col_name.is_some() {
2990 return Some((cte, replacement));
2991 }
2992 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
2993 this: replacement,
2994 alias: alias.alias.clone(),
2995 column_aliases: alias.column_aliases.clone(),
2996 alias_explicit_as: false,
2997 alias_keyword: None,
2998 pre_alias_comments: alias.pre_alias_comments.clone(),
2999 trailing_comments: alias.trailing_comments.clone(),
3000 inferred_type: None,
3001 }));
3002 return Some((cte, new_alias));
3003 }
3004 }
3005
3006 None
3007}
3008
3009fn extract_interval_unit_and_count(
3014 expr: &Expression,
3015) -> (crate::expressions::IntervalUnit, Expression) {
3016 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
3017
3018 if let Expression::Interval(ref iv) = expr {
3019 if let Some(ref unit_spec) = iv.unit {
3021 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
3022 let count = match &iv.this {
3023 Some(e) => e.clone(),
3024 None => Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3025 };
3026 return (unit.clone(), count);
3027 }
3028 }
3029
3030 if let Some(ref val_expr) = iv.this {
3032 match val_expr {
3033 Expression::Literal(lit)
3034 if matches!(lit.as_ref(), Literal::String(_) | Literal::Number(_)) =>
3035 {
3036 let s = match lit.as_ref() {
3037 Literal::String(s) | Literal::Number(s) => s,
3038 _ => unreachable!(),
3039 };
3040 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
3042 if parts.len() == 2 {
3043 let count_str = parts[0].trim();
3044 let unit_str = parts[1].trim().to_uppercase();
3045 let unit = match unit_str.as_str() {
3046 "YEAR" | "YEARS" => IntervalUnit::Year,
3047 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
3048 "MONTH" | "MONTHS" => IntervalUnit::Month,
3049 "WEEK" | "WEEKS" => IntervalUnit::Week,
3050 "DAY" | "DAYS" => IntervalUnit::Day,
3051 "HOUR" | "HOURS" => IntervalUnit::Hour,
3052 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
3053 "SECOND" | "SECONDS" => IntervalUnit::Second,
3054 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
3055 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
3056 _ => IntervalUnit::Day,
3057 };
3058 return (
3059 unit,
3060 Expression::Literal(Box::new(Literal::Number(count_str.to_string()))),
3061 );
3062 }
3063 if s.parse::<f64>().is_ok() {
3065 return (
3066 IntervalUnit::Day,
3067 Expression::Literal(Box::new(Literal::Number(s.clone()))),
3068 );
3069 }
3070 }
3071 _ => {}
3072 }
3073 }
3074
3075 (
3077 IntervalUnit::Day,
3078 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3079 )
3080 } else {
3081 (
3082 IntervalUnit::Day,
3083 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3084 )
3085 }
3086}
3087
3088pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
3101 match expr {
3102 Expression::ILike(ilike) => {
3103 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
3105 name: "LOWER".to_string(),
3106 args: vec![ilike.left],
3107 distinct: false,
3108 trailing_comments: vec![],
3109 use_bracket_syntax: false,
3110 no_parens: false,
3111 quoted: false,
3112 span: None,
3113 inferred_type: None,
3114 }));
3115
3116 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
3117 name: "LOWER".to_string(),
3118 args: vec![ilike.right],
3119 distinct: false,
3120 trailing_comments: vec![],
3121 use_bracket_syntax: false,
3122 no_parens: false,
3123 quoted: false,
3124 span: None,
3125 inferred_type: None,
3126 }));
3127
3128 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
3129 left: lower_left,
3130 right: lower_right,
3131 escape: ilike.escape,
3132 quantifier: ilike.quantifier,
3133 inferred_type: None,
3134 })))
3135 }
3136 other => Ok(other),
3137 }
3138}
3139
3140pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
3148 match expr {
3149 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
3150 other => Ok(other),
3151 }
3152}
3153
3154pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
3159 match expr {
3160 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
3161 other => Ok(other),
3162 }
3163}
3164
3165pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
3172 Ok(expr)
3174}
3175
3176pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
3190 match expr {
3193 Expression::Table(ref table) => {
3194 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
3197 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3199 this: expr.clone(),
3200 expressions: Vec::new(),
3201 with_ordinality: false,
3202 alias: None,
3203 offset_alias: None,
3204 }));
3205
3206 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
3208 this: unnest,
3209 alias: Identifier::new("_u".to_string()),
3210 column_aliases: vec![],
3211 alias_explicit_as: false,
3212 alias_keyword: None,
3213 pre_alias_comments: vec![],
3214 trailing_comments: vec![],
3215 inferred_type: None,
3216 })));
3217 }
3218 Ok(expr)
3219 }
3220 Expression::GenerateSeries(gs) => {
3221 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3223 this: Expression::GenerateSeries(gs),
3224 expressions: Vec::new(),
3225 with_ordinality: false,
3226 alias: None,
3227 offset_alias: None,
3228 }));
3229 Ok(unnest)
3230 }
3231 other => Ok(other),
3232 }
3233}
3234
3235pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
3246 use crate::dialects::transform_recursive;
3247 transform_recursive(expr, &unwrap_unnest_generate_series_single)
3248}
3249
3250fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
3251 use crate::expressions::*;
3252 match expr {
3254 Expression::Select(mut select) => {
3255 if let Some(ref mut from) = select.from {
3257 for table_expr in &mut from.expressions {
3258 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
3259 *table_expr = replacement;
3260 }
3261 }
3262 }
3263 for join in &mut select.joins {
3265 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
3266 join.this = replacement;
3267 }
3268 }
3269 Ok(Expression::Select(select))
3270 }
3271 other => Ok(other),
3272 }
3273}
3274
3275fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
3278 use crate::expressions::*;
3279
3280 let gen_series = match expr {
3282 Expression::Unnest(unnest) => {
3283 if let Expression::GenerateSeries(ref gs) = unnest.this {
3284 Some(gs.as_ref().clone())
3285 } else {
3286 None
3287 }
3288 }
3289 Expression::Alias(alias) => {
3290 if let Expression::Unnest(ref unnest) = alias.this {
3291 if let Expression::GenerateSeries(ref gs) = unnest.this {
3292 Some(gs.as_ref().clone())
3293 } else {
3294 None
3295 }
3296 } else {
3297 None
3298 }
3299 }
3300 _ => None,
3301 };
3302
3303 let gs = gen_series?;
3304
3305 let value_col = Expression::boxed_column(Column {
3307 name: Identifier::new("value".to_string()),
3308 table: None,
3309 join_mark: false,
3310 trailing_comments: vec![],
3311 span: None,
3312 inferred_type: None,
3313 });
3314
3315 let cast_value = Expression::Cast(Box::new(Cast {
3316 this: value_col,
3317 to: DataType::Date,
3318 trailing_comments: vec![],
3319 double_colon_syntax: false,
3320 format: None,
3321 default: None,
3322 inferred_type: None,
3323 }));
3324
3325 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
3326
3327 let gen_series_aliased = Expression::Alias(Box::new(Alias {
3329 this: gen_series_expr,
3330 alias: Identifier::new("_t".to_string()),
3331 column_aliases: vec![Identifier::new("value".to_string())],
3332 alias_explicit_as: false,
3333 alias_keyword: None,
3334 pre_alias_comments: vec![],
3335 trailing_comments: vec![],
3336 inferred_type: None,
3337 }));
3338
3339 let mut inner_select = Select::new();
3340 inner_select.expressions = vec![cast_value];
3341 inner_select.from = Some(From {
3342 expressions: vec![gen_series_aliased],
3343 });
3344
3345 let inner_select_expr = Expression::Select(Box::new(inner_select));
3346
3347 let subquery = Expression::Subquery(Box::new(Subquery {
3348 this: inner_select_expr,
3349 alias: None,
3350 column_aliases: vec![],
3351 alias_explicit_as: false,
3352 alias_keyword: None,
3353 order_by: None,
3354 limit: None,
3355 offset: None,
3356 distribute_by: None,
3357 sort_by: None,
3358 cluster_by: None,
3359 lateral: false,
3360 modifiers_inside: false,
3361 trailing_comments: vec![],
3362 inferred_type: None,
3363 }));
3364
3365 Some(Expression::Alias(Box::new(Alias {
3367 this: subquery,
3368 alias: Identifier::new("_unnested_generate_series".to_string()),
3369 column_aliases: vec![],
3370 alias_explicit_as: false,
3371 alias_keyword: None,
3372 pre_alias_comments: vec![],
3373 trailing_comments: vec![],
3374 inferred_type: None,
3375 })))
3376}
3377
3378pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
3386 match expr {
3387 Expression::Delete(mut delete) => {
3388 if let Some(ref mut where_clause) = delete.where_clause {
3390 where_clause.this = expand_between_recursive(where_clause.this.clone());
3391 }
3392 Ok(Expression::Delete(delete))
3393 }
3394 other => Ok(other),
3395 }
3396}
3397
3398fn expand_between_recursive(expr: Expression) -> Expression {
3400 match expr {
3401 Expression::Between(between) => {
3404 let this = expand_between_recursive(between.this.clone());
3405 let low = expand_between_recursive(between.low);
3406 let high = expand_between_recursive(between.high);
3407
3408 if between.not {
3409 Expression::Or(Box::new(BinaryOp::new(
3411 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
3412 Expression::Gt(Box::new(BinaryOp::new(this, high))),
3413 )))
3414 } else {
3415 Expression::And(Box::new(BinaryOp::new(
3417 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
3418 Expression::Lte(Box::new(BinaryOp::new(this, high))),
3419 )))
3420 }
3421 }
3422
3423 Expression::And(mut op) => {
3425 op.left = expand_between_recursive(op.left);
3426 op.right = expand_between_recursive(op.right);
3427 Expression::And(op)
3428 }
3429 Expression::Or(mut op) => {
3430 op.left = expand_between_recursive(op.left);
3431 op.right = expand_between_recursive(op.right);
3432 Expression::Or(op)
3433 }
3434 Expression::Not(mut op) => {
3435 op.this = expand_between_recursive(op.this);
3436 Expression::Not(op)
3437 }
3438
3439 Expression::Paren(mut paren) => {
3441 paren.this = expand_between_recursive(paren.this);
3442 Expression::Paren(paren)
3443 }
3444
3445 other => other,
3447 }
3448}
3449
3450pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
3459 match expr {
3460 Expression::Select(mut select) => {
3461 if let Some(ref mut with) = select.with {
3462 for cte in &mut with.ctes {
3463 if !cte.columns.is_empty() {
3464 let is_star = matches!(&cte.this, Expression::Select(s) if
3466 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
3467
3468 if is_star {
3469 cte.columns.clear();
3471 continue;
3472 }
3473
3474 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
3476
3477 if let Expression::Select(ref mut inner_select) = cte.this {
3479 let new_exprs: Vec<Expression> = inner_select
3480 .expressions
3481 .drain(..)
3482 .zip(
3483 column_names
3484 .into_iter()
3485 .chain(std::iter::repeat_with(|| Identifier::new(""))),
3486 )
3487 .map(|(expr, col_name)| {
3488 if col_name.name.is_empty() {
3489 return expr;
3490 }
3491 match expr {
3493 Expression::Alias(mut a) => {
3494 a.alias = col_name;
3495 Expression::Alias(a)
3496 }
3497 other => {
3498 Expression::Alias(Box::new(crate::expressions::Alias {
3499 this: other,
3500 alias: col_name,
3501 column_aliases: Vec::new(),
3502 alias_explicit_as: false,
3503 alias_keyword: None,
3504 pre_alias_comments: Vec::new(),
3505 trailing_comments: Vec::new(),
3506 inferred_type: None,
3507 }))
3508 }
3509 }
3510 })
3511 .collect();
3512 inner_select.expressions = new_exprs;
3513 }
3514 }
3515 }
3516 }
3517 Ok(Expression::Select(select))
3518 }
3519 other => Ok(other),
3520 }
3521}
3522
3523pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
3527 match expr {
3528 Expression::Select(mut select) => {
3529 if let Some(ref mut from) = select.from {
3530 for from_item in from.expressions.iter_mut() {
3531 simplify_paren_values_in_from(from_item);
3532 }
3533 }
3534 Ok(Expression::Select(select))
3535 }
3536 other => Ok(other),
3537 }
3538}
3539
3540fn simplify_paren_values_in_from(expr: &mut Expression) {
3541 let replacement = match expr {
3543 Expression::Subquery(ref subquery) => {
3545 if let Expression::Paren(ref paren) = subquery.this {
3546 if matches!(&paren.this, Expression::Values(_)) {
3547 let mut new_sub = subquery.as_ref().clone();
3548 new_sub.this = paren.this.clone();
3549 Some(Expression::Subquery(Box::new(new_sub)))
3550 } else {
3551 None
3552 }
3553 } else {
3554 None
3555 }
3556 }
3557 Expression::Paren(ref outer_paren) => {
3560 if let Expression::Subquery(ref subquery) = outer_paren.this {
3561 if matches!(&subquery.this, Expression::Values(_)) {
3563 Some(outer_paren.this.clone())
3564 }
3565 else if let Expression::Paren(ref paren) = subquery.this {
3567 if matches!(&paren.this, Expression::Values(_)) {
3568 let mut new_sub = subquery.as_ref().clone();
3569 new_sub.this = paren.this.clone();
3570 Some(Expression::Subquery(Box::new(new_sub)))
3571 } else {
3572 None
3573 }
3574 } else {
3575 None
3576 }
3577 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
3578 if matches!(&inner_paren.this, Expression::Values(_)) {
3579 Some(outer_paren.this.clone())
3580 } else {
3581 None
3582 }
3583 } else {
3584 None
3585 }
3586 }
3587 _ => None,
3588 };
3589 if let Some(new_expr) = replacement {
3590 *expr = new_expr;
3591 }
3592}
3593
3594pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
3598 match expr {
3599 Expression::Select(mut select) => {
3600 if let Some(ref mut from) = select.from {
3602 let mut counter = 0usize;
3603 for from_item in from.expressions.iter_mut() {
3604 add_auto_alias_to_from_item(from_item, &mut counter);
3605 }
3606 }
3607 Ok(Expression::Select(select))
3608 }
3609 other => Ok(other),
3610 }
3611}
3612
3613fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
3614 use crate::expressions::Identifier;
3615
3616 match expr {
3617 Expression::Alias(ref mut alias) => {
3618 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
3620 alias.alias = Identifier::new(format!("_t{}", counter));
3621 *counter += 1;
3622 }
3623 }
3624 _ => {}
3625 }
3626}
3627
3628pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
3638 use crate::dialects::transform_recursive;
3639 transform_recursive(expr, &propagate_struct_names_in_expr)
3640}
3641
3642fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
3643 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
3644
3645 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
3647 if elements.len() <= 1 {
3648 return None;
3649 }
3650 if let Some(Expression::Function(ref first_struct)) = elements.first() {
3652 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
3653 let field_names: Vec<Option<String>> = first_struct
3655 .args
3656 .iter()
3657 .map(|arg| {
3658 if let Expression::Alias(a) = arg {
3659 Some(a.alias.name.clone())
3660 } else {
3661 None
3662 }
3663 })
3664 .collect();
3665
3666 if field_names.iter().any(|n| n.is_some()) {
3668 let mut new_elements = Vec::with_capacity(elements.len());
3669 new_elements.push(elements[0].clone());
3670
3671 for elem in &elements[1..] {
3672 if let Expression::Function(ref s) = elem {
3673 if s.name.eq_ignore_ascii_case("STRUCT")
3674 && s.args.len() == field_names.len()
3675 {
3676 let all_unnamed =
3678 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
3679 if all_unnamed {
3680 let new_args: Vec<Expression> = s
3682 .args
3683 .iter()
3684 .zip(field_names.iter())
3685 .map(|(val, name)| {
3686 if let Some(n) = name {
3687 Expression::Alias(Box::new(Alias::new(
3688 val.clone(),
3689 Identifier::new(n.clone()),
3690 )))
3691 } else {
3692 val.clone()
3693 }
3694 })
3695 .collect();
3696 new_elements.push(Expression::Function(Box::new(
3697 Function::new("STRUCT".to_string(), new_args),
3698 )));
3699 continue;
3700 }
3701 }
3702 }
3703 new_elements.push(elem.clone());
3704 }
3705
3706 return Some(new_elements);
3707 }
3708 }
3709 }
3710 None
3711 }
3712
3713 if let Expression::Array(ref arr) = expr {
3715 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3716 return Ok(Expression::Array(Box::new(crate::expressions::Array {
3717 expressions: new_elements,
3718 })));
3719 }
3720 }
3721
3722 if let Expression::ArrayFunc(ref arr) = expr {
3724 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3725 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
3726 expressions: new_elements,
3727 bracket_notation: arr.bracket_notation,
3728 use_list_keyword: arr.use_list_keyword,
3729 })));
3730 }
3731 }
3732
3733 Ok(expr)
3734}
3735
3736pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
3739 use crate::dialects::transform_recursive;
3740 transform_recursive(expr, &unnest_alias_transform_single_select)
3741}
3742
3743pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
3746 use crate::dialects::transform_recursive;
3747 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
3748}
3749
3750fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
3751 if let Expression::Select(mut select) = expr {
3752 if let Some(ref mut from) = select.from {
3753 if from.expressions.len() > 1 {
3754 let mut new_from_exprs = Vec::new();
3755 let mut new_cross_joins = Vec::new();
3756
3757 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3758 if idx == 0 {
3759 new_from_exprs.push(from_item);
3760 } else {
3761 let is_unnest = match &from_item {
3762 Expression::Unnest(_) => true,
3763 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3764 _ => false,
3765 };
3766
3767 if is_unnest {
3768 new_cross_joins.push(crate::expressions::Join {
3769 this: from_item,
3770 on: None,
3771 using: Vec::new(),
3772 kind: JoinKind::Cross,
3773 use_inner_keyword: false,
3774 use_outer_keyword: false,
3775 deferred_condition: false,
3776 join_hint: None,
3777 match_condition: None,
3778 pivots: Vec::new(),
3779 comments: Vec::new(),
3780 nesting_group: 0,
3781 directed: false,
3782 });
3783 } else {
3784 new_from_exprs.push(from_item);
3785 }
3786 }
3787 }
3788
3789 from.expressions = new_from_exprs;
3790 new_cross_joins.append(&mut select.joins);
3791 select.joins = new_cross_joins;
3792 }
3793 }
3794
3795 Ok(Expression::Select(select))
3796 } else {
3797 Ok(expr)
3798 }
3799}
3800
3801pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
3805 use crate::dialects::transform_recursive;
3806 transform_recursive(expr, &wrap_unnest_join_aliases_single)
3807}
3808
3809fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
3810 if let Expression::Select(mut select) = expr {
3811 for join in &mut select.joins {
3813 wrap_unnest_alias_in_join_item(&mut join.this);
3814 }
3815 Ok(Expression::Select(select))
3816 } else {
3817 Ok(expr)
3818 }
3819}
3820
3821fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
3823 use crate::expressions::Identifier;
3824 if let Expression::Alias(alias) = expr {
3825 let is_unnest = match &alias.this {
3827 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
3828 _ => false,
3829 };
3830
3831 if is_unnest && alias.column_aliases.is_empty() {
3832 let original_alias_name = alias.alias.name.clone();
3834 alias.alias = Identifier {
3835 name: "_u".to_string(),
3836 quoted: false,
3837 trailing_comments: Vec::new(),
3838 span: None,
3839 };
3840 alias.column_aliases = vec![Identifier {
3841 name: original_alias_name,
3842 quoted: false,
3843 trailing_comments: Vec::new(),
3844 span: None,
3845 }];
3846 }
3847 }
3848}
3849
3850fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
3851 if let Expression::Select(mut select) = expr {
3852 let mut counter = 0usize;
3853
3854 if let Some(ref mut from) = select.from {
3856 for from_item in from.expressions.iter_mut() {
3858 convert_unnest_alias_in_from(from_item, &mut counter);
3859 }
3860
3861 if from.expressions.len() > 1 {
3863 let mut new_from_exprs = Vec::new();
3864 let mut new_cross_joins = Vec::new();
3865
3866 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3867 if idx == 0 {
3868 new_from_exprs.push(from_item);
3870 } else {
3871 let is_unnest = match &from_item {
3873 Expression::Unnest(_) => true,
3874 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3875 _ => false,
3876 };
3877
3878 if is_unnest {
3879 new_cross_joins.push(crate::expressions::Join {
3881 this: from_item,
3882 on: None,
3883 using: Vec::new(),
3884 kind: JoinKind::Cross,
3885 use_inner_keyword: false,
3886 use_outer_keyword: false,
3887 deferred_condition: false,
3888 join_hint: None,
3889 match_condition: None,
3890 pivots: Vec::new(),
3891 comments: Vec::new(),
3892 nesting_group: 0,
3893 directed: false,
3894 });
3895 } else {
3896 new_from_exprs.push(from_item);
3898 }
3899 }
3900 }
3901
3902 from.expressions = new_from_exprs;
3903 new_cross_joins.append(&mut select.joins);
3905 select.joins = new_cross_joins;
3906 }
3907 }
3908
3909 for join in select.joins.iter_mut() {
3911 convert_unnest_alias_in_from(&mut join.this, &mut counter);
3912 }
3913
3914 Ok(Expression::Select(select))
3915 } else {
3916 Ok(expr)
3917 }
3918}
3919
3920fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
3921 use crate::expressions::Identifier;
3922
3923 if let Expression::Alias(ref mut alias) = expr {
3924 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
3926 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
3927
3928 if is_unnest && alias.column_aliases.is_empty() {
3929 let col_alias = alias.alias.clone();
3931 alias.column_aliases = vec![col_alias];
3932 alias.alias = Identifier::new(format!("_t{}", counter));
3933 *counter += 1;
3934 }
3935 }
3936}
3937
3938pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
3945 use crate::expressions::{Alias, Function};
3946
3947 match expr {
3948 Expression::Select(mut select) => {
3949 let mut new_expressions = Vec::new();
3951 let mut changed = false;
3952
3953 for sel_expr in select.expressions.drain(..) {
3954 if let Expression::Alias(ref alias_box) = sel_expr {
3956 if let Expression::Function(ref func) = alias_box.this {
3957 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3958 let arg = func.args[0].clone();
3959 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
3961 (
3962 alias_box.column_aliases[0].name.clone(),
3963 alias_box.column_aliases[1].name.clone(),
3964 )
3965 } else if !alias_box.alias.is_empty() {
3966 ("pos".to_string(), alias_box.alias.name.clone())
3968 } else {
3969 ("pos".to_string(), "col".to_string())
3970 };
3971
3972 let gen_subscripts = Expression::Function(Box::new(Function::new(
3974 "GENERATE_SUBSCRIPTS".to_string(),
3975 vec![
3976 arg.clone(),
3977 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3978 ],
3979 )));
3980 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3981 gen_subscripts,
3982 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3983 )));
3984 let pos_alias = Expression::Alias(Box::new(Alias {
3985 this: sub_one,
3986 alias: Identifier::new(pos_name),
3987 column_aliases: Vec::new(),
3988 alias_explicit_as: false,
3989 alias_keyword: None,
3990 pre_alias_comments: Vec::new(),
3991 trailing_comments: Vec::new(),
3992 inferred_type: None,
3993 }));
3994
3995 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3997 this: arg,
3998 expressions: Vec::new(),
3999 with_ordinality: false,
4000 alias: None,
4001 offset_alias: None,
4002 }));
4003 let col_alias = Expression::Alias(Box::new(Alias {
4004 this: unnest,
4005 alias: Identifier::new(col_name),
4006 column_aliases: Vec::new(),
4007 alias_explicit_as: false,
4008 alias_keyword: None,
4009 pre_alias_comments: Vec::new(),
4010 trailing_comments: Vec::new(),
4011 inferred_type: None,
4012 }));
4013
4014 new_expressions.push(pos_alias);
4015 new_expressions.push(col_alias);
4016 changed = true;
4017 continue;
4018 }
4019 }
4020 }
4021
4022 if let Expression::Function(ref func) = sel_expr {
4024 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4025 let arg = func.args[0].clone();
4026 let pos_name = "pos";
4027 let col_name = "col";
4028
4029 let gen_subscripts = Expression::Function(Box::new(Function::new(
4031 "GENERATE_SUBSCRIPTS".to_string(),
4032 vec![
4033 arg.clone(),
4034 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4035 ],
4036 )));
4037 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4038 gen_subscripts,
4039 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4040 )));
4041 let pos_alias = Expression::Alias(Box::new(Alias {
4042 this: sub_one,
4043 alias: Identifier::new(pos_name),
4044 column_aliases: Vec::new(),
4045 alias_explicit_as: false,
4046 alias_keyword: None,
4047 pre_alias_comments: Vec::new(),
4048 trailing_comments: Vec::new(),
4049 inferred_type: None,
4050 }));
4051
4052 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4054 this: arg,
4055 expressions: Vec::new(),
4056 with_ordinality: false,
4057 alias: None,
4058 offset_alias: None,
4059 }));
4060 let col_alias = Expression::Alias(Box::new(Alias {
4061 this: unnest,
4062 alias: Identifier::new(col_name),
4063 column_aliases: Vec::new(),
4064 alias_explicit_as: false,
4065 alias_keyword: None,
4066 pre_alias_comments: Vec::new(),
4067 trailing_comments: Vec::new(),
4068 inferred_type: None,
4069 }));
4070
4071 new_expressions.push(pos_alias);
4072 new_expressions.push(col_alias);
4073 changed = true;
4074 continue;
4075 }
4076 }
4077
4078 new_expressions.push(sel_expr);
4080 }
4081
4082 if changed {
4083 select.expressions = new_expressions;
4084 } else {
4085 select.expressions = new_expressions;
4086 }
4087
4088 if let Some(ref mut from) = select.from {
4091 expand_posexplode_in_from_duckdb(from)?;
4092 }
4093
4094 Ok(Expression::Select(select))
4095 }
4096 other => Ok(other),
4097 }
4098}
4099
4100fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
4102 use crate::expressions::{Alias, Function};
4103
4104 let mut new_expressions = Vec::new();
4105 let mut _changed = false;
4106
4107 for table_expr in from.expressions.drain(..) {
4108 if let Expression::Alias(ref alias_box) = table_expr {
4110 if let Expression::Function(ref func) = alias_box.this {
4111 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4112 let arg = func.args[0].clone();
4113 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4114 (
4115 alias_box.column_aliases[0].name.clone(),
4116 alias_box.column_aliases[1].name.clone(),
4117 )
4118 } else {
4119 ("pos".to_string(), "col".to_string())
4120 };
4121
4122 let gen_subscripts = Expression::Function(Box::new(Function::new(
4124 "GENERATE_SUBSCRIPTS".to_string(),
4125 vec![
4126 arg.clone(),
4127 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4128 ],
4129 )));
4130 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4131 gen_subscripts,
4132 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4133 )));
4134 let pos_alias = Expression::Alias(Box::new(Alias {
4135 this: sub_one,
4136 alias: Identifier::new(&pos_name),
4137 column_aliases: Vec::new(),
4138 alias_explicit_as: false,
4139 alias_keyword: None,
4140 pre_alias_comments: Vec::new(),
4141 trailing_comments: Vec::new(),
4142 inferred_type: None,
4143 }));
4144 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4145 this: arg,
4146 expressions: Vec::new(),
4147 with_ordinality: false,
4148 alias: None,
4149 offset_alias: None,
4150 }));
4151 let col_alias = Expression::Alias(Box::new(Alias {
4152 this: unnest,
4153 alias: Identifier::new(&col_name),
4154 column_aliases: Vec::new(),
4155 alias_explicit_as: false,
4156 alias_keyword: None,
4157 pre_alias_comments: Vec::new(),
4158 trailing_comments: Vec::new(),
4159 inferred_type: None,
4160 }));
4161
4162 let mut inner_select = Select::new();
4163 inner_select.expressions = vec![pos_alias, col_alias];
4164
4165 let subquery = Expression::Subquery(Box::new(Subquery {
4166 this: Expression::Select(Box::new(inner_select)),
4167 alias: None,
4168 column_aliases: Vec::new(),
4169 alias_explicit_as: false,
4170 alias_keyword: None,
4171 order_by: None,
4172 limit: None,
4173 offset: None,
4174 distribute_by: None,
4175 sort_by: None,
4176 cluster_by: None,
4177 lateral: false,
4178 modifiers_inside: false,
4179 trailing_comments: Vec::new(),
4180 inferred_type: None,
4181 }));
4182 new_expressions.push(subquery);
4183 _changed = true;
4184 continue;
4185 }
4186 }
4187 }
4188
4189 if let Expression::Function(ref func) = table_expr {
4191 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4192 let arg = func.args[0].clone();
4193
4194 let gen_subscripts = Expression::Function(Box::new(Function::new(
4196 "GENERATE_SUBSCRIPTS".to_string(),
4197 vec![
4198 arg.clone(),
4199 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4200 ],
4201 )));
4202 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4203 gen_subscripts,
4204 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4205 )));
4206 let pos_alias = Expression::Alias(Box::new(Alias {
4207 this: sub_one,
4208 alias: Identifier::new("pos"),
4209 column_aliases: Vec::new(),
4210 alias_explicit_as: false,
4211 alias_keyword: None,
4212 pre_alias_comments: Vec::new(),
4213 trailing_comments: Vec::new(),
4214 inferred_type: None,
4215 }));
4216 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4217 this: arg,
4218 expressions: Vec::new(),
4219 with_ordinality: false,
4220 alias: None,
4221 offset_alias: None,
4222 }));
4223 let col_alias = Expression::Alias(Box::new(Alias {
4224 this: unnest,
4225 alias: Identifier::new("col"),
4226 column_aliases: Vec::new(),
4227 alias_explicit_as: false,
4228 alias_keyword: None,
4229 pre_alias_comments: Vec::new(),
4230 trailing_comments: Vec::new(),
4231 inferred_type: None,
4232 }));
4233
4234 let mut inner_select = Select::new();
4235 inner_select.expressions = vec![pos_alias, col_alias];
4236
4237 let subquery = Expression::Subquery(Box::new(Subquery {
4238 this: Expression::Select(Box::new(inner_select)),
4239 alias: None,
4240 column_aliases: Vec::new(),
4241 alias_explicit_as: false,
4242 alias_keyword: None,
4243 order_by: None,
4244 limit: None,
4245 offset: None,
4246 distribute_by: None,
4247 sort_by: None,
4248 cluster_by: None,
4249 lateral: false,
4250 modifiers_inside: false,
4251 trailing_comments: Vec::new(),
4252 inferred_type: None,
4253 }));
4254 new_expressions.push(subquery);
4255 _changed = true;
4256 continue;
4257 }
4258 }
4259
4260 new_expressions.push(table_expr);
4261 }
4262
4263 from.expressions = new_expressions;
4264 Ok(())
4265}
4266
4267pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
4282 match expr {
4283 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
4284 other => Ok(other),
4285 }
4286}
4287
4288pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
4298 match expr {
4299 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
4300 other => Ok(other),
4301 }
4302}
4303
4304fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
4305 let mut flattened_inputs: Vec<Expression> = Vec::new();
4306 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
4307
4308 for sel_expr in select.expressions.into_iter() {
4309 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
4310
4311 let rewritten = transform_recursive(sel_expr, &|e| {
4312 if let Expression::Lateral(lat) = e {
4313 if let Some(input_expr) = extract_flatten_input(&lat) {
4314 if found_input.borrow().is_none() {
4315 *found_input.borrow_mut() = Some(input_expr);
4316 }
4317 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
4318 }
4319 return Ok(Expression::Lateral(lat));
4320 }
4321 Ok(e)
4322 })?;
4323
4324 if let Some(input) = found_input.into_inner() {
4325 flattened_inputs.push(input);
4326 }
4327 new_selects.push(rewritten);
4328 }
4329
4330 if flattened_inputs.is_empty() {
4331 select.expressions = new_selects;
4332 return Ok(Expression::Select(Box::new(select)));
4333 }
4334
4335 select.expressions = new_selects;
4336
4337 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
4338 let is_first = idx == 0;
4340 let series_alias = if is_first {
4341 "pos".to_string()
4342 } else {
4343 format!("pos_{}", idx + 1)
4344 };
4345 let series_source_alias = if is_first {
4346 "_u".to_string()
4347 } else {
4348 format!("_u_{}", idx * 2 + 1)
4349 };
4350 let unnest_source_alias = if is_first {
4351 "_u_2".to_string()
4352 } else {
4353 format!("_u_{}", idx * 2 + 2)
4354 };
4355 let pos2_alias = if is_first {
4356 "pos_2".to_string()
4357 } else {
4358 format!("{}_2", series_alias)
4359 };
4360 let entity_alias = if is_first {
4361 "entity".to_string()
4362 } else {
4363 format!("entity_{}", idx + 1)
4364 };
4365
4366 let array_size_call = Expression::Function(Box::new(Function::new(
4367 "ARRAY_SIZE".to_string(),
4368 vec![Expression::NamedArgument(Box::new(NamedArgument {
4369 name: Identifier::new("INPUT"),
4370 value: input_expr.clone(),
4371 separator: NamedArgSeparator::DArrow,
4372 }))],
4373 )));
4374
4375 let greatest = Expression::Function(Box::new(Function::new(
4376 "GREATEST".to_string(),
4377 vec![array_size_call.clone()],
4378 )));
4379
4380 let series_end = Expression::Add(Box::new(BinaryOp::new(
4381 Expression::Paren(Box::new(crate::expressions::Paren {
4382 this: Expression::Sub(Box::new(BinaryOp::new(
4383 greatest,
4384 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4385 ))),
4386 trailing_comments: Vec::new(),
4387 })),
4388 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4389 )));
4390
4391 let series_range = Expression::Function(Box::new(Function::new(
4392 "ARRAY_GENERATE_RANGE".to_string(),
4393 vec![
4394 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
4395 series_end,
4396 ],
4397 )));
4398
4399 let series_flatten = Expression::Function(Box::new(Function::new(
4400 "FLATTEN".to_string(),
4401 vec![Expression::NamedArgument(Box::new(NamedArgument {
4402 name: Identifier::new("INPUT"),
4403 value: series_range,
4404 separator: NamedArgSeparator::DArrow,
4405 }))],
4406 )));
4407
4408 let series_table = Expression::Function(Box::new(Function::new(
4409 "TABLE".to_string(),
4410 vec![series_flatten],
4411 )));
4412
4413 let series_alias_expr = Expression::Alias(Box::new(Alias {
4414 this: series_table,
4415 alias: Identifier::new(series_source_alias.clone()),
4416 column_aliases: vec![
4417 Identifier::new("seq"),
4418 Identifier::new("key"),
4419 Identifier::new("path"),
4420 Identifier::new("index"),
4421 Identifier::new(series_alias.clone()),
4422 Identifier::new("this"),
4423 ],
4424 alias_explicit_as: false,
4425 alias_keyword: None,
4426 pre_alias_comments: Vec::new(),
4427 trailing_comments: Vec::new(),
4428 inferred_type: None,
4429 }));
4430
4431 select.joins.push(Join {
4432 this: series_alias_expr,
4433 on: None,
4434 using: Vec::new(),
4435 kind: JoinKind::Cross,
4436 use_inner_keyword: false,
4437 use_outer_keyword: false,
4438 deferred_condition: false,
4439 join_hint: None,
4440 match_condition: None,
4441 pivots: Vec::new(),
4442 comments: Vec::new(),
4443 nesting_group: 0,
4444 directed: false,
4445 });
4446
4447 let entity_flatten = Expression::Function(Box::new(Function::new(
4448 "FLATTEN".to_string(),
4449 vec![Expression::NamedArgument(Box::new(NamedArgument {
4450 name: Identifier::new("INPUT"),
4451 value: input_expr.clone(),
4452 separator: NamedArgSeparator::DArrow,
4453 }))],
4454 )));
4455
4456 let entity_table = Expression::Function(Box::new(Function::new(
4457 "TABLE".to_string(),
4458 vec![entity_flatten],
4459 )));
4460
4461 let entity_alias_expr = Expression::Alias(Box::new(Alias {
4462 this: entity_table,
4463 alias: Identifier::new(unnest_source_alias.clone()),
4464 column_aliases: vec![
4465 Identifier::new("seq"),
4466 Identifier::new("key"),
4467 Identifier::new("path"),
4468 Identifier::new(pos2_alias.clone()),
4469 Identifier::new(entity_alias.clone()),
4470 Identifier::new("this"),
4471 ],
4472 alias_explicit_as: false,
4473 alias_keyword: None,
4474 pre_alias_comments: Vec::new(),
4475 trailing_comments: Vec::new(),
4476 inferred_type: None,
4477 }));
4478
4479 select.joins.push(Join {
4480 this: entity_alias_expr,
4481 on: None,
4482 using: Vec::new(),
4483 kind: JoinKind::Cross,
4484 use_inner_keyword: false,
4485 use_outer_keyword: false,
4486 deferred_condition: false,
4487 join_hint: None,
4488 match_condition: None,
4489 pivots: Vec::new(),
4490 comments: Vec::new(),
4491 nesting_group: 0,
4492 directed: false,
4493 });
4494
4495 let pos_col =
4496 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
4497 let pos2_col =
4498 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
4499
4500 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
4501 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
4502 this: Expression::Sub(Box::new(BinaryOp::new(
4503 array_size_call,
4504 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4505 ))),
4506 trailing_comments: Vec::new(),
4507 }));
4508 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
4509 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
4510 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
4511 let or_cond = Expression::Or(Box::new(BinaryOp::new(
4512 eq,
4513 Expression::Paren(Box::new(crate::expressions::Paren {
4514 this: and_cond,
4515 trailing_comments: Vec::new(),
4516 })),
4517 )));
4518
4519 select.where_clause = Some(match select.where_clause.take() {
4520 Some(existing) => Where {
4521 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
4522 },
4523 None => Where { this: or_cond },
4524 });
4525 }
4526
4527 Ok(Expression::Select(Box::new(select)))
4528}
4529
4530fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
4531 let Expression::Function(f) = lat.this.as_ref() else {
4532 return None;
4533 };
4534 if !f.name.eq_ignore_ascii_case("FLATTEN") {
4535 return None;
4536 }
4537
4538 for arg in &f.args {
4539 if let Expression::NamedArgument(na) = arg {
4540 if na.name.name.eq_ignore_ascii_case("INPUT") {
4541 return Some(na.value.clone());
4542 }
4543 }
4544 }
4545 f.args.first().cloned()
4546}
4547
4548fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
4549 let cond = Expression::Eq(Box::new(BinaryOp::new(
4550 Expression::qualified_column("_u", "pos"),
4551 Expression::qualified_column("_u_2", "pos_2"),
4552 )));
4553 let true_expr = Expression::qualified_column("_u_2", "entity");
4554 let iff_expr = Expression::Function(Box::new(Function::new(
4555 "IFF".to_string(),
4556 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
4557 )));
4558
4559 lat.this = Box::new(iff_expr);
4560 if lat.column_aliases.is_empty() {
4561 lat.column_aliases = vec![
4562 "SEQ".to_string(),
4563 "KEY".to_string(),
4564 "PATH".to_string(),
4565 "INDEX".to_string(),
4566 "VALUE".to_string(),
4567 "THIS".to_string(),
4568 ];
4569 }
4570 lat
4571}
4572
4573struct ExplodeInfo {
4575 arg_sql: String,
4577 explode_alias: String,
4579 pos_alias: String,
4581 unnest_source_alias: String,
4583}
4584
4585fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
4586 let is_presto = matches!(
4587 target,
4588 DialectType::Presto | DialectType::Trino | DialectType::Athena
4589 );
4590 let is_bigquery = matches!(target, DialectType::BigQuery);
4591
4592 if !is_presto && !is_bigquery {
4593 return Ok(Expression::Select(Box::new(select)));
4594 }
4595
4596 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
4598 if !has_explode {
4599 return Ok(Expression::Select(Box::new(select)));
4600 }
4601
4602 let mut taken_select_names = std::collections::HashSet::new();
4604 let mut taken_source_names = std::collections::HashSet::new();
4605
4606 for sel in &select.expressions {
4608 if let Some(name) = get_output_name(sel) {
4609 taken_select_names.insert(name);
4610 }
4611 }
4612
4613 for sel in &select.expressions {
4615 let explode_expr = find_explode_in_expr(sel);
4616 if let Some(arg) = explode_expr {
4617 if let Some(name) = get_output_name(&arg) {
4618 taken_select_names.insert(name);
4619 }
4620 }
4621 }
4622
4623 if let Some(ref from) = select.from {
4625 for from_expr in &from.expressions {
4626 collect_source_names(from_expr, &mut taken_source_names);
4627 }
4628 }
4629 for join in &select.joins {
4631 collect_source_names(&join.this, &mut taken_source_names);
4632 }
4633
4634 let series_alias = new_name(&mut taken_select_names, "pos");
4636
4637 let series_source_alias = new_name(&mut taken_source_names, "_u");
4639
4640 let target_dialect = Dialect::get(target);
4642
4643 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
4645 let mut new_projections: Vec<String> = Vec::new();
4646
4647 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
4648 let explode_data = extract_explode_data(sel_expr);
4649
4650 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
4651 let arg_sql = target_dialect
4653 .generate(&arg_expr)
4654 .unwrap_or_else(|_| "NULL".to_string());
4655
4656 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
4657
4658 let explode_alias = if let Some(ref ea) = explicit_alias {
4659 taken_select_names.remove(ea.as_str());
4662 let name = new_name(&mut taken_select_names, ea);
4664 name
4665 } else {
4666 new_name(&mut taken_select_names, "col")
4667 };
4668
4669 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
4670 taken_select_names.remove(pa.as_str());
4672 let name = new_name(&mut taken_select_names, pa);
4673 name
4674 } else {
4675 new_name(&mut taken_select_names, "pos")
4676 };
4677
4678 if is_presto {
4680 let if_col = format!(
4682 "IF({}.{} = {}.{}, {}.{}) AS {}",
4683 series_source_alias,
4684 series_alias,
4685 unnest_source_alias,
4686 pos_alias,
4687 unnest_source_alias,
4688 explode_alias,
4689 explode_alias
4690 );
4691 new_projections.push(if_col);
4692
4693 if is_posexplode {
4695 let if_pos = format!(
4696 "IF({}.{} = {}.{}, {}.{}) AS {}",
4697 series_source_alias,
4698 series_alias,
4699 unnest_source_alias,
4700 pos_alias,
4701 unnest_source_alias,
4702 pos_alias,
4703 pos_alias
4704 );
4705 new_projections.push(if_pos);
4706 }
4707 } else {
4708 let if_col = format!(
4710 "IF({} = {}, {}, NULL) AS {}",
4711 series_alias, pos_alias, explode_alias, explode_alias
4712 );
4713 new_projections.push(if_col);
4714
4715 if is_posexplode {
4717 let if_pos = format!(
4718 "IF({} = {}, {}, NULL) AS {}",
4719 series_alias, pos_alias, pos_alias, pos_alias
4720 );
4721 new_projections.push(if_pos);
4722 }
4723 }
4724
4725 explode_infos.push(ExplodeInfo {
4726 arg_sql,
4727 explode_alias,
4728 pos_alias,
4729 unnest_source_alias,
4730 });
4731 } else {
4732 let sel_sql = target_dialect
4734 .generate(sel_expr)
4735 .unwrap_or_else(|_| "*".to_string());
4736 new_projections.push(sel_sql);
4737 }
4738 }
4739
4740 if explode_infos.is_empty() {
4741 return Ok(Expression::Select(Box::new(select)));
4742 }
4743
4744 let mut from_parts: Vec<String> = Vec::new();
4746
4747 if let Some(ref from) = select.from {
4749 for from_expr in &from.expressions {
4750 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
4751 from_parts.push(from_sql);
4752 }
4753 }
4754
4755 let size_exprs: Vec<String> = explode_infos
4757 .iter()
4758 .map(|info| {
4759 if is_presto {
4760 format!("CARDINALITY({})", info.arg_sql)
4761 } else {
4762 format!("ARRAY_LENGTH({})", info.arg_sql)
4763 }
4764 })
4765 .collect();
4766
4767 let greatest_arg = if size_exprs.len() == 1 {
4768 size_exprs[0].clone()
4769 } else {
4770 format!("GREATEST({})", size_exprs.join(", "))
4771 };
4772
4773 let series_sql = if is_presto {
4776 if size_exprs.len() == 1 {
4778 format!(
4779 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
4780 greatest_arg, series_source_alias, series_alias
4781 )
4782 } else {
4783 format!(
4785 "UNNEST(SEQUENCE(1, {})) AS {}({})",
4786 greatest_arg, series_source_alias, series_alias
4787 )
4788 }
4789 } else {
4790 if size_exprs.len() == 1 {
4792 format!(
4793 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
4794 greatest_arg, series_alias
4795 )
4796 } else {
4797 format!(
4799 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
4800 greatest_arg, series_alias
4801 )
4802 }
4803 };
4804
4805 let mut cross_joins: Vec<String> = Vec::new();
4809
4810 for info in &explode_infos {
4811 cross_joins.push(format!(
4813 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
4814 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
4815 ));
4816 }
4817
4818 let mut where_conditions: Vec<String> = Vec::new();
4820
4821 for info in &explode_infos {
4822 let size_expr = if is_presto {
4823 format!("CARDINALITY({})", info.arg_sql)
4824 } else {
4825 format!("ARRAY_LENGTH({})", info.arg_sql)
4826 };
4827
4828 let cond = if is_presto {
4829 format!(
4830 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
4831 series_src = series_source_alias,
4832 series_al = series_alias,
4833 unnest_src = info.unnest_source_alias,
4834 pos_al = info.pos_alias,
4835 size = size_expr
4836 )
4837 } else {
4838 format!(
4839 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
4840 series_al = series_alias,
4841 pos_al = info.pos_alias,
4842 size = size_expr
4843 )
4844 };
4845
4846 where_conditions.push(cond);
4847 }
4848
4849 let where_sql = if where_conditions.len() == 1 {
4851 where_conditions[0].clone()
4852 } else {
4853 where_conditions
4854 .iter()
4855 .map(|c| format!("({})", c))
4856 .collect::<Vec<_>>()
4857 .join(" AND ")
4858 };
4859
4860 let select_part = new_projections.join(", ");
4862
4863 let from_and_joins = if from_parts.is_empty() {
4865 format!("FROM {} {}", series_sql, cross_joins.join(" "))
4867 } else {
4868 format!(
4869 "FROM {} {} {}",
4870 from_parts.join(", "),
4871 format!("CROSS JOIN {}", series_sql),
4872 cross_joins.join(" ")
4873 )
4874 };
4875
4876 let full_sql = format!(
4877 "SELECT {} {} WHERE {}",
4878 select_part, from_and_joins, where_sql
4879 );
4880
4881 let generic_dialect = Dialect::get(DialectType::Generic);
4884 let parsed = generic_dialect.parse(&full_sql);
4885 match parsed {
4886 Ok(mut stmts) if !stmts.is_empty() => {
4887 let mut result = stmts.remove(0);
4888
4889 if is_bigquery {
4893 convert_unnest_presto_to_bigquery(&mut result);
4894 }
4895
4896 Ok(result)
4897 }
4898 _ => {
4899 Ok(Expression::Select(Box::new(select)))
4901 }
4902 }
4903}
4904
4905fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
4909 match expr {
4910 Expression::Select(ref mut select) => {
4911 if let Some(ref mut from) = select.from {
4913 for from_item in from.expressions.iter_mut() {
4914 convert_unnest_presto_to_bigquery(from_item);
4915 }
4916 }
4917 for join in select.joins.iter_mut() {
4919 convert_unnest_presto_to_bigquery(&mut join.this);
4920 }
4921 }
4922 Expression::Alias(ref alias) => {
4923 if let Expression::Unnest(ref unnest) = alias.this {
4925 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
4926 let col_alias = alias.column_aliases[0].clone();
4927 let pos_alias = alias.column_aliases[1].clone();
4928 let mut new_unnest = unnest.as_ref().clone();
4929 new_unnest.alias = Some(col_alias);
4930 new_unnest.offset_alias = Some(pos_alias);
4931 *expr = Expression::Unnest(Box::new(new_unnest));
4933 }
4934 }
4935 }
4936 _ => {}
4937 }
4938}
4939
4940fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
4943 if !names.contains(base) {
4944 names.insert(base.to_string());
4945 return base.to_string();
4946 }
4947 let mut i = 2;
4948 loop {
4949 let candidate = format!("{}_{}", base, i);
4950 if !names.contains(&candidate) {
4951 names.insert(candidate.clone());
4952 return candidate;
4953 }
4954 i += 1;
4955 }
4956}
4957
4958fn expr_contains_explode(expr: &Expression) -> bool {
4960 match expr {
4961 Expression::Explode(_) => true,
4962 Expression::ExplodeOuter(_) => true,
4963 Expression::Function(f) => {
4964 let name = f.name.to_uppercase();
4965 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
4966 }
4967 Expression::Alias(a) => expr_contains_explode(&a.this),
4968 _ => false,
4969 }
4970}
4971
4972fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
4974 match expr {
4975 Expression::Explode(uf) => Some(uf.this.clone()),
4976 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
4977 Expression::Function(f) => {
4978 let name = f.name.to_uppercase();
4979 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
4980 Some(f.args[0].clone())
4981 } else {
4982 None
4983 }
4984 }
4985 Expression::Alias(a) => find_explode_in_expr(&a.this),
4986 _ => None,
4987 }
4988}
4989
4990fn extract_explode_data(
4993 expr: &Expression,
4994) -> Option<(bool, Expression, Option<String>, Option<String>)> {
4995 match expr {
4996 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
4998 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
4999 Expression::Function(f) => {
5001 let name = f.name.to_uppercase();
5002 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5003 Some((true, f.args[0].clone(), None, None))
5004 } else {
5005 None
5006 }
5007 }
5008 Expression::Alias(a) => {
5010 match &a.this {
5011 Expression::Explode(uf) => {
5012 let alias = if !a.alias.is_empty() {
5013 Some(a.alias.name.clone())
5014 } else {
5015 None
5016 };
5017 Some((false, uf.this.clone(), alias, None))
5018 }
5019 Expression::ExplodeOuter(uf) => {
5020 let alias = if !a.alias.is_empty() {
5021 Some(a.alias.name.clone())
5022 } else {
5023 None
5024 };
5025 Some((false, uf.this.clone(), alias, None))
5026 }
5027 Expression::Function(f) => {
5028 let name = f.name.to_uppercase();
5029 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5030 if a.column_aliases.len() == 2 {
5032 let pos_alias = a.column_aliases[0].name.clone();
5033 let col_alias = a.column_aliases[1].name.clone();
5034 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
5035 } else if !a.alias.is_empty() {
5036 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
5038 } else {
5039 Some((true, f.args[0].clone(), None, None))
5040 }
5041 } else {
5042 None
5043 }
5044 }
5045 _ => None,
5046 }
5047 }
5048 _ => None,
5049 }
5050}
5051
5052fn get_output_name(expr: &Expression) -> Option<String> {
5054 match expr {
5055 Expression::Alias(a) => {
5056 if !a.alias.is_empty() {
5057 Some(a.alias.name.clone())
5058 } else {
5059 None
5060 }
5061 }
5062 Expression::Column(c) => Some(c.name.name.clone()),
5063 Expression::Identifier(id) => Some(id.name.clone()),
5064 _ => None,
5065 }
5066}
5067
5068fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
5070 match expr {
5071 Expression::Alias(a) => {
5072 if !a.alias.is_empty() {
5073 names.insert(a.alias.name.clone());
5074 }
5075 }
5076 Expression::Subquery(s) => {
5077 if let Some(ref alias) = s.alias {
5078 names.insert(alias.name.clone());
5079 }
5080 }
5081 Expression::Table(t) => {
5082 if let Some(ref alias) = t.alias {
5083 names.insert(alias.name.clone());
5084 } else {
5085 names.insert(t.name.name.clone());
5086 }
5087 }
5088 Expression::Column(c) => {
5089 names.insert(c.name.name.clone());
5090 }
5091 Expression::Identifier(id) => {
5092 names.insert(id.name.clone());
5093 }
5094 _ => {}
5095 }
5096}
5097
5098pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
5101 use crate::dialects::transform_recursive;
5102 transform_recursive(expr, &strip_unnest_column_refs_single)
5103}
5104
5105fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
5106 if let Expression::Select(mut select) = expr {
5107 for join in select.joins.iter_mut() {
5109 strip_unnest_from_expr(&mut join.this);
5110 }
5111 if let Some(ref mut from) = select.from {
5113 for from_item in from.expressions.iter_mut() {
5114 strip_unnest_from_expr(from_item);
5115 }
5116 }
5117 Ok(Expression::Select(select))
5118 } else {
5119 Ok(expr)
5120 }
5121}
5122
5123fn strip_unnest_from_expr(expr: &mut Expression) {
5126 if let Expression::Alias(ref mut alias) = expr {
5127 if let Expression::Unnest(ref unnest) = alias.this {
5128 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
5129 if is_column_ref {
5130 let inner = unnest.this.clone();
5132 alias.this = inner;
5133 }
5134 }
5135 }
5136}
5137
5138pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
5141 use crate::dialects::transform_recursive;
5142 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
5143}
5144
5145fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
5146 if let Expression::Select(mut select) = expr {
5147 if let Some(ref mut from) = select.from {
5149 for from_item in from.expressions.iter_mut() {
5150 try_wrap_unnest_in_subquery(from_item);
5151 }
5152 }
5153
5154 for join in select.joins.iter_mut() {
5156 try_wrap_unnest_in_subquery(&mut join.this);
5157 }
5158
5159 Ok(Expression::Select(select))
5160 } else {
5161 Ok(expr)
5162 }
5163}
5164
5165fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
5167 match expr {
5168 Expression::Array(arr) => arr
5170 .expressions
5171 .iter()
5172 .any(|e| matches!(e, Expression::Struct(_))),
5173 Expression::ArrayFunc(arr) => arr
5174 .expressions
5175 .iter()
5176 .any(|e| matches!(e, Expression::Struct(_))),
5177 Expression::Cast(c) => {
5179 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
5180 }
5181 _ => false,
5182 }
5183}
5184
5185fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
5188 if let Expression::Alias(ref alias) = expr {
5190 if let Expression::Unnest(ref unnest) = alias.this {
5191 if is_struct_array_unnest_arg(&unnest.this) {
5192 let unnest_clone = (**unnest).clone();
5193 let alias_name = alias.alias.clone();
5194 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
5195 *expr = new_expr;
5196 return;
5197 }
5198 }
5199 }
5200
5201 if let Expression::Unnest(ref unnest) = expr {
5203 if is_struct_array_unnest_arg(&unnest.this) {
5204 let unnest_clone = (**unnest).clone();
5205 let new_expr = make_unnest_subquery(unnest_clone, None);
5206 *expr = new_expr;
5207 }
5208 }
5209}
5210
5211fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
5213 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
5215 name: Identifier::new("max_depth".to_string()),
5216 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
5217 separator: NamedArgSeparator::DArrow,
5218 }));
5219
5220 let mut unnest_args = vec![unnest.this];
5221 unnest_args.extend(unnest.expressions);
5222 unnest_args.push(max_depth_arg);
5223
5224 let unnest_func =
5225 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
5226
5227 let mut inner_select = Select::new();
5229 inner_select.expressions = vec![unnest_func];
5230 let inner_select = Expression::Select(Box::new(inner_select));
5231
5232 let subquery = Subquery {
5234 this: inner_select,
5235 alias,
5236 column_aliases: Vec::new(),
5237 alias_explicit_as: false,
5238 alias_keyword: None,
5239 order_by: None,
5240 limit: None,
5241 offset: None,
5242 distribute_by: None,
5243 sort_by: None,
5244 cluster_by: None,
5245 lateral: false,
5246 modifiers_inside: false,
5247 trailing_comments: Vec::new(),
5248 inferred_type: None,
5249 };
5250
5251 Expression::Subquery(Box::new(subquery))
5252}
5253
5254pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
5266 use crate::expressions::{Limit as LimitClause, Offset as OffsetClause, OrderBy, Star};
5267
5268 match expr {
5269 Expression::Union(mut u) => {
5270 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
5273 if let Expression::Select(ref mut right_select) = u.right {
5275 if right_select.order_by.is_some()
5276 || right_select.limit.is_some()
5277 || right_select.offset.is_some()
5278 {
5279 u.order_by = right_select.order_by.take();
5281 u.limit = right_select.limit.take().map(|l| Box::new(l.this));
5282 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
5283 }
5284 }
5285 }
5286
5287 let has_order_or_limit =
5288 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
5289 if has_order_or_limit {
5290 let order_by: Option<OrderBy> = u.order_by.take();
5292 let union_limit: Option<Box<Expression>> = u.limit.take();
5293 let union_offset: Option<Box<Expression>> = u.offset.take();
5294
5295 let select_limit: Option<LimitClause> = union_limit.map(|l| LimitClause {
5297 this: *l,
5298 percent: false,
5299 comments: Vec::new(),
5300 });
5301
5302 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
5304 this: *o,
5305 rows: None,
5306 });
5307
5308 let subquery = Subquery {
5310 this: Expression::Union(u),
5311 alias: Some(Identifier::new("_l_0")),
5312 column_aliases: Vec::new(),
5313 alias_explicit_as: true,
5314 alias_keyword: None,
5315 lateral: false,
5316 modifiers_inside: false,
5317 order_by: None,
5318 limit: None,
5319 offset: None,
5320 distribute_by: None,
5321 sort_by: None,
5322 cluster_by: None,
5323 trailing_comments: Vec::new(),
5324 inferred_type: None,
5325 };
5326
5327 let mut select = Select::default();
5329 select.expressions = vec![Expression::Star(Star {
5330 table: None,
5331 except: None,
5332 replace: None,
5333 rename: None,
5334 trailing_comments: Vec::new(),
5335 span: None,
5336 })];
5337 select.from = Some(From {
5338 expressions: vec![Expression::Subquery(Box::new(subquery))],
5339 });
5340 select.order_by = order_by;
5341 select.limit = select_limit;
5342 select.offset = select_offset;
5343
5344 Ok(Expression::Select(Box::new(select)))
5345 } else {
5346 Ok(Expression::Union(u))
5347 }
5348 }
5349 _ => Ok(expr),
5350 }
5351}
5352
5353pub fn expand_like_any(expr: Expression) -> Result<Expression> {
5361 use crate::expressions::{BinaryOp, LikeOp, Paren};
5362
5363 const LIKE_ALL_MARKER: &str = "__LIKE_ALL_EXPANSION__";
5366
5367 fn unwrap_parens(e: &Expression) -> &Expression {
5368 match e {
5369 Expression::Paren(p) => unwrap_parens(&p.this),
5370 _ => e,
5371 }
5372 }
5373
5374 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
5375 let inner = unwrap_parens(e);
5376 match inner {
5377 Expression::Tuple(t) => Some(t.expressions.clone()),
5378 _ if !matches!(e, Expression::Tuple(_)) => Some(vec![inner.clone()]),
5380 _ => None,
5381 }
5382 }
5383
5384 fn expand_like_quantifier(
5386 op: &LikeOp,
5387 values: Vec<Expression>,
5388 is_ilike: bool,
5389 combiner: fn(Expression, Expression) -> Expression,
5390 wrap_marker: bool,
5391 ) -> Expression {
5392 let num_values = values.len();
5393 let mut result: Option<Expression> = None;
5394 for val in values {
5395 let like = if is_ilike {
5396 Expression::ILike(Box::new(LikeOp {
5397 left: op.left.clone(),
5398 right: val,
5399 escape: op.escape.clone(),
5400 quantifier: None,
5401 inferred_type: None,
5402 }))
5403 } else {
5404 Expression::Like(Box::new(LikeOp {
5405 left: op.left.clone(),
5406 right: val,
5407 escape: op.escape.clone(),
5408 quantifier: None,
5409 inferred_type: None,
5410 }))
5411 };
5412 result = Some(match result {
5413 None => like,
5414 Some(prev) => combiner(prev, like),
5415 });
5416 }
5417 let expanded = result.unwrap_or_else(|| unreachable!("values is non-empty"));
5418 if wrap_marker && num_values > 1 {
5422 Expression::Paren(Box::new(Paren {
5423 this: expanded,
5424 trailing_comments: vec![LIKE_ALL_MARKER.to_string()],
5425 }))
5426 } else {
5427 expanded
5428 }
5429 }
5430
5431 fn or_combiner(a: Expression, b: Expression) -> Expression {
5432 Expression::Or(Box::new(BinaryOp::new(a, b)))
5433 }
5434
5435 fn and_combiner(a: Expression, b: Expression) -> Expression {
5436 Expression::And(Box::new(BinaryOp::new(a, b)))
5437 }
5438
5439 fn is_like_all_marker(p: &Paren) -> bool {
5440 p.trailing_comments.len() == 1 && p.trailing_comments[0] == LIKE_ALL_MARKER
5441 }
5442
5443 let result = transform_recursive(expr, &|e| {
5451 match e {
5452 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
5454 if let Some(values) = extract_tuple_values(&op.right) {
5455 if values.is_empty() {
5456 return Ok(e);
5457 }
5458 Ok(expand_like_quantifier(
5459 op,
5460 values,
5461 false,
5462 or_combiner,
5463 false,
5464 ))
5465 } else {
5466 Ok(e)
5467 }
5468 }
5469 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ALL") => {
5471 if let Some(values) = extract_tuple_values(&op.right) {
5472 if values.is_empty() {
5473 return Ok(e);
5474 }
5475 Ok(expand_like_quantifier(
5476 op,
5477 values,
5478 false,
5479 and_combiner,
5480 true,
5481 ))
5482 } else {
5483 Ok(e)
5484 }
5485 }
5486 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
5488 if let Some(values) = extract_tuple_values(&op.right) {
5489 if values.is_empty() {
5490 return Ok(e);
5491 }
5492 Ok(expand_like_quantifier(op, values, true, or_combiner, false))
5493 } else {
5494 Ok(e)
5495 }
5496 }
5497 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ALL") => {
5499 if let Some(values) = extract_tuple_values(&op.right) {
5500 if values.is_empty() {
5501 return Ok(e);
5502 }
5503 Ok(expand_like_quantifier(op, values, true, and_combiner, true))
5504 } else {
5505 Ok(e)
5506 }
5507 }
5508 Expression::And(mut op) => {
5513 if matches!(&op.left, Expression::Or(_)) {
5514 op.left = Expression::Paren(Box::new(Paren {
5515 this: op.left,
5516 trailing_comments: vec![],
5517 }));
5518 }
5519 if matches!(&op.right, Expression::Or(_)) {
5520 op.right = Expression::Paren(Box::new(Paren {
5521 this: op.right,
5522 trailing_comments: vec![],
5523 }));
5524 }
5525 Ok(Expression::And(op))
5526 }
5527 Expression::Or(mut op) => {
5530 if let Expression::Paren(ref mut p) = op.left {
5531 if is_like_all_marker(p) {
5532 p.trailing_comments.clear();
5533 }
5534 }
5535 if let Expression::Paren(ref mut p) = op.right {
5536 if is_like_all_marker(p) {
5537 p.trailing_comments.clear();
5538 }
5539 }
5540 Ok(Expression::Or(op))
5541 }
5542 _ => Ok(e),
5543 }
5544 })?;
5545
5546 transform_recursive(result, &|e| {
5550 if let Expression::Paren(p) = &e {
5551 if is_like_all_marker(p) {
5552 let Expression::Paren(p) = e else {
5553 unreachable!()
5554 };
5555 return Ok(p.this);
5556 }
5557 }
5558 Ok(e)
5559 })
5560}
5561
5562pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
5570 use crate::expressions::Alias;
5571
5572 fn add_self_aliases_to_select(select: &mut Select) {
5573 let new_expressions: Vec<Expression> = select
5574 .expressions
5575 .iter()
5576 .map(|e| {
5577 match e {
5578 Expression::Column(col) => {
5580 let alias_name = col.name.clone();
5581 Expression::Alias(Box::new(Alias {
5582 this: e.clone(),
5583 alias: alias_name,
5584 column_aliases: Vec::new(),
5585 alias_explicit_as: false,
5586 alias_keyword: None,
5587 pre_alias_comments: Vec::new(),
5588 trailing_comments: Vec::new(),
5589 inferred_type: None,
5590 }))
5591 }
5592 _ => e.clone(),
5594 }
5595 })
5596 .collect();
5597 select.expressions = new_expressions;
5598 }
5599
5600 fn walk_and_qualify(expr: &mut Expression) {
5601 match expr {
5602 Expression::Select(ref mut select) => {
5603 if let Some(ref mut from) = select.from {
5605 for e in from.expressions.iter_mut() {
5606 qualify_subquery_expr(e);
5607 walk_and_qualify(e);
5608 }
5609 }
5610 for join in select.joins.iter_mut() {
5612 qualify_subquery_expr(&mut join.this);
5613 walk_and_qualify(&mut join.this);
5614 }
5615 for e in select.expressions.iter_mut() {
5617 walk_and_qualify(e);
5618 }
5619 if let Some(ref mut w) = select.where_clause {
5621 walk_and_qualify(&mut w.this);
5622 }
5623 }
5624 Expression::Subquery(ref mut subquery) => {
5625 walk_and_qualify(&mut subquery.this);
5626 }
5627 Expression::Union(ref mut u) => {
5628 walk_and_qualify(&mut u.left);
5629 walk_and_qualify(&mut u.right);
5630 }
5631 Expression::Intersect(ref mut i) => {
5632 walk_and_qualify(&mut i.left);
5633 walk_and_qualify(&mut i.right);
5634 }
5635 Expression::Except(ref mut e) => {
5636 walk_and_qualify(&mut e.left);
5637 walk_and_qualify(&mut e.right);
5638 }
5639 Expression::Cte(ref mut cte) => {
5640 walk_and_qualify(&mut cte.this);
5641 }
5642 _ => {}
5643 }
5644 }
5645
5646 fn qualify_subquery_expr(expr: &mut Expression) {
5647 match expr {
5648 Expression::Subquery(ref mut subquery) => {
5649 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
5651 if let Expression::Select(ref mut inner_select) = subquery.this {
5652 let has_star = inner_select
5654 .expressions
5655 .iter()
5656 .any(|e| matches!(e, Expression::Star(_)));
5657 if !has_star {
5658 add_self_aliases_to_select(inner_select);
5659 }
5660 }
5661 }
5662 walk_and_qualify(&mut subquery.this);
5664 }
5665 Expression::Alias(ref mut alias) => {
5666 qualify_subquery_expr(&mut alias.this);
5667 }
5668 _ => {}
5669 }
5670 }
5671
5672 let mut result = expr;
5673 walk_and_qualify(&mut result);
5674
5675 if let Expression::Select(ref mut select) = result {
5677 if let Some(ref mut with) = select.with {
5678 for cte in with.ctes.iter_mut() {
5679 if cte.columns.is_empty() {
5681 walk_and_qualify(&mut cte.this);
5683 }
5684 }
5685 }
5686 }
5687
5688 Ok(result)
5689}
5690
5691#[cfg(test)]
5692mod tests {
5693 use super::*;
5694 use crate::dialects::{Dialect, DialectType};
5695 use crate::expressions::Column;
5696
5697 fn gen(expr: &Expression) -> String {
5698 let dialect = Dialect::get(DialectType::Generic);
5699 dialect.generate(expr).unwrap()
5700 }
5701
5702 #[test]
5703 fn test_preprocess() {
5704 let expr = Expression::Boolean(BooleanLiteral { value: true });
5705 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
5706 assert!(
5707 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
5708 );
5709 }
5710
5711 #[test]
5712 fn test_preprocess_chain() {
5713 let expr = Expression::Boolean(BooleanLiteral { value: true });
5715 let transforms: Vec<fn(Expression) -> Result<Expression>> =
5717 vec![replace_bool_with_int, replace_int_with_bool];
5718 let result = preprocess(expr, &transforms).unwrap();
5719 if let Expression::Boolean(b) = result {
5722 assert!(b.value);
5723 } else {
5724 panic!("Expected boolean literal");
5725 }
5726 }
5727
5728 #[test]
5729 fn test_unnest_to_explode() {
5730 let unnest = Expression::Unnest(Box::new(UnnestFunc {
5731 this: Expression::boxed_column(Column {
5732 name: Identifier::new("arr".to_string()),
5733 table: None,
5734 join_mark: false,
5735 trailing_comments: vec![],
5736 span: None,
5737 inferred_type: None,
5738 }),
5739 expressions: Vec::new(),
5740 with_ordinality: false,
5741 alias: None,
5742 offset_alias: None,
5743 }));
5744
5745 let result = unnest_to_explode(unnest).unwrap();
5746 assert!(matches!(result, Expression::Explode(_)));
5747 }
5748
5749 #[test]
5750 fn test_explode_to_unnest() {
5751 let explode = Expression::Explode(Box::new(UnaryFunc {
5752 this: Expression::boxed_column(Column {
5753 name: Identifier::new("arr".to_string()),
5754 table: None,
5755 join_mark: false,
5756 trailing_comments: vec![],
5757 span: None,
5758 inferred_type: None,
5759 }),
5760 original_name: None,
5761 inferred_type: None,
5762 }));
5763
5764 let result = explode_to_unnest(explode).unwrap();
5765 assert!(matches!(result, Expression::Unnest(_)));
5766 }
5767
5768 #[test]
5769 fn test_replace_bool_with_int() {
5770 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
5771 let result = replace_bool_with_int(true_expr).unwrap();
5772 if let Expression::Literal(lit) = result {
5773 if let Literal::Number(n) = lit.as_ref() {
5774 assert_eq!(n, "1");
5775 }
5776 } else {
5777 panic!("Expected number literal");
5778 }
5779
5780 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
5781 let result = replace_bool_with_int(false_expr).unwrap();
5782 if let Expression::Literal(lit) = result {
5783 if let Literal::Number(n) = lit.as_ref() {
5784 assert_eq!(n, "0");
5785 }
5786 } else {
5787 panic!("Expected number literal");
5788 }
5789 }
5790
5791 #[test]
5792 fn test_replace_int_with_bool() {
5793 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
5794 let result = replace_int_with_bool(one_expr).unwrap();
5795 if let Expression::Boolean(b) = result {
5796 assert!(b.value);
5797 } else {
5798 panic!("Expected boolean true");
5799 }
5800
5801 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
5802 let result = replace_int_with_bool(zero_expr).unwrap();
5803 if let Expression::Boolean(b) = result {
5804 assert!(!b.value);
5805 } else {
5806 panic!("Expected boolean false");
5807 }
5808
5809 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
5811 let result = replace_int_with_bool(two_expr).unwrap();
5812 assert!(
5813 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
5814 );
5815 }
5816
5817 #[test]
5818 fn test_strip_data_type_params() {
5819 let decimal = DataType::Decimal {
5821 precision: Some(10),
5822 scale: Some(2),
5823 };
5824 let stripped = strip_data_type_params(decimal);
5825 assert_eq!(
5826 stripped,
5827 DataType::Decimal {
5828 precision: None,
5829 scale: None
5830 }
5831 );
5832
5833 let varchar = DataType::VarChar {
5835 length: Some(255),
5836 parenthesized_length: false,
5837 };
5838 let stripped = strip_data_type_params(varchar);
5839 assert_eq!(
5840 stripped,
5841 DataType::VarChar {
5842 length: None,
5843 parenthesized_length: false
5844 }
5845 );
5846
5847 let char_type = DataType::Char { length: Some(10) };
5849 let stripped = strip_data_type_params(char_type);
5850 assert_eq!(stripped, DataType::Char { length: None });
5851
5852 let timestamp = DataType::Timestamp {
5854 precision: Some(6),
5855 timezone: true,
5856 };
5857 let stripped = strip_data_type_params(timestamp);
5858 assert_eq!(
5859 stripped,
5860 DataType::Timestamp {
5861 precision: None,
5862 timezone: true
5863 }
5864 );
5865
5866 let array = DataType::Array {
5868 element_type: Box::new(DataType::VarChar {
5869 length: Some(100),
5870 parenthesized_length: false,
5871 }),
5872 dimension: None,
5873 };
5874 let stripped = strip_data_type_params(array);
5875 assert_eq!(
5876 stripped,
5877 DataType::Array {
5878 element_type: Box::new(DataType::VarChar {
5879 length: None,
5880 parenthesized_length: false
5881 }),
5882 dimension: None,
5883 }
5884 );
5885
5886 let text = DataType::Text;
5888 let stripped = strip_data_type_params(text);
5889 assert_eq!(stripped, DataType::Text);
5890 }
5891
5892 #[test]
5893 fn test_remove_precision_parameterized_types_cast() {
5894 let cast_expr = Expression::Cast(Box::new(Cast {
5896 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5897 to: DataType::Decimal {
5898 precision: Some(10),
5899 scale: Some(2),
5900 },
5901 trailing_comments: vec![],
5902 double_colon_syntax: false,
5903 format: None,
5904 default: None,
5905 inferred_type: None,
5906 }));
5907
5908 let result = remove_precision_parameterized_types(cast_expr).unwrap();
5909 if let Expression::Cast(cast) = result {
5910 assert_eq!(
5911 cast.to,
5912 DataType::Decimal {
5913 precision: None,
5914 scale: None
5915 }
5916 );
5917 } else {
5918 panic!("Expected Cast expression");
5919 }
5920 }
5921
5922 #[test]
5923 fn test_remove_precision_parameterized_types_varchar() {
5924 let cast_expr = Expression::Cast(Box::new(Cast {
5926 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
5927 to: DataType::VarChar {
5928 length: Some(10),
5929 parenthesized_length: false,
5930 },
5931 trailing_comments: vec![],
5932 double_colon_syntax: false,
5933 format: None,
5934 default: None,
5935 inferred_type: None,
5936 }));
5937
5938 let result = remove_precision_parameterized_types(cast_expr).unwrap();
5939 if let Expression::Cast(cast) = result {
5940 assert_eq!(
5941 cast.to,
5942 DataType::VarChar {
5943 length: None,
5944 parenthesized_length: false
5945 }
5946 );
5947 } else {
5948 panic!("Expected Cast expression");
5949 }
5950 }
5951
5952 #[test]
5953 fn test_remove_precision_direct_cast() {
5954 let cast = Expression::Cast(Box::new(Cast {
5958 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5959 to: DataType::Decimal {
5960 precision: Some(10),
5961 scale: Some(2),
5962 },
5963 trailing_comments: vec![],
5964 double_colon_syntax: false,
5965 format: None,
5966 default: None,
5967 inferred_type: None,
5968 }));
5969
5970 let transformed = remove_precision_parameterized_types(cast).unwrap();
5971 let generated = gen(&transformed);
5972
5973 assert!(generated.contains("DECIMAL"));
5975 assert!(!generated.contains("(10"));
5976 }
5977
5978 #[test]
5979 fn test_epoch_cast_to_ts() {
5980 let cast_expr = Expression::Cast(Box::new(Cast {
5982 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
5983 to: DataType::Timestamp {
5984 precision: None,
5985 timezone: false,
5986 },
5987 trailing_comments: vec![],
5988 double_colon_syntax: false,
5989 format: None,
5990 default: None,
5991 inferred_type: None,
5992 }));
5993
5994 let result = epoch_cast_to_ts(cast_expr).unwrap();
5995 if let Expression::Cast(cast) = result {
5996 if let Expression::Literal(lit) = cast.this {
5997 if let Literal::String(s) = lit.as_ref() {
5998 assert_eq!(s, "1970-01-01 00:00:00");
5999 }
6000 } else {
6001 panic!("Expected string literal");
6002 }
6003 } else {
6004 panic!("Expected Cast expression");
6005 }
6006 }
6007
6008 #[test]
6009 fn test_epoch_cast_to_ts_preserves_non_epoch() {
6010 let cast_expr = Expression::Cast(Box::new(Cast {
6012 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
6013 to: DataType::Timestamp {
6014 precision: None,
6015 timezone: false,
6016 },
6017 trailing_comments: vec![],
6018 double_colon_syntax: false,
6019 format: None,
6020 default: None,
6021 inferred_type: None,
6022 }));
6023
6024 let result = epoch_cast_to_ts(cast_expr).unwrap();
6025 if let Expression::Cast(cast) = result {
6026 if let Expression::Literal(lit) = cast.this {
6027 if let Literal::String(s) = lit.as_ref() {
6028 assert_eq!(s, "2024-01-15");
6029 }
6030 } else {
6031 panic!("Expected string literal");
6032 }
6033 } else {
6034 panic!("Expected Cast expression");
6035 }
6036 }
6037
6038 #[test]
6039 fn test_unqualify_columns() {
6040 let col = Expression::boxed_column(Column {
6042 name: Identifier::new("id".to_string()),
6043 table: Some(Identifier::new("users".to_string())),
6044 join_mark: false,
6045 trailing_comments: vec![],
6046 span: None,
6047 inferred_type: None,
6048 });
6049
6050 let result = unqualify_columns(col).unwrap();
6051 if let Expression::Column(c) = result {
6052 assert!(c.table.is_none());
6053 assert_eq!(c.name.name, "id");
6054 } else {
6055 panic!("Expected Column expression");
6056 }
6057 }
6058
6059 #[test]
6060 fn test_is_temporal_type() {
6061 assert!(is_temporal_type(&DataType::Date));
6062 assert!(is_temporal_type(&DataType::Timestamp {
6063 precision: None,
6064 timezone: false
6065 }));
6066 assert!(is_temporal_type(&DataType::Time {
6067 precision: None,
6068 timezone: false
6069 }));
6070 assert!(!is_temporal_type(&DataType::Int {
6071 length: None,
6072 integer_spelling: false
6073 }));
6074 assert!(!is_temporal_type(&DataType::VarChar {
6075 length: None,
6076 parenthesized_length: false
6077 }));
6078 }
6079
6080 #[test]
6081 fn test_eliminate_semi_join_basic() {
6082 use crate::expressions::{Join, TableRef};
6083
6084 let select = Expression::Select(Box::new(Select {
6086 expressions: vec![Expression::boxed_column(Column {
6087 name: Identifier::new("a".to_string()),
6088 table: None,
6089 join_mark: false,
6090 trailing_comments: vec![],
6091 span: None,
6092 inferred_type: None,
6093 })],
6094 from: Some(From {
6095 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
6096 }),
6097 joins: vec![Join {
6098 this: Expression::Table(Box::new(TableRef::new("t2"))),
6099 kind: JoinKind::Semi,
6100 on: Some(Expression::Eq(Box::new(BinaryOp {
6101 left: Expression::boxed_column(Column {
6102 name: Identifier::new("x".to_string()),
6103 table: None,
6104 join_mark: false,
6105 trailing_comments: vec![],
6106 span: None,
6107 inferred_type: None,
6108 }),
6109 right: Expression::boxed_column(Column {
6110 name: Identifier::new("y".to_string()),
6111 table: None,
6112 join_mark: false,
6113 trailing_comments: vec![],
6114 span: None,
6115 inferred_type: None,
6116 }),
6117 left_comments: vec![],
6118 operator_comments: vec![],
6119 trailing_comments: vec![],
6120 inferred_type: None,
6121 }))),
6122 using: vec![],
6123 use_inner_keyword: false,
6124 use_outer_keyword: false,
6125 deferred_condition: false,
6126 join_hint: None,
6127 match_condition: None,
6128 pivots: Vec::new(),
6129 comments: Vec::new(),
6130 nesting_group: 0,
6131 directed: false,
6132 }],
6133 ..Select::new()
6134 }));
6135
6136 let result = eliminate_semi_and_anti_joins(select).unwrap();
6137 if let Expression::Select(s) = result {
6138 assert!(s.joins.is_empty());
6140 assert!(s.where_clause.is_some());
6142 } else {
6143 panic!("Expected Select expression");
6144 }
6145 }
6146
6147 #[test]
6148 fn test_no_ilike_sql() {
6149 use crate::expressions::LikeOp;
6150
6151 let ilike_expr = Expression::ILike(Box::new(LikeOp {
6153 left: Expression::boxed_column(Column {
6154 name: Identifier::new("name".to_string()),
6155 table: None,
6156 join_mark: false,
6157 trailing_comments: vec![],
6158 span: None,
6159 inferred_type: None,
6160 }),
6161 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
6162 escape: None,
6163 quantifier: None,
6164 inferred_type: None,
6165 }));
6166
6167 let result = no_ilike_sql(ilike_expr).unwrap();
6168 if let Expression::Like(like) = result {
6169 if let Expression::Function(f) = &like.left {
6171 assert_eq!(f.name, "LOWER");
6172 } else {
6173 panic!("Expected LOWER function on left");
6174 }
6175 if let Expression::Function(f) = &like.right {
6177 assert_eq!(f.name, "LOWER");
6178 } else {
6179 panic!("Expected LOWER function on right");
6180 }
6181 } else {
6182 panic!("Expected Like expression");
6183 }
6184 }
6185
6186 #[test]
6187 fn test_no_trycast_sql() {
6188 let trycast_expr = Expression::TryCast(Box::new(Cast {
6190 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6191 to: DataType::Int {
6192 length: None,
6193 integer_spelling: false,
6194 },
6195 trailing_comments: vec![],
6196 double_colon_syntax: false,
6197 format: None,
6198 default: None,
6199 inferred_type: None,
6200 }));
6201
6202 let result = no_trycast_sql(trycast_expr).unwrap();
6203 assert!(matches!(result, Expression::Cast(_)));
6204 }
6205
6206 #[test]
6207 fn test_no_safe_cast_sql() {
6208 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
6210 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6211 to: DataType::Int {
6212 length: None,
6213 integer_spelling: false,
6214 },
6215 trailing_comments: vec![],
6216 double_colon_syntax: false,
6217 format: None,
6218 default: None,
6219 inferred_type: None,
6220 }));
6221
6222 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
6223 assert!(matches!(result, Expression::Cast(_)));
6224 }
6225
6226 #[test]
6227 fn test_explode_to_unnest_presto() {
6228 let spark = Dialect::get(DialectType::Spark);
6229 let result = spark
6230 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
6231 .unwrap();
6232 assert_eq!(
6233 result[0],
6234 "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))"
6235 );
6236 }
6237
6238 #[test]
6239 fn test_explode_to_unnest_bigquery() {
6240 let spark = Dialect::get(DialectType::Spark);
6241 let result = spark
6242 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
6243 .unwrap();
6244 assert_eq!(
6245 result[0],
6246 "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))"
6247 );
6248 }
6249}