1use crate::dialects::transform_recursive;
10use crate::dialects::{Dialect, DialectType};
11use crate::error::Result;
12use crate::expressions::{
13 Alias, BinaryOp, BooleanLiteral, Cast, DataType, Exists, Expression, From, Function,
14 Identifier, Join, JoinKind, Lateral, LateralView, Literal, NamedArgSeparator, NamedArgument,
15 Over, Select, StructField, Subquery, UnaryFunc, UnnestFunc, Where,
16};
17use std::cell::RefCell;
18
19pub fn preprocess<F>(expr: Expression, transforms: &[F]) -> Result<Expression>
28where
29 F: Fn(Expression) -> Result<Expression>,
30{
31 let mut result = expr;
32 for transform in transforms {
33 result = transform(result)?;
34 }
35 Ok(result)
36}
37
38pub fn unnest_to_explode(expr: Expression) -> Result<Expression> {
42 match expr {
43 Expression::Unnest(unnest) => {
44 Ok(Expression::Explode(Box::new(UnaryFunc::new(unnest.this))))
45 }
46 _ => Ok(expr),
47 }
48}
49
50pub fn unnest_to_explode_select(expr: Expression) -> Result<Expression> {
60 transform_recursive(expr, &unnest_to_explode_select_inner)
61}
62
63fn make_udtf_expr(unnest: &UnnestFunc) -> Expression {
66 let has_multi_expr = !unnest.expressions.is_empty();
67 if has_multi_expr {
68 let mut all_args = vec![unnest.this.clone()];
70 all_args.extend(unnest.expressions.iter().cloned());
71 let arrays_zip =
72 Expression::Function(Box::new(Function::new("ARRAYS_ZIP".to_string(), all_args)));
73 Expression::Function(Box::new(Function::new(
74 "INLINE".to_string(),
75 vec![arrays_zip],
76 )))
77 } else {
78 Expression::Explode(Box::new(UnaryFunc::new(unnest.this.clone())))
80 }
81}
82
83fn unnest_to_explode_select_inner(expr: Expression) -> Result<Expression> {
84 let Expression::Select(mut select) = expr else {
85 return Ok(expr);
86 };
87
88 if let Some(ref mut from) = select.from {
90 if from.expressions.len() >= 1 {
91 let mut new_from_exprs = Vec::new();
92 let mut new_lateral_views = Vec::new();
93 let first_is_unnest = is_unnest_expr(&from.expressions[0]);
94
95 for (idx, from_item) in from.expressions.drain(..).enumerate() {
96 if idx == 0 && first_is_unnest {
97 let replaced = replace_from_unnest(from_item);
100 new_from_exprs.push(replaced);
101 } else if idx > 0 && is_unnest_expr(&from_item) {
102 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(from_item);
104 let udtf = make_udtf_expr(&unnest_func);
105 new_lateral_views.push(LateralView {
106 this: udtf,
107 table_alias: alias_name,
108 column_aliases,
109 outer: false,
110 });
111 } else {
112 new_from_exprs.push(from_item);
113 }
114 }
115
116 from.expressions = new_from_exprs;
117 select.lateral_views.extend(new_lateral_views);
119 }
120 }
121
122 let mut remaining_joins = Vec::new();
124 for join in select.joins.drain(..) {
125 if matches!(join.kind, JoinKind::Cross | JoinKind::Inner) {
126 let (is_unnest, is_lateral) = check_join_unnest(&join.this);
127 if is_unnest {
128 let (lateral_alias, lateral_col_aliases, join_expr) = if is_lateral {
130 if let Expression::Lateral(lat) = join.this {
131 let alias = lat.alias.map(|s| Identifier::new(&s));
133 let col_aliases: Vec<Identifier> = lat
134 .column_aliases
135 .iter()
136 .map(|s| Identifier::new(s))
137 .collect();
138 (alias, col_aliases, *lat.this)
139 } else {
140 (None, Vec::new(), join.this)
141 }
142 } else {
143 (None, Vec::new(), join.this)
144 };
145
146 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(join_expr);
147
148 let final_alias = lateral_alias.or(alias_name);
150 let final_col_aliases = if !lateral_col_aliases.is_empty() {
151 lateral_col_aliases
152 } else {
153 column_aliases
154 };
155
156 let table_alias = final_alias.or_else(|| Some(Identifier::new("unnest")));
158 let col_aliases = if final_col_aliases.is_empty() {
159 vec![Identifier::new("unnest")]
160 } else {
161 final_col_aliases
162 };
163
164 let udtf = make_udtf_expr(&unnest_func);
165 select.lateral_views.push(LateralView {
166 this: udtf,
167 table_alias,
168 column_aliases: col_aliases,
169 outer: false,
170 });
171 } else {
172 remaining_joins.push(join);
173 }
174 } else {
175 remaining_joins.push(join);
176 }
177 }
178 select.joins = remaining_joins;
179
180 Ok(Expression::Select(select))
181}
182
183fn is_unnest_expr(expr: &Expression) -> bool {
185 match expr {
186 Expression::Unnest(_) => true,
187 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
188 _ => false,
189 }
190}
191
192fn check_join_unnest(expr: &Expression) -> (bool, bool) {
194 match expr {
195 Expression::Unnest(_) => (true, false),
196 Expression::Alias(a) => {
197 if matches!(a.this, Expression::Unnest(_)) {
198 (true, false)
199 } else {
200 (false, false)
201 }
202 }
203 Expression::Lateral(lat) => match &*lat.this {
204 Expression::Unnest(_) => (true, true),
205 Expression::Alias(a) => {
206 if matches!(a.this, Expression::Unnest(_)) {
207 (true, true)
208 } else {
209 (false, true)
210 }
211 }
212 _ => (false, true),
213 },
214 _ => (false, false),
215 }
216}
217
218fn replace_from_unnest(from_item: Expression) -> Expression {
220 match from_item {
221 Expression::Alias(mut a) => {
222 if let Expression::Unnest(unnest) = a.this {
223 a.this = make_udtf_expr(&unnest);
224 }
225 Expression::Alias(a)
226 }
227 Expression::Unnest(unnest) => make_udtf_expr(&unnest),
228 other => other,
229 }
230}
231
232fn extract_unnest_info(expr: Expression) -> (Option<Identifier>, Vec<Identifier>, UnnestFunc) {
234 match expr {
235 Expression::Alias(a) => {
236 if let Expression::Unnest(unnest) = a.this {
237 (Some(a.alias), a.column_aliases, *unnest)
238 } else {
239 (
241 Some(a.alias),
242 a.column_aliases,
243 UnnestFunc {
244 this: a.this,
245 expressions: Vec::new(),
246 with_ordinality: false,
247 alias: None,
248 offset_alias: None,
249 },
250 )
251 }
252 }
253 Expression::Unnest(unnest) => {
254 let alias = unnest.alias.clone();
255 (alias, Vec::new(), *unnest)
256 }
257 _ => (
258 None,
259 Vec::new(),
260 UnnestFunc {
261 this: expr,
262 expressions: Vec::new(),
263 with_ordinality: false,
264 alias: None,
265 offset_alias: None,
266 },
267 ),
268 }
269}
270
271pub fn explode_to_unnest(expr: Expression) -> Result<Expression> {
273 match expr {
274 Expression::Explode(explode) => Ok(Expression::Unnest(Box::new(UnnestFunc {
275 this: explode.this,
276 expressions: Vec::new(),
277 with_ordinality: false,
278 alias: None,
279 offset_alias: None,
280 }))),
281 _ => Ok(expr),
282 }
283}
284
285pub fn replace_bool_with_int(expr: Expression) -> Result<Expression> {
289 match expr {
290 Expression::Boolean(b) => {
291 let value = if b.value { "1" } else { "0" };
292 Ok(Expression::Literal(Literal::Number(value.to_string())))
293 }
294 _ => Ok(expr),
295 }
296}
297
298pub fn replace_int_with_bool(expr: Expression) -> Result<Expression> {
302 match expr {
303 Expression::Literal(Literal::Number(n)) if n == "1" || n == "0" => {
304 Ok(Expression::Boolean(BooleanLiteral { value: n == "1" }))
305 }
306 _ => Ok(expr),
307 }
308}
309
310pub fn remove_precision_parameterized_types(expr: Expression) -> Result<Expression> {
315 Ok(strip_type_params_recursive(expr))
316}
317
318fn strip_type_params_recursive(expr: Expression) -> Expression {
320 match expr {
321 Expression::Cast(mut cast) => {
323 cast.to = strip_data_type_params(cast.to);
324 cast.this = strip_type_params_recursive(cast.this);
326 Expression::Cast(cast)
327 }
328 Expression::TryCast(mut try_cast) => {
330 try_cast.to = strip_data_type_params(try_cast.to);
331 try_cast.this = strip_type_params_recursive(try_cast.this);
332 Expression::TryCast(try_cast)
333 }
334 Expression::SafeCast(mut safe_cast) => {
336 safe_cast.to = strip_data_type_params(safe_cast.to);
337 safe_cast.this = strip_type_params_recursive(safe_cast.this);
338 Expression::SafeCast(safe_cast)
339 }
340 _ => expr,
343 }
344}
345
346fn strip_data_type_params(dt: DataType) -> DataType {
348 match dt {
349 DataType::Decimal { .. } => DataType::Decimal {
351 precision: None,
352 scale: None,
353 },
354 DataType::TinyInt { .. } => DataType::TinyInt { length: None },
355 DataType::SmallInt { .. } => DataType::SmallInt { length: None },
356 DataType::Int { .. } => DataType::Int {
357 length: None,
358 integer_spelling: false,
359 },
360 DataType::BigInt { .. } => DataType::BigInt { length: None },
361
362 DataType::Char { .. } => DataType::Char { length: None },
364 DataType::VarChar { .. } => DataType::VarChar {
365 length: None,
366 parenthesized_length: false,
367 },
368
369 DataType::Binary { .. } => DataType::Binary { length: None },
371 DataType::VarBinary { .. } => DataType::VarBinary { length: None },
372
373 DataType::Bit { .. } => DataType::Bit { length: None },
375 DataType::VarBit { .. } => DataType::VarBit { length: None },
376
377 DataType::Time { .. } => DataType::Time {
379 precision: None,
380 timezone: false,
381 },
382 DataType::Timestamp { timezone, .. } => DataType::Timestamp {
383 precision: None,
384 timezone,
385 },
386
387 DataType::Array {
389 element_type,
390 dimension,
391 } => DataType::Array {
392 element_type: Box::new(strip_data_type_params(*element_type)),
393 dimension,
394 },
395
396 DataType::Map {
398 key_type,
399 value_type,
400 } => DataType::Map {
401 key_type: Box::new(strip_data_type_params(*key_type)),
402 value_type: Box::new(strip_data_type_params(*value_type)),
403 },
404
405 DataType::Struct { fields, nested } => DataType::Struct {
407 fields: fields
408 .into_iter()
409 .map(|f| {
410 StructField::with_options(
411 f.name,
412 strip_data_type_params(f.data_type),
413 f.options,
414 )
415 })
416 .collect(),
417 nested,
418 },
419
420 DataType::Vector { element_type, .. } => DataType::Vector {
422 element_type: element_type.map(|et| Box::new(strip_data_type_params(*et))),
423 dimension: None,
424 },
425
426 DataType::Object { fields, modifier } => DataType::Object {
428 fields: fields
429 .into_iter()
430 .map(|(name, ty, not_null)| (name, strip_data_type_params(ty), not_null))
431 .collect(),
432 modifier,
433 },
434
435 other => other,
437 }
438}
439
440pub fn eliminate_qualify(expr: Expression) -> Result<Expression> {
455 match expr {
456 Expression::Select(mut select) => {
457 if let Some(qualify) = select.qualify.take() {
458 let qualify_filter = qualify.this;
465 let window_alias_name = "_w".to_string();
466 let window_alias_ident = Identifier::new(window_alias_name.clone());
467
468 let (window_expr, outer_where) =
471 extract_window_from_condition(qualify_filter.clone(), &window_alias_ident);
472
473 if let Some(win_expr) = window_expr {
474 let window_alias_expr =
476 Expression::Alias(Box::new(crate::expressions::Alias {
477 this: win_expr,
478 alias: window_alias_ident.clone(),
479 column_aliases: vec![],
480 pre_alias_comments: vec![],
481 trailing_comments: vec![],
482 }));
483
484 let outer_exprs: Vec<Expression> = select
488 .expressions
489 .iter()
490 .map(|expr| {
491 if let Expression::Alias(a) = expr {
492 Expression::Column(crate::expressions::Column {
494 name: a.alias.clone(),
495 table: None,
496 join_mark: false,
497 trailing_comments: vec![],
498 })
499 } else {
500 expr.clone()
501 }
502 })
503 .collect();
504 select.expressions.push(window_alias_expr);
505
506 let inner_select = Expression::Select(select);
508 let subquery = Subquery {
509 this: inner_select,
510 alias: Some(Identifier::new("_t".to_string())),
511 column_aliases: vec![],
512 order_by: None,
513 limit: None,
514 offset: None,
515 distribute_by: None,
516 sort_by: None,
517 cluster_by: None,
518 lateral: false,
519 modifiers_inside: false,
520 trailing_comments: vec![],
521 };
522
523 let outer_select = Select {
525 expressions: outer_exprs,
526 from: Some(From {
527 expressions: vec![Expression::Subquery(Box::new(subquery))],
528 }),
529 where_clause: Some(Where { this: outer_where }),
530 ..Select::new()
531 };
532
533 return Ok(Expression::Select(Box::new(outer_select)));
534 } else {
535 let qualify_alias = Expression::Alias(Box::new(crate::expressions::Alias {
537 this: qualify_filter.clone(),
538 alias: window_alias_ident.clone(),
539 column_aliases: vec![],
540 pre_alias_comments: vec![],
541 trailing_comments: vec![],
542 }));
543
544 let original_exprs = select.expressions.clone();
545 select.expressions.push(qualify_alias);
546
547 let inner_select = Expression::Select(select);
548 let subquery = Subquery {
549 this: inner_select,
550 alias: Some(Identifier::new("_t".to_string())),
551 column_aliases: vec![],
552 order_by: None,
553 limit: None,
554 offset: None,
555 distribute_by: None,
556 sort_by: None,
557 cluster_by: None,
558 lateral: false,
559 modifiers_inside: false,
560 trailing_comments: vec![],
561 };
562
563 let outer_select = Select {
564 expressions: original_exprs,
565 from: Some(From {
566 expressions: vec![Expression::Subquery(Box::new(subquery))],
567 }),
568 where_clause: Some(Where {
569 this: Expression::Column(crate::expressions::Column {
570 name: window_alias_ident,
571 table: None,
572 join_mark: false,
573 trailing_comments: vec![],
574 }),
575 }),
576 ..Select::new()
577 };
578
579 return Ok(Expression::Select(Box::new(outer_select)));
580 }
581 }
582 Ok(Expression::Select(select))
583 }
584 other => Ok(other),
585 }
586}
587
588fn extract_window_from_condition(
592 condition: Expression,
593 alias: &Identifier,
594) -> (Option<Expression>, Expression) {
595 let alias_col = Expression::Column(crate::expressions::Column {
596 name: alias.clone(),
597 table: None,
598 join_mark: false,
599 trailing_comments: vec![],
600 });
601
602 match condition {
604 Expression::Eq(ref op) => {
606 if is_window_expr(&op.left) {
607 (
608 Some(op.left.clone()),
609 Expression::Eq(Box::new(BinaryOp {
610 left: alias_col,
611 right: op.right.clone(),
612 ..(**op).clone()
613 })),
614 )
615 } else if is_window_expr(&op.right) {
616 (
617 Some(op.right.clone()),
618 Expression::Eq(Box::new(BinaryOp {
619 left: op.left.clone(),
620 right: alias_col,
621 ..(**op).clone()
622 })),
623 )
624 } else {
625 (None, condition)
626 }
627 }
628 Expression::Neq(ref op) => {
629 if is_window_expr(&op.left) {
630 (
631 Some(op.left.clone()),
632 Expression::Neq(Box::new(BinaryOp {
633 left: alias_col,
634 right: op.right.clone(),
635 ..(**op).clone()
636 })),
637 )
638 } else if is_window_expr(&op.right) {
639 (
640 Some(op.right.clone()),
641 Expression::Neq(Box::new(BinaryOp {
642 left: op.left.clone(),
643 right: alias_col,
644 ..(**op).clone()
645 })),
646 )
647 } else {
648 (None, condition)
649 }
650 }
651 Expression::Lt(ref op) => {
652 if is_window_expr(&op.left) {
653 (
654 Some(op.left.clone()),
655 Expression::Lt(Box::new(BinaryOp {
656 left: alias_col,
657 right: op.right.clone(),
658 ..(**op).clone()
659 })),
660 )
661 } else if is_window_expr(&op.right) {
662 (
663 Some(op.right.clone()),
664 Expression::Lt(Box::new(BinaryOp {
665 left: op.left.clone(),
666 right: alias_col,
667 ..(**op).clone()
668 })),
669 )
670 } else {
671 (None, condition)
672 }
673 }
674 Expression::Lte(ref op) => {
675 if is_window_expr(&op.left) {
676 (
677 Some(op.left.clone()),
678 Expression::Lte(Box::new(BinaryOp {
679 left: alias_col,
680 right: op.right.clone(),
681 ..(**op).clone()
682 })),
683 )
684 } else if is_window_expr(&op.right) {
685 (
686 Some(op.right.clone()),
687 Expression::Lte(Box::new(BinaryOp {
688 left: op.left.clone(),
689 right: alias_col,
690 ..(**op).clone()
691 })),
692 )
693 } else {
694 (None, condition)
695 }
696 }
697 Expression::Gt(ref op) => {
698 if is_window_expr(&op.left) {
699 (
700 Some(op.left.clone()),
701 Expression::Gt(Box::new(BinaryOp {
702 left: alias_col,
703 right: op.right.clone(),
704 ..(**op).clone()
705 })),
706 )
707 } else if is_window_expr(&op.right) {
708 (
709 Some(op.right.clone()),
710 Expression::Gt(Box::new(BinaryOp {
711 left: op.left.clone(),
712 right: alias_col,
713 ..(**op).clone()
714 })),
715 )
716 } else {
717 (None, condition)
718 }
719 }
720 Expression::Gte(ref op) => {
721 if is_window_expr(&op.left) {
722 (
723 Some(op.left.clone()),
724 Expression::Gte(Box::new(BinaryOp {
725 left: alias_col,
726 right: op.right.clone(),
727 ..(**op).clone()
728 })),
729 )
730 } else if is_window_expr(&op.right) {
731 (
732 Some(op.right.clone()),
733 Expression::Gte(Box::new(BinaryOp {
734 left: op.left.clone(),
735 right: alias_col,
736 ..(**op).clone()
737 })),
738 )
739 } else {
740 (None, condition)
741 }
742 }
743 _ if is_window_expr(&condition) => (Some(condition), alias_col),
745 _ => (None, condition),
747 }
748}
749
750fn is_window_expr(expr: &Expression) -> bool {
752 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
753}
754
755pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
774 eliminate_distinct_on_for_dialect(expr, None)
775}
776
777pub fn eliminate_distinct_on_for_dialect(
782 expr: Expression,
783 target: Option<DialectType>,
784) -> Result<Expression> {
785 use crate::expressions::Case;
786
787 if matches!(
789 target,
790 Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)
791 ) {
792 return Ok(expr);
793 }
794
795 enum NullsMode {
800 None, NullsFirst, CaseExpr, }
804
805 let nulls_mode = match target {
806 Some(DialectType::MySQL)
807 | Some(DialectType::StarRocks)
808 | Some(DialectType::SingleStore)
809 | Some(DialectType::TSQL)
810 | Some(DialectType::Fabric) => NullsMode::CaseExpr,
811 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => {
812 NullsMode::None
813 }
814 _ => NullsMode::NullsFirst,
816 };
817
818 match expr {
819 Expression::Select(mut select) => {
820 if let Some(distinct_cols) = select.distinct_on.take() {
821 if !distinct_cols.is_empty() {
822 let row_number_alias = Identifier::new("_row_number".to_string());
824
825 let order_exprs = if let Some(ref order_by) = select.order_by {
827 let mut exprs = order_by.expressions.clone();
828 match nulls_mode {
830 NullsMode::NullsFirst => {
831 for ord in &mut exprs {
832 if ord.desc && ord.nulls_first.is_none() {
833 ord.nulls_first = Some(true);
834 }
835 }
836 }
837 NullsMode::CaseExpr => {
838 let mut new_exprs = Vec::new();
841 for ord in &exprs {
842 if ord.desc && ord.nulls_first.is_none() {
843 let null_check = Expression::Case(Box::new(Case {
845 operand: None,
846 whens: vec![(
847 Expression::IsNull(Box::new(
848 crate::expressions::IsNull {
849 this: ord.this.clone(),
850 not: false,
851 postfix_form: false,
852 },
853 )),
854 Expression::Literal(Literal::Number(
855 "1".to_string(),
856 )),
857 )],
858 else_: Some(Expression::Literal(Literal::Number(
859 "0".to_string(),
860 ))),
861 comments: Vec::new(),
862 }));
863 new_exprs.push(crate::expressions::Ordered {
864 this: null_check,
865 desc: true,
866 nulls_first: None,
867 explicit_asc: false,
868 with_fill: None,
869 });
870 }
871 new_exprs.push(ord.clone());
872 }
873 exprs = new_exprs;
874 }
875 NullsMode::None => {}
876 }
877 exprs
878 } else {
879 distinct_cols
880 .iter()
881 .map(|e| crate::expressions::Ordered {
882 this: e.clone(),
883 desc: false,
884 nulls_first: None,
885 explicit_asc: false,
886 with_fill: None,
887 })
888 .collect()
889 };
890
891 let row_number_func =
893 Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
894 this: Expression::RowNumber(crate::expressions::RowNumber),
895 over: Over {
896 partition_by: distinct_cols,
897 order_by: order_exprs,
898 frame: None,
899 window_name: None,
900 alias: None,
901 },
902 keep: None,
903 }));
904
905 let mut inner_aliased_exprs = Vec::new();
909 let mut outer_select_exprs = Vec::new();
910 for orig_expr in &select.expressions {
911 match orig_expr {
912 Expression::Alias(alias) => {
913 inner_aliased_exprs.push(orig_expr.clone());
915 outer_select_exprs.push(Expression::Column(
916 crate::expressions::Column {
917 name: alias.alias.clone(),
918 table: None,
919 join_mark: false,
920 trailing_comments: vec![],
921 },
922 ));
923 }
924 Expression::Column(col) => {
925 inner_aliased_exprs.push(Expression::Alias(Box::new(
927 crate::expressions::Alias {
928 this: orig_expr.clone(),
929 alias: col.name.clone(),
930 column_aliases: vec![],
931 pre_alias_comments: vec![],
932 trailing_comments: vec![],
933 },
934 )));
935 outer_select_exprs.push(Expression::Column(
936 crate::expressions::Column {
937 name: col.name.clone(),
938 table: None,
939 join_mark: false,
940 trailing_comments: vec![],
941 },
942 ));
943 }
944 _ => {
945 inner_aliased_exprs.push(orig_expr.clone());
947 outer_select_exprs.push(orig_expr.clone());
948 }
949 }
950 }
951
952 let row_number_alias_expr =
954 Expression::Alias(Box::new(crate::expressions::Alias {
955 this: row_number_func,
956 alias: row_number_alias.clone(),
957 column_aliases: vec![],
958 pre_alias_comments: vec![],
959 trailing_comments: vec![],
960 }));
961 inner_aliased_exprs.push(row_number_alias_expr);
962
963 select.expressions = inner_aliased_exprs;
965
966 let _inner_order_by = select.order_by.take();
968
969 select.distinct = false;
971
972 let inner_select = Expression::Select(select);
974 let subquery = Subquery {
975 this: inner_select,
976 alias: Some(Identifier::new("_t".to_string())),
977 column_aliases: vec![],
978 order_by: None,
979 limit: None,
980 offset: None,
981 distribute_by: None,
982 sort_by: None,
983 cluster_by: None,
984 lateral: false,
985 modifiers_inside: false,
986 trailing_comments: vec![],
987 };
988
989 let outer_select = Select {
992 expressions: outer_select_exprs,
993 from: Some(From {
994 expressions: vec![Expression::Subquery(Box::new(subquery))],
995 }),
996 where_clause: Some(Where {
997 this: Expression::Eq(Box::new(BinaryOp {
998 left: Expression::Column(crate::expressions::Column {
999 name: row_number_alias,
1000 table: None,
1001 join_mark: false,
1002 trailing_comments: vec![],
1003 }),
1004 right: Expression::Literal(Literal::Number("1".to_string())),
1005 left_comments: vec![],
1006 operator_comments: vec![],
1007 trailing_comments: vec![],
1008 })),
1009 }),
1010 ..Select::new()
1011 };
1012
1013 return Ok(Expression::Select(Box::new(outer_select)));
1014 }
1015 }
1016 Ok(Expression::Select(select))
1017 }
1018 other => Ok(other),
1019 }
1020}
1021
1022pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
1030 match expr {
1031 Expression::Select(mut select) => {
1032 let mut new_joins = Vec::new();
1033 let mut extra_where_conditions = Vec::new();
1034
1035 for join in select.joins.drain(..) {
1036 match join.kind {
1037 JoinKind::Semi | JoinKind::LeftSemi => {
1038 if let Some(on_condition) = join.on {
1039 let subquery_select = Select {
1041 expressions: vec![Expression::Literal(Literal::Number(
1042 "1".to_string(),
1043 ))],
1044 from: Some(From {
1045 expressions: vec![join.this],
1046 }),
1047 where_clause: Some(Where { this: on_condition }),
1048 ..Select::new()
1049 };
1050
1051 let exists = Expression::Exists(Box::new(Exists {
1052 this: Expression::Subquery(Box::new(Subquery {
1053 this: Expression::Select(Box::new(subquery_select)),
1054 alias: None,
1055 column_aliases: vec![],
1056 order_by: None,
1057 limit: None,
1058 offset: None,
1059 distribute_by: None,
1060 sort_by: None,
1061 cluster_by: None,
1062 lateral: false,
1063 modifiers_inside: false,
1064 trailing_comments: vec![],
1065 })),
1066 not: false,
1067 }));
1068
1069 extra_where_conditions.push(exists);
1070 }
1071 }
1072 JoinKind::Anti | JoinKind::LeftAnti => {
1073 if let Some(on_condition) = join.on {
1074 let subquery_select = Select {
1076 expressions: vec![Expression::Literal(Literal::Number(
1077 "1".to_string(),
1078 ))],
1079 from: Some(From {
1080 expressions: vec![join.this],
1081 }),
1082 where_clause: Some(Where { this: on_condition }),
1083 ..Select::new()
1084 };
1085
1086 let not_exists = Expression::Exists(Box::new(Exists {
1088 this: Expression::Subquery(Box::new(Subquery {
1089 this: Expression::Select(Box::new(subquery_select)),
1090 alias: None,
1091 column_aliases: vec![],
1092 order_by: None,
1093 limit: None,
1094 offset: None,
1095 distribute_by: None,
1096 sort_by: None,
1097 cluster_by: None,
1098 lateral: false,
1099 modifiers_inside: false,
1100 trailing_comments: vec![],
1101 })),
1102 not: true,
1103 }));
1104
1105 extra_where_conditions.push(not_exists);
1106 }
1107 }
1108 _ => {
1109 new_joins.push(join);
1111 }
1112 }
1113 }
1114
1115 select.joins = new_joins;
1116
1117 if !extra_where_conditions.is_empty() {
1119 let combined = extra_where_conditions
1120 .into_iter()
1121 .reduce(|acc, cond| {
1122 Expression::And(Box::new(BinaryOp {
1123 left: acc,
1124 right: cond,
1125 left_comments: vec![],
1126 operator_comments: vec![],
1127 trailing_comments: vec![],
1128 }))
1129 })
1130 .unwrap();
1131
1132 select.where_clause = match select.where_clause {
1133 Some(Where { this: existing }) => Some(Where {
1134 this: Expression::And(Box::new(BinaryOp {
1135 left: existing,
1136 right: combined,
1137 left_comments: vec![],
1138 operator_comments: vec![],
1139 trailing_comments: vec![],
1140 })),
1141 }),
1142 None => Some(Where { this: combined }),
1143 };
1144 }
1145
1146 Ok(Expression::Select(select))
1147 }
1148 other => Ok(other),
1149 }
1150}
1151
1152pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
1170 match expr {
1171 Expression::Select(mut select) => {
1172 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
1174
1175 if let Some(idx) = full_outer_join_idx {
1176 let full_join_count = select
1178 .joins
1179 .iter()
1180 .filter(|j| j.kind == JoinKind::Full)
1181 .count();
1182 if full_join_count != 1 {
1183 return Ok(Expression::Select(select));
1184 }
1185
1186 let mut right_select = select.clone();
1188
1189 let full_join = &select.joins[idx];
1191 let join_condition = full_join.on.clone();
1192
1193 select.joins[idx].kind = JoinKind::Left;
1195
1196 right_select.joins[idx].kind = JoinKind::Right;
1198
1199 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
1201 if !from.expressions.is_empty() {
1202 let anti_subquery = Expression::Select(Box::new(Select {
1203 expressions: vec![Expression::Literal(Literal::Number(
1204 "1".to_string(),
1205 ))],
1206 from: Some(from.clone()),
1207 where_clause: Some(Where {
1208 this: join_cond.clone(),
1209 }),
1210 ..Select::new()
1211 }));
1212
1213 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
1214 this: Expression::Exists(Box::new(Exists {
1215 this: Expression::Subquery(Box::new(Subquery {
1216 this: anti_subquery,
1217 alias: None,
1218 column_aliases: vec![],
1219 order_by: None,
1220 limit: None,
1221 offset: None,
1222 distribute_by: None,
1223 sort_by: None,
1224 cluster_by: None,
1225 lateral: false,
1226 modifiers_inside: false,
1227 trailing_comments: vec![],
1228 })),
1229 not: false,
1230 })),
1231 }));
1232
1233 right_select.where_clause = Some(Where {
1235 this: match right_select.where_clause {
1236 Some(w) => Expression::And(Box::new(BinaryOp {
1237 left: w.this,
1238 right: not_exists,
1239 left_comments: vec![],
1240 operator_comments: vec![],
1241 trailing_comments: vec![],
1242 })),
1243 None => not_exists,
1244 },
1245 });
1246 }
1247 }
1248
1249 right_select.with = None;
1251
1252 let order_by = select.order_by.take();
1254
1255 let union = crate::expressions::Union {
1257 left: Expression::Select(select),
1258 right: Expression::Select(right_select),
1259 all: true, distinct: false,
1261 with: None,
1262 order_by,
1263 limit: None,
1264 offset: None,
1265 distribute_by: None,
1266 sort_by: None,
1267 cluster_by: None,
1268 by_name: false,
1269 side: None,
1270 kind: None,
1271 corresponding: false,
1272 strict: false,
1273 on_columns: Vec::new(),
1274 };
1275
1276 return Ok(Expression::Union(Box::new(union)));
1277 }
1278
1279 Ok(Expression::Select(select))
1280 }
1281 other => Ok(other),
1282 }
1283}
1284
1285pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
1298 match expr {
1299 Expression::Select(mut select) => {
1300 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
1302 let mut has_recursive = false;
1303
1304 collect_nested_ctes(
1305 &Expression::Select(select.clone()),
1306 &mut collected_ctes,
1307 &mut has_recursive,
1308 true,
1309 );
1310
1311 let mut cte_body_collected: Vec<(String, Vec<crate::expressions::Cte>)> = Vec::new();
1314 if let Some(ref with) = select.with {
1315 for cte in &with.ctes {
1316 let mut body_ctes: Vec<crate::expressions::Cte> = Vec::new();
1317 collect_ctes_from_cte_body(&cte.this, &mut body_ctes, &mut has_recursive);
1318 if !body_ctes.is_empty() {
1319 cte_body_collected.push((cte.alias.name.clone(), body_ctes));
1320 }
1321 }
1322 }
1323
1324 let has_subquery_ctes = !collected_ctes.is_empty();
1325 let has_body_ctes = !cte_body_collected.is_empty();
1326
1327 if has_subquery_ctes || has_body_ctes {
1328 strip_nested_with_clauses(&mut select, true);
1330
1331 if has_body_ctes {
1333 if let Some(ref mut with) = select.with {
1334 for cte in with.ctes.iter_mut() {
1335 strip_with_from_cte_body(&mut cte.this);
1336 }
1337 }
1338 }
1339
1340 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
1341 ctes: Vec::new(),
1342 recursive: false,
1343 leading_comments: vec![],
1344 search: None,
1345 });
1346
1347 if has_recursive {
1348 top_with.recursive = true;
1349 }
1350
1351 if has_body_ctes {
1353 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
1354 for mut cte in top_with.ctes.drain(..) {
1355 if let Some(pos) = cte_body_collected
1357 .iter()
1358 .position(|(name, _)| *name == cte.alias.name)
1359 {
1360 let (_, mut nested) = cte_body_collected.remove(pos);
1361 for nested_cte in nested.iter_mut() {
1363 strip_with_from_cte_body(&mut nested_cte.this);
1364 }
1365 new_ctes.extend(nested);
1366 }
1367 strip_with_from_cte_body(&mut cte.this);
1369 new_ctes.push(cte);
1370 }
1371 top_with.ctes = new_ctes;
1372 }
1373
1374 top_with.ctes.extend(collected_ctes);
1376 }
1377
1378 Ok(Expression::Select(select))
1379 }
1380 other => Ok(other),
1381 }
1382}
1383
1384fn collect_ctes_from_cte_body(
1386 expr: &Expression,
1387 collected: &mut Vec<crate::expressions::Cte>,
1388 has_recursive: &mut bool,
1389) {
1390 if let Expression::Select(select) = expr {
1391 if let Some(ref with) = select.with {
1392 if with.recursive {
1393 *has_recursive = true;
1394 }
1395 for cte in &with.ctes {
1396 collect_ctes_from_cte_body(&cte.this, collected, has_recursive);
1398 collected.push(cte.clone());
1400 }
1401 }
1402 }
1403}
1404
1405fn strip_with_from_cte_body(expr: &mut Expression) {
1407 if let Expression::Select(ref mut select) = expr {
1408 select.with = None;
1409 }
1410}
1411
1412fn strip_nested_with_clauses(select: &mut Select, _is_top_level: bool) {
1414 if let Some(ref mut from) = select.from {
1416 for expr in from.expressions.iter_mut() {
1417 strip_with_from_expr(expr);
1418 }
1419 }
1420 for join in select.joins.iter_mut() {
1422 strip_with_from_expr(&mut join.this);
1423 }
1424 for expr in select.expressions.iter_mut() {
1426 strip_with_from_expr(expr);
1427 }
1428 if let Some(ref mut w) = select.where_clause {
1430 strip_with_from_expr(&mut w.this);
1431 }
1432}
1433
1434fn strip_with_from_expr(expr: &mut Expression) {
1435 match expr {
1436 Expression::Subquery(ref mut subquery) => {
1437 strip_with_from_inner_query(&mut subquery.this);
1438 }
1439 Expression::Alias(ref mut alias) => {
1440 strip_with_from_expr(&mut alias.this);
1441 }
1442 Expression::Select(ref mut select) => {
1443 select.with = None;
1445 strip_nested_with_clauses(select, false);
1447 }
1448 _ => {}
1449 }
1450}
1451
1452fn strip_with_from_inner_query(expr: &mut Expression) {
1453 if let Expression::Select(ref mut select) = expr {
1454 select.with = None;
1455 strip_nested_with_clauses(select, false);
1456 }
1457}
1458
1459fn collect_nested_ctes(
1461 expr: &Expression,
1462 collected: &mut Vec<crate::expressions::Cte>,
1463 has_recursive: &mut bool,
1464 is_top_level: bool,
1465) {
1466 match expr {
1467 Expression::Select(select) => {
1468 if !is_top_level {
1470 if let Some(ref with) = select.with {
1471 if with.recursive {
1472 *has_recursive = true;
1473 }
1474 collected.extend(with.ctes.clone());
1475 }
1476 }
1477
1478 if let Some(ref from) = select.from {
1480 for expr in &from.expressions {
1481 collect_nested_ctes(expr, collected, has_recursive, false);
1482 }
1483 }
1484
1485 for join in &select.joins {
1487 collect_nested_ctes(&join.this, collected, has_recursive, false);
1488 }
1489
1490 for sel_expr in &select.expressions {
1492 collect_nested_ctes(sel_expr, collected, has_recursive, false);
1493 }
1494
1495 if let Some(ref where_clause) = select.where_clause {
1497 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
1498 }
1499 }
1500 Expression::Subquery(subquery) => {
1501 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
1503 }
1504 Expression::Alias(alias) => {
1505 collect_nested_ctes(&alias.this, collected, has_recursive, false);
1506 }
1507 _ => {}
1509 }
1510}
1511
1512pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
1528 match expr {
1529 Expression::Select(mut select) => {
1530 if let Some(named_windows) = select.windows.take() {
1531 let window_map: std::collections::HashMap<String, &Over> = named_windows
1533 .iter()
1534 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
1535 .collect();
1536
1537 select.expressions = select
1539 .expressions
1540 .into_iter()
1541 .map(|e| inline_window_refs(e, &window_map))
1542 .collect();
1543 }
1544 Ok(Expression::Select(select))
1545 }
1546 other => Ok(other),
1547 }
1548}
1549
1550fn inline_window_refs(
1552 expr: Expression,
1553 window_map: &std::collections::HashMap<String, &Over>,
1554) -> Expression {
1555 match expr {
1556 Expression::WindowFunction(mut wf) => {
1557 if let Some(ref name) = wf.over.window_name {
1559 let key = name.name.to_lowercase();
1560 if let Some(named_spec) = window_map.get(&key) {
1561 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
1563 wf.over.partition_by = named_spec.partition_by.clone();
1564 }
1565 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
1566 wf.over.order_by = named_spec.order_by.clone();
1567 }
1568 if wf.over.frame.is_none() && named_spec.frame.is_some() {
1569 wf.over.frame = named_spec.frame.clone();
1570 }
1571 wf.over.window_name = None;
1573 }
1574 }
1575 Expression::WindowFunction(wf)
1576 }
1577 Expression::Alias(mut alias) => {
1578 alias.this = inline_window_refs(alias.this, window_map);
1580 Expression::Alias(alias)
1581 }
1582 other => other,
1585 }
1586}
1587
1588pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
1602 match expr {
1603 Expression::Select(mut select) => {
1604 let has_join_marks = select
1606 .where_clause
1607 .as_ref()
1608 .map_or(false, |w| contains_join_mark(&w.this));
1609
1610 if !has_join_marks {
1611 return Ok(Expression::Select(select));
1612 }
1613
1614 let from_tables: Vec<String> = select
1616 .from
1617 .as_ref()
1618 .map(|f| {
1619 f.expressions
1620 .iter()
1621 .filter_map(|e| get_table_name(e))
1622 .collect()
1623 })
1624 .unwrap_or_default();
1625
1626 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
1628 std::collections::HashMap::new();
1629 let mut remaining_conditions: Vec<Expression> = Vec::new();
1630
1631 if let Some(ref where_clause) = select.where_clause {
1632 extract_join_mark_conditions(
1633 &where_clause.this,
1634 &mut join_conditions,
1635 &mut remaining_conditions,
1636 );
1637 }
1638
1639 let mut new_joins = select.joins.clone();
1641 for (table_name, conditions) in join_conditions {
1642 let table_in_from = from_tables.contains(&table_name);
1644
1645 if table_in_from && !conditions.is_empty() {
1646 let combined_condition = conditions.into_iter().reduce(|a, b| {
1648 Expression::And(Box::new(BinaryOp {
1649 left: a,
1650 right: b,
1651 left_comments: vec![],
1652 operator_comments: vec![],
1653 trailing_comments: vec![],
1654 }))
1655 });
1656
1657 if let Some(ref mut from) = select.from {
1659 if let Some(pos) = from
1660 .expressions
1661 .iter()
1662 .position(|e| get_table_name(e).map_or(false, |n| n == table_name))
1663 {
1664 if from.expressions.len() > 1 {
1665 let join_table = from.expressions.remove(pos);
1666 new_joins.push(crate::expressions::Join {
1667 this: join_table,
1668 kind: JoinKind::Left,
1669 on: combined_condition,
1670 using: vec![],
1671 use_inner_keyword: false,
1672 use_outer_keyword: true,
1673 deferred_condition: false,
1674 join_hint: None,
1675 match_condition: None,
1676 pivots: Vec::new(),
1677 comments: Vec::new(),
1678 nesting_group: 0,
1679 directed: false,
1680 });
1681 }
1682 }
1683 }
1684 }
1685 }
1686
1687 select.joins = new_joins;
1688
1689 if remaining_conditions.is_empty() {
1691 select.where_clause = None;
1692 } else {
1693 let combined = remaining_conditions.into_iter().reduce(|a, b| {
1694 Expression::And(Box::new(BinaryOp {
1695 left: a,
1696 right: b,
1697 left_comments: vec![],
1698 operator_comments: vec![],
1699 trailing_comments: vec![],
1700 }))
1701 });
1702 select.where_clause = combined.map(|c| Where { this: c });
1703 }
1704
1705 clear_join_marks(&mut Expression::Select(select.clone()));
1707
1708 Ok(Expression::Select(select))
1709 }
1710 other => Ok(other),
1711 }
1712}
1713
1714fn contains_join_mark(expr: &Expression) -> bool {
1716 match expr {
1717 Expression::Column(col) => col.join_mark,
1718 Expression::And(op) | Expression::Or(op) => {
1719 contains_join_mark(&op.left) || contains_join_mark(&op.right)
1720 }
1721 Expression::Eq(op)
1722 | Expression::Neq(op)
1723 | Expression::Lt(op)
1724 | Expression::Lte(op)
1725 | Expression::Gt(op)
1726 | Expression::Gte(op) => contains_join_mark(&op.left) || contains_join_mark(&op.right),
1727 Expression::Not(op) => contains_join_mark(&op.this),
1728 _ => false,
1729 }
1730}
1731
1732fn get_table_name(expr: &Expression) -> Option<String> {
1734 match expr {
1735 Expression::Table(t) => Some(t.name.name.clone()),
1736 Expression::Alias(a) => Some(a.alias.name.clone()),
1737 _ => None,
1738 }
1739}
1740
1741fn extract_join_mark_conditions(
1743 expr: &Expression,
1744 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
1745 remaining: &mut Vec<Expression>,
1746) {
1747 match expr {
1748 Expression::And(op) => {
1749 extract_join_mark_conditions(&op.left, join_conditions, remaining);
1750 extract_join_mark_conditions(&op.right, join_conditions, remaining);
1751 }
1752 _ => {
1753 if let Some(table) = get_join_mark_table(expr) {
1754 join_conditions
1755 .entry(table)
1756 .or_insert_with(Vec::new)
1757 .push(expr.clone());
1758 } else {
1759 remaining.push(expr.clone());
1760 }
1761 }
1762 }
1763}
1764
1765fn get_join_mark_table(expr: &Expression) -> Option<String> {
1767 match expr {
1768 Expression::Eq(op)
1769 | Expression::Neq(op)
1770 | Expression::Lt(op)
1771 | Expression::Lte(op)
1772 | Expression::Gt(op)
1773 | Expression::Gte(op) => {
1774 if let Expression::Column(col) = &op.left {
1776 if col.join_mark {
1777 return col.table.as_ref().map(|t| t.name.clone());
1778 }
1779 }
1780 if let Expression::Column(col) = &op.right {
1781 if col.join_mark {
1782 return col.table.as_ref().map(|t| t.name.clone());
1783 }
1784 }
1785 None
1786 }
1787 _ => None,
1788 }
1789}
1790
1791fn clear_join_marks(expr: &mut Expression) {
1793 match expr {
1794 Expression::Column(col) => col.join_mark = false,
1795 Expression::Select(select) => {
1796 if let Some(ref mut w) = select.where_clause {
1797 clear_join_marks(&mut w.this);
1798 }
1799 for sel_expr in &mut select.expressions {
1800 clear_join_marks(sel_expr);
1801 }
1802 }
1803 Expression::And(op) | Expression::Or(op) => {
1804 clear_join_marks(&mut op.left);
1805 clear_join_marks(&mut op.right);
1806 }
1807 Expression::Eq(op)
1808 | Expression::Neq(op)
1809 | Expression::Lt(op)
1810 | Expression::Lte(op)
1811 | Expression::Gt(op)
1812 | Expression::Gte(op) => {
1813 clear_join_marks(&mut op.left);
1814 clear_join_marks(&mut op.right);
1815 }
1816 _ => {}
1817 }
1818}
1819
1820pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
1827 match expr {
1828 Expression::Select(mut select) => {
1829 if let Some(ref mut with) = select.with {
1830 if with.recursive {
1831 let mut counter = 0;
1832 for cte in &mut with.ctes {
1833 if cte.columns.is_empty() {
1834 if let Expression::Select(ref cte_select) = cte.this {
1836 let names: Vec<Identifier> = cte_select
1837 .expressions
1838 .iter()
1839 .map(|e| match e {
1840 Expression::Alias(a) => a.alias.clone(),
1841 Expression::Column(c) => c.name.clone(),
1842 _ => {
1843 counter += 1;
1844 Identifier::new(format!("_c_{}", counter))
1845 }
1846 })
1847 .collect();
1848 cte.columns = names;
1849 }
1850 }
1851 }
1852 }
1853 }
1854 Ok(Expression::Select(select))
1855 }
1856 other => Ok(other),
1857 }
1858}
1859
1860pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
1867 match expr {
1868 Expression::Cast(mut cast) => {
1869 if let Expression::Literal(Literal::String(ref s)) = cast.this {
1870 if s.to_lowercase() == "epoch" {
1871 if is_temporal_type(&cast.to) {
1872 cast.this =
1873 Expression::Literal(Literal::String("1970-01-01 00:00:00".to_string()));
1874 }
1875 }
1876 }
1877 Ok(Expression::Cast(cast))
1878 }
1879 Expression::TryCast(mut try_cast) => {
1880 if let Expression::Literal(Literal::String(ref s)) = try_cast.this {
1881 if s.to_lowercase() == "epoch" {
1882 if is_temporal_type(&try_cast.to) {
1883 try_cast.this =
1884 Expression::Literal(Literal::String("1970-01-01 00:00:00".to_string()));
1885 }
1886 }
1887 }
1888 Ok(Expression::TryCast(try_cast))
1889 }
1890 other => Ok(other),
1891 }
1892}
1893
1894fn is_temporal_type(dt: &DataType) -> bool {
1896 matches!(
1897 dt,
1898 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
1899 )
1900}
1901
1902pub fn ensure_bools(expr: Expression) -> Result<Expression> {
1927 let expr = ensure_bools_in_case(expr);
1929 match expr {
1930 Expression::Select(mut select) => {
1931 if let Some(ref mut where_clause) = select.where_clause {
1933 where_clause.this = ensure_bool_condition(where_clause.this.clone());
1934 }
1935 if let Some(ref mut having) = select.having {
1937 having.this = ensure_bool_condition(having.this.clone());
1938 }
1939 Ok(Expression::Select(select))
1940 }
1941 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => {
1943 Ok(ensure_bool_condition(expr))
1944 }
1945 other => Ok(other),
1946 }
1947}
1948
1949fn ensure_bools_in_case(expr: Expression) -> Expression {
1953 match expr {
1954 Expression::Case(mut case) => {
1955 case.whens = case
1956 .whens
1957 .into_iter()
1958 .map(|(condition, result)| {
1959 let new_condition = ensure_bool_condition(ensure_bools_in_case(condition));
1960 let new_result = ensure_bools_in_case(result);
1961 (new_condition, new_result)
1962 })
1963 .collect();
1964 if let Some(else_expr) = case.else_ {
1965 case.else_ = Some(ensure_bools_in_case(else_expr));
1966 }
1967 Expression::Case(Box::new(*case))
1968 }
1969 Expression::Select(mut select) => {
1970 select.expressions = select
1972 .expressions
1973 .into_iter()
1974 .map(ensure_bools_in_case)
1975 .collect();
1976 Expression::Select(select)
1978 }
1979 Expression::Alias(mut alias) => {
1980 alias.this = ensure_bools_in_case(alias.this);
1981 Expression::Alias(alias)
1982 }
1983 Expression::Paren(mut paren) => {
1984 paren.this = ensure_bools_in_case(paren.this);
1985 Expression::Paren(paren)
1986 }
1987 other => other,
1988 }
1989}
1990
1991fn is_boolean_expression(expr: &Expression) -> bool {
1994 matches!(
1995 expr,
1996 Expression::Eq(_)
1997 | Expression::Neq(_)
1998 | Expression::Lt(_)
1999 | Expression::Lte(_)
2000 | Expression::Gt(_)
2001 | Expression::Gte(_)
2002 | Expression::Is(_)
2003 | Expression::IsNull(_)
2004 | Expression::IsTrue(_)
2005 | Expression::IsFalse(_)
2006 | Expression::Like(_)
2007 | Expression::ILike(_)
2008 | Expression::SimilarTo(_)
2009 | Expression::Glob(_)
2010 | Expression::RegexpLike(_)
2011 | Expression::In(_)
2012 | Expression::Between(_)
2013 | Expression::Exists(_)
2014 | Expression::And(_)
2015 | Expression::Or(_)
2016 | Expression::Not(_)
2017 | Expression::Any(_)
2018 | Expression::All(_)
2019 | Expression::EqualNull(_)
2020 )
2021}
2022
2023fn wrap_neq_zero(expr: Expression) -> Expression {
2025 Expression::Neq(Box::new(BinaryOp {
2026 left: expr,
2027 right: Expression::Literal(Literal::Number("0".to_string())),
2028 left_comments: vec![],
2029 operator_comments: vec![],
2030 trailing_comments: vec![],
2031 }))
2032}
2033
2034fn ensure_bool_condition(expr: Expression) -> Expression {
2040 match expr {
2041 Expression::And(op) => {
2043 let new_op = BinaryOp {
2044 left: ensure_bool_condition(op.left.clone()),
2045 right: ensure_bool_condition(op.right.clone()),
2046 left_comments: op.left_comments.clone(),
2047 operator_comments: op.operator_comments.clone(),
2048 trailing_comments: op.trailing_comments.clone(),
2049 };
2050 Expression::And(Box::new(new_op))
2051 }
2052 Expression::Or(op) => {
2053 let new_op = BinaryOp {
2054 left: ensure_bool_condition(op.left.clone()),
2055 right: ensure_bool_condition(op.right.clone()),
2056 left_comments: op.left_comments.clone(),
2057 operator_comments: op.operator_comments.clone(),
2058 trailing_comments: op.trailing_comments.clone(),
2059 };
2060 Expression::Or(Box::new(new_op))
2061 }
2062 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
2064 this: ensure_bool_condition(op.this.clone()),
2065 })),
2066 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
2068 this: ensure_bool_condition(paren.this.clone()),
2069 trailing_comments: paren.trailing_comments.clone(),
2070 })),
2071 Expression::Boolean(BooleanLiteral { value: true }) => {
2073 Expression::Paren(Box::new(crate::expressions::Paren {
2074 this: Expression::Eq(Box::new(BinaryOp {
2075 left: Expression::Literal(Literal::Number("1".to_string())),
2076 right: Expression::Literal(Literal::Number("1".to_string())),
2077 left_comments: vec![],
2078 operator_comments: vec![],
2079 trailing_comments: vec![],
2080 })),
2081 trailing_comments: vec![],
2082 }))
2083 }
2084 Expression::Boolean(BooleanLiteral { value: false }) => {
2085 Expression::Paren(Box::new(crate::expressions::Paren {
2086 this: Expression::Eq(Box::new(BinaryOp {
2087 left: Expression::Literal(Literal::Number("1".to_string())),
2088 right: Expression::Literal(Literal::Number("0".to_string())),
2089 left_comments: vec![],
2090 operator_comments: vec![],
2091 trailing_comments: vec![],
2092 })),
2093 trailing_comments: vec![],
2094 }))
2095 }
2096 ref e if is_boolean_expression(e) => expr,
2098 _ => wrap_neq_zero(expr),
2101 }
2102}
2103
2104pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
2110 Ok(unqualify_columns_recursive(expr))
2111}
2112
2113fn unqualify_columns_recursive(expr: Expression) -> Expression {
2115 match expr {
2116 Expression::Column(mut col) => {
2117 col.table = None;
2118 Expression::Column(col)
2119 }
2120 Expression::Select(mut select) => {
2121 select.expressions = select
2122 .expressions
2123 .into_iter()
2124 .map(unqualify_columns_recursive)
2125 .collect();
2126 if let Some(ref mut where_clause) = select.where_clause {
2127 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
2128 }
2129 if let Some(ref mut having) = select.having {
2130 having.this = unqualify_columns_recursive(having.this.clone());
2131 }
2132 if let Some(ref mut group_by) = select.group_by {
2133 group_by.expressions = group_by
2134 .expressions
2135 .iter()
2136 .cloned()
2137 .map(unqualify_columns_recursive)
2138 .collect();
2139 }
2140 if let Some(ref mut order_by) = select.order_by {
2141 order_by.expressions = order_by
2142 .expressions
2143 .iter()
2144 .map(|o| crate::expressions::Ordered {
2145 this: unqualify_columns_recursive(o.this.clone()),
2146 desc: o.desc,
2147 nulls_first: o.nulls_first,
2148 explicit_asc: o.explicit_asc,
2149 with_fill: o.with_fill.clone(),
2150 })
2151 .collect();
2152 }
2153 for join in &mut select.joins {
2154 if let Some(ref mut on) = join.on {
2155 *on = unqualify_columns_recursive(on.clone());
2156 }
2157 }
2158 Expression::Select(select)
2159 }
2160 Expression::Alias(mut alias) => {
2161 alias.this = unqualify_columns_recursive(alias.this);
2162 Expression::Alias(alias)
2163 }
2164 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
2166 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
2167 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
2168 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
2169 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
2170 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
2171 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
2172 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
2173 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
2174 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
2175 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
2176 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
2177 Expression::Function(mut func) => {
2179 func.args = func
2180 .args
2181 .into_iter()
2182 .map(unqualify_columns_recursive)
2183 .collect();
2184 Expression::Function(func)
2185 }
2186 Expression::AggregateFunction(mut func) => {
2187 func.args = func
2188 .args
2189 .into_iter()
2190 .map(unqualify_columns_recursive)
2191 .collect();
2192 Expression::AggregateFunction(func)
2193 }
2194 Expression::Case(mut case) => {
2195 case.whens = case
2196 .whens
2197 .into_iter()
2198 .map(|(cond, result)| {
2199 (
2200 unqualify_columns_recursive(cond),
2201 unqualify_columns_recursive(result),
2202 )
2203 })
2204 .collect();
2205 if let Some(else_expr) = case.else_ {
2206 case.else_ = Some(unqualify_columns_recursive(else_expr));
2207 }
2208 Expression::Case(case)
2209 }
2210 other => other,
2212 }
2213}
2214
2215fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
2217 op.left = unqualify_columns_recursive(op.left);
2218 op.right = unqualify_columns_recursive(op.right);
2219 op
2220}
2221
2222pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
2242 match expr {
2243 Expression::Select(mut select) => {
2244 let mut cte_count = 0;
2245 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2246
2247 if let Some(ref mut with) = select.with {
2249 for cte in &mut with.ctes {
2250 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
2251 }
2252 }
2253
2254 if let Some(ref mut from) = select.from {
2256 for table_expr in &mut from.expressions {
2257 if let Some((cte, replacement)) =
2258 try_convert_generate_date_array(table_expr, &mut cte_count)
2259 {
2260 new_ctes.push(cte);
2261 *table_expr = replacement;
2262 }
2263 }
2264 }
2265
2266 for join in &mut select.joins {
2268 if let Some((cte, replacement)) =
2269 try_convert_generate_date_array(&join.this, &mut cte_count)
2270 {
2271 new_ctes.push(cte);
2272 join.this = replacement;
2273 }
2274 }
2275
2276 if !new_ctes.is_empty() {
2278 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
2279 ctes: Vec::new(),
2280 recursive: true, leading_comments: vec![],
2282 search: None,
2283 });
2284 with_clause.recursive = true;
2285
2286 let mut all_ctes = new_ctes;
2288 all_ctes.append(&mut with_clause.ctes);
2289 with_clause.ctes = all_ctes;
2290 }
2291
2292 Ok(Expression::Select(select))
2293 }
2294 other => Ok(other),
2295 }
2296}
2297
2298fn process_expression_for_gda(
2301 expr: &mut Expression,
2302 cte_count: &mut usize,
2303 new_ctes: &mut Vec<crate::expressions::Cte>,
2304) {
2305 match expr {
2306 Expression::Select(ref mut select) => {
2307 if let Some(ref mut from) = select.from {
2309 for table_expr in &mut from.expressions {
2310 if let Some((cte, replacement)) =
2311 try_convert_generate_date_array(table_expr, cte_count)
2312 {
2313 new_ctes.push(cte);
2314 *table_expr = replacement;
2315 }
2316 }
2317 }
2318 for join in &mut select.joins {
2320 if let Some((cte, replacement)) =
2321 try_convert_generate_date_array(&join.this, cte_count)
2322 {
2323 new_ctes.push(cte);
2324 join.this = replacement;
2325 }
2326 }
2327 }
2328 Expression::Union(ref mut u) => {
2329 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
2330 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
2331 }
2332 Expression::Subquery(ref mut sq) => {
2333 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
2334 }
2335 _ => {}
2336 }
2337}
2338
2339fn try_convert_generate_date_array(
2342 expr: &Expression,
2343 cte_count: &mut usize,
2344) -> Option<(crate::expressions::Cte, Expression)> {
2345 try_convert_generate_date_array_with_name(expr, cte_count, None)
2346}
2347
2348fn try_convert_generate_date_array_with_name(
2349 expr: &Expression,
2350 cte_count: &mut usize,
2351 column_name_override: Option<&str>,
2352) -> Option<(crate::expressions::Cte, Expression)> {
2353 fn extract_gda_args(
2355 inner: &Expression,
2356 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
2357 match inner {
2358 Expression::GenerateDateArray(gda) => {
2359 let start = gda.start.as_ref()?;
2360 let end = gda.end.as_ref()?;
2361 let step = gda.step.as_deref();
2362 Some((start, end, step))
2363 }
2364 Expression::GenerateSeries(gs) => {
2365 let start = gs.start.as_deref()?;
2366 let end = gs.end.as_deref()?;
2367 let step = gs.step.as_deref();
2368 Some((start, end, step))
2369 }
2370 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
2371 if f.args.len() >= 2 {
2372 let start = &f.args[0];
2373 let end = &f.args[1];
2374 let step = f.args.get(2);
2375 Some((start, end, step))
2376 } else {
2377 None
2378 }
2379 }
2380 _ => None,
2381 }
2382 }
2383
2384 if let Expression::Unnest(unnest) = expr {
2386 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
2387 let start = start;
2388 let end = end;
2389 let step: Option<&Expression> = step_opt;
2390
2391 let cte_name = if *cte_count == 0 {
2393 "_generated_dates".to_string()
2394 } else {
2395 format!("_generated_dates_{}", cte_count)
2396 };
2397 *cte_count += 1;
2398
2399 let column_name =
2400 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
2401
2402 let cast_to_date = |expr: &Expression| -> Expression {
2404 match expr {
2405 Expression::Literal(Literal::Date(_)) => {
2406 if let Expression::Literal(Literal::Date(d)) = expr {
2408 Expression::Cast(Box::new(Cast {
2409 this: Expression::Literal(Literal::String(d.clone())),
2410 to: DataType::Date,
2411 trailing_comments: vec![],
2412 double_colon_syntax: false,
2413 format: None,
2414 default: None,
2415 }))
2416 } else {
2417 unreachable!()
2418 }
2419 }
2420 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
2421 _ => Expression::Cast(Box::new(Cast {
2422 this: expr.clone(),
2423 to: DataType::Date,
2424 trailing_comments: vec![],
2425 double_colon_syntax: false,
2426 format: None,
2427 default: None,
2428 })),
2429 }
2430 };
2431
2432 let base_select = Select {
2434 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
2435 this: cast_to_date(start),
2436 alias: column_name.clone(),
2437 column_aliases: vec![],
2438 pre_alias_comments: vec![],
2439 trailing_comments: vec![],
2440 }))],
2441 ..Select::new()
2442 };
2443
2444 let normalize_interval = |expr: &Expression| -> Expression {
2446 if let Expression::Interval(ref iv) = expr {
2447 let mut iv_clone = iv.as_ref().clone();
2448 if let Some(Expression::Literal(Literal::String(ref s))) = iv_clone.this {
2449 if s.parse::<f64>().is_ok() {
2451 iv_clone.this = Some(Expression::Literal(Literal::Number(s.clone())));
2452 }
2453 }
2454 Expression::Interval(Box::new(iv_clone))
2455 } else {
2456 expr.clone()
2457 }
2458 };
2459
2460 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
2463 Expression::Interval(Box::new(crate::expressions::Interval {
2464 this: Some(Expression::Literal(Literal::Number("1".to_string()))),
2465 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
2466 unit: crate::expressions::IntervalUnit::Day,
2467 use_plural: false,
2468 }),
2469 }))
2470 });
2471
2472 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
2474
2475 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
2476 this: Expression::Column(crate::expressions::Column {
2477 name: column_name.clone(),
2478 table: None,
2479 join_mark: false,
2480 trailing_comments: vec![],
2481 }),
2482 interval: add_count,
2483 unit: add_unit,
2484 }));
2485
2486 let cast_date_add = Expression::Cast(Box::new(Cast {
2487 this: date_add_expr.clone(),
2488 to: DataType::Date,
2489 trailing_comments: vec![],
2490 double_colon_syntax: false,
2491 format: None,
2492 default: None,
2493 }));
2494
2495 let recursive_select = Select {
2496 expressions: vec![cast_date_add.clone()],
2497 from: Some(From {
2498 expressions: vec![Expression::Table(crate::expressions::TableRef::new(
2499 &cte_name,
2500 ))],
2501 }),
2502 where_clause: Some(Where {
2503 this: Expression::Lte(Box::new(BinaryOp {
2504 left: cast_date_add,
2505 right: cast_to_date(end),
2506 left_comments: vec![],
2507 operator_comments: vec![],
2508 trailing_comments: vec![],
2509 })),
2510 }),
2511 ..Select::new()
2512 };
2513
2514 let union = crate::expressions::Union {
2516 left: Expression::Select(Box::new(base_select)),
2517 right: Expression::Select(Box::new(recursive_select)),
2518 all: true, distinct: false,
2520 with: None,
2521 order_by: None,
2522 limit: None,
2523 offset: None,
2524 distribute_by: None,
2525 sort_by: None,
2526 cluster_by: None,
2527 by_name: false,
2528 side: None,
2529 kind: None,
2530 corresponding: false,
2531 strict: false,
2532 on_columns: Vec::new(),
2533 };
2534
2535 let cte = crate::expressions::Cte {
2537 this: Expression::Union(Box::new(union)),
2538 alias: Identifier::new(cte_name.clone()),
2539 columns: vec![column_name.clone()],
2540 materialized: None,
2541 key_expressions: Vec::new(),
2542 alias_first: true,
2543 comments: Vec::new(),
2544 };
2545
2546 let replacement_select = Select {
2548 expressions: vec![Expression::Column(crate::expressions::Column {
2549 name: column_name,
2550 table: None,
2551 join_mark: false,
2552 trailing_comments: vec![],
2553 })],
2554 from: Some(From {
2555 expressions: vec![Expression::Table(crate::expressions::TableRef::new(
2556 &cte_name,
2557 ))],
2558 }),
2559 ..Select::new()
2560 };
2561
2562 let replacement = Expression::Subquery(Box::new(Subquery {
2563 this: Expression::Select(Box::new(replacement_select)),
2564 alias: Some(Identifier::new(cte_name)),
2565 column_aliases: vec![],
2566 order_by: None,
2567 limit: None,
2568 offset: None,
2569 distribute_by: None,
2570 sort_by: None,
2571 cluster_by: None,
2572 lateral: false,
2573 modifiers_inside: false,
2574 trailing_comments: vec![],
2575 }));
2576
2577 return Some((cte, replacement));
2578 }
2579 }
2580
2581 if let Expression::Alias(alias) = expr {
2583 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
2585 if let Some((cte, replacement)) =
2586 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
2587 {
2588 if col_name.is_some() {
2591 return Some((cte, replacement));
2592 }
2593 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
2594 this: replacement,
2595 alias: alias.alias.clone(),
2596 column_aliases: alias.column_aliases.clone(),
2597 pre_alias_comments: alias.pre_alias_comments.clone(),
2598 trailing_comments: alias.trailing_comments.clone(),
2599 }));
2600 return Some((cte, new_alias));
2601 }
2602 }
2603
2604 None
2605}
2606
2607fn extract_interval_unit_and_count(
2612 expr: &Expression,
2613) -> (crate::expressions::IntervalUnit, Expression) {
2614 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
2615
2616 if let Expression::Interval(ref iv) = expr {
2617 if let Some(ref unit_spec) = iv.unit {
2619 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
2620 let count = match &iv.this {
2621 Some(e) => e.clone(),
2622 None => Expression::Literal(Literal::Number("1".to_string())),
2623 };
2624 return (unit.clone(), count);
2625 }
2626 }
2627
2628 if let Some(ref val_expr) = iv.this {
2630 match val_expr {
2631 Expression::Literal(Literal::String(s))
2632 | Expression::Literal(Literal::Number(s)) => {
2633 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
2635 if parts.len() == 2 {
2636 let count_str = parts[0].trim();
2637 let unit_str = parts[1].trim().to_uppercase();
2638 let unit = match unit_str.as_str() {
2639 "YEAR" | "YEARS" => IntervalUnit::Year,
2640 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
2641 "MONTH" | "MONTHS" => IntervalUnit::Month,
2642 "WEEK" | "WEEKS" => IntervalUnit::Week,
2643 "DAY" | "DAYS" => IntervalUnit::Day,
2644 "HOUR" | "HOURS" => IntervalUnit::Hour,
2645 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
2646 "SECOND" | "SECONDS" => IntervalUnit::Second,
2647 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
2648 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
2649 _ => IntervalUnit::Day,
2650 };
2651 return (
2652 unit,
2653 Expression::Literal(Literal::Number(count_str.to_string())),
2654 );
2655 }
2656 if s.parse::<f64>().is_ok() {
2658 return (
2659 IntervalUnit::Day,
2660 Expression::Literal(Literal::Number(s.clone())),
2661 );
2662 }
2663 }
2664 _ => {}
2665 }
2666 }
2667
2668 (
2670 IntervalUnit::Day,
2671 Expression::Literal(Literal::Number("1".to_string())),
2672 )
2673 } else {
2674 (
2675 IntervalUnit::Day,
2676 Expression::Literal(Literal::Number("1".to_string())),
2677 )
2678 }
2679}
2680
2681pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
2694 match expr {
2695 Expression::ILike(ilike) => {
2696 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
2698 name: "LOWER".to_string(),
2699 args: vec![ilike.left],
2700 distinct: false,
2701 trailing_comments: vec![],
2702 use_bracket_syntax: false,
2703 no_parens: false,
2704 quoted: false,
2705 }));
2706
2707 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
2708 name: "LOWER".to_string(),
2709 args: vec![ilike.right],
2710 distinct: false,
2711 trailing_comments: vec![],
2712 use_bracket_syntax: false,
2713 no_parens: false,
2714 quoted: false,
2715 }));
2716
2717 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
2718 left: lower_left,
2719 right: lower_right,
2720 escape: ilike.escape,
2721 quantifier: ilike.quantifier,
2722 })))
2723 }
2724 other => Ok(other),
2725 }
2726}
2727
2728pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
2736 match expr {
2737 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
2738 other => Ok(other),
2739 }
2740}
2741
2742pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
2747 match expr {
2748 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
2749 other => Ok(other),
2750 }
2751}
2752
2753pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
2760 Ok(expr)
2762}
2763
2764pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
2778 match expr {
2781 Expression::Table(ref table) => {
2782 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
2785 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2787 this: expr.clone(),
2788 expressions: Vec::new(),
2789 with_ordinality: false,
2790 alias: None,
2791 offset_alias: None,
2792 }));
2793
2794 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
2796 this: unnest,
2797 alias: Identifier::new("_u".to_string()),
2798 column_aliases: vec![],
2799 pre_alias_comments: vec![],
2800 trailing_comments: vec![],
2801 })));
2802 }
2803 Ok(expr)
2804 }
2805 Expression::GenerateSeries(gs) => {
2806 let unnest = Expression::Unnest(Box::new(UnnestFunc {
2808 this: Expression::GenerateSeries(gs),
2809 expressions: Vec::new(),
2810 with_ordinality: false,
2811 alias: None,
2812 offset_alias: None,
2813 }));
2814 Ok(unnest)
2815 }
2816 other => Ok(other),
2817 }
2818}
2819
2820pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
2831 use crate::dialects::transform_recursive;
2832 transform_recursive(expr, &unwrap_unnest_generate_series_single)
2833}
2834
2835fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
2836 use crate::expressions::*;
2837 match expr {
2839 Expression::Select(mut select) => {
2840 if let Some(ref mut from) = select.from {
2842 for table_expr in &mut from.expressions {
2843 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
2844 *table_expr = replacement;
2845 }
2846 }
2847 }
2848 for join in &mut select.joins {
2850 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
2851 join.this = replacement;
2852 }
2853 }
2854 Ok(Expression::Select(select))
2855 }
2856 other => Ok(other),
2857 }
2858}
2859
2860fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
2863 use crate::expressions::*;
2864
2865 let gen_series = match expr {
2867 Expression::Unnest(unnest) => {
2868 if let Expression::GenerateSeries(ref gs) = unnest.this {
2869 Some(gs.as_ref().clone())
2870 } else {
2871 None
2872 }
2873 }
2874 Expression::Alias(alias) => {
2875 if let Expression::Unnest(ref unnest) = alias.this {
2876 if let Expression::GenerateSeries(ref gs) = unnest.this {
2877 Some(gs.as_ref().clone())
2878 } else {
2879 None
2880 }
2881 } else {
2882 None
2883 }
2884 }
2885 _ => None,
2886 };
2887
2888 let gs = gen_series?;
2889
2890 let value_col = Expression::Column(Column {
2892 name: Identifier::new("value".to_string()),
2893 table: None,
2894 join_mark: false,
2895 trailing_comments: vec![],
2896 });
2897
2898 let cast_value = Expression::Cast(Box::new(Cast {
2899 this: value_col,
2900 to: DataType::Date,
2901 trailing_comments: vec![],
2902 double_colon_syntax: false,
2903 format: None,
2904 default: None,
2905 }));
2906
2907 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
2908
2909 let gen_series_aliased = Expression::Alias(Box::new(Alias {
2911 this: gen_series_expr,
2912 alias: Identifier::new("_t".to_string()),
2913 column_aliases: vec![Identifier::new("value".to_string())],
2914 pre_alias_comments: vec![],
2915 trailing_comments: vec![],
2916 }));
2917
2918 let mut inner_select = Select::new();
2919 inner_select.expressions = vec![cast_value];
2920 inner_select.from = Some(From {
2921 expressions: vec![gen_series_aliased],
2922 });
2923
2924 let inner_select_expr = Expression::Select(Box::new(inner_select));
2925
2926 let subquery = Expression::Subquery(Box::new(Subquery {
2927 this: inner_select_expr,
2928 alias: None,
2929 column_aliases: vec![],
2930 order_by: None,
2931 limit: None,
2932 offset: None,
2933 distribute_by: None,
2934 sort_by: None,
2935 cluster_by: None,
2936 lateral: false,
2937 modifiers_inside: false,
2938 trailing_comments: vec![],
2939 }));
2940
2941 Some(Expression::Alias(Box::new(Alias {
2943 this: subquery,
2944 alias: Identifier::new("_unnested_generate_series".to_string()),
2945 column_aliases: vec![],
2946 pre_alias_comments: vec![],
2947 trailing_comments: vec![],
2948 })))
2949}
2950
2951pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
2959 match expr {
2960 Expression::Delete(mut delete) => {
2961 if let Some(ref mut where_clause) = delete.where_clause {
2963 where_clause.this = expand_between_recursive(where_clause.this.clone());
2964 }
2965 Ok(Expression::Delete(delete))
2966 }
2967 other => Ok(other),
2968 }
2969}
2970
2971fn expand_between_recursive(expr: Expression) -> Expression {
2973 match expr {
2974 Expression::Between(between) => {
2977 let this = expand_between_recursive(between.this.clone());
2978 let low = expand_between_recursive(between.low);
2979 let high = expand_between_recursive(between.high);
2980
2981 if between.not {
2982 Expression::Or(Box::new(BinaryOp::new(
2984 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
2985 Expression::Gt(Box::new(BinaryOp::new(this, high))),
2986 )))
2987 } else {
2988 Expression::And(Box::new(BinaryOp::new(
2990 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
2991 Expression::Lte(Box::new(BinaryOp::new(this, high))),
2992 )))
2993 }
2994 }
2995
2996 Expression::And(mut op) => {
2998 op.left = expand_between_recursive(op.left);
2999 op.right = expand_between_recursive(op.right);
3000 Expression::And(op)
3001 }
3002 Expression::Or(mut op) => {
3003 op.left = expand_between_recursive(op.left);
3004 op.right = expand_between_recursive(op.right);
3005 Expression::Or(op)
3006 }
3007 Expression::Not(mut op) => {
3008 op.this = expand_between_recursive(op.this);
3009 Expression::Not(op)
3010 }
3011
3012 Expression::Paren(mut paren) => {
3014 paren.this = expand_between_recursive(paren.this);
3015 Expression::Paren(paren)
3016 }
3017
3018 other => other,
3020 }
3021}
3022
3023pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
3032 match expr {
3033 Expression::Select(mut select) => {
3034 if let Some(ref mut with) = select.with {
3035 for cte in &mut with.ctes {
3036 if !cte.columns.is_empty() {
3037 let is_star = matches!(&cte.this, Expression::Select(s) if
3039 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
3040
3041 if is_star {
3042 cte.columns.clear();
3044 continue;
3045 }
3046
3047 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
3049
3050 if let Expression::Select(ref mut inner_select) = cte.this {
3052 let new_exprs: Vec<Expression> = inner_select
3053 .expressions
3054 .drain(..)
3055 .zip(
3056 column_names
3057 .into_iter()
3058 .chain(std::iter::repeat_with(|| Identifier::new(""))),
3059 )
3060 .map(|(expr, col_name)| {
3061 if col_name.name.is_empty() {
3062 return expr;
3063 }
3064 match expr {
3066 Expression::Alias(mut a) => {
3067 a.alias = col_name;
3068 Expression::Alias(a)
3069 }
3070 other => {
3071 Expression::Alias(Box::new(crate::expressions::Alias {
3072 this: other,
3073 alias: col_name,
3074 column_aliases: Vec::new(),
3075 pre_alias_comments: Vec::new(),
3076 trailing_comments: Vec::new(),
3077 }))
3078 }
3079 }
3080 })
3081 .collect();
3082 inner_select.expressions = new_exprs;
3083 }
3084 }
3085 }
3086 }
3087 Ok(Expression::Select(select))
3088 }
3089 other => Ok(other),
3090 }
3091}
3092
3093pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
3097 match expr {
3098 Expression::Select(mut select) => {
3099 if let Some(ref mut from) = select.from {
3100 for from_item in from.expressions.iter_mut() {
3101 simplify_paren_values_in_from(from_item);
3102 }
3103 }
3104 Ok(Expression::Select(select))
3105 }
3106 other => Ok(other),
3107 }
3108}
3109
3110fn simplify_paren_values_in_from(expr: &mut Expression) {
3111 let replacement = match expr {
3113 Expression::Subquery(ref subquery) => {
3115 if let Expression::Paren(ref paren) = subquery.this {
3116 if matches!(&paren.this, Expression::Values(_)) {
3117 let mut new_sub = subquery.as_ref().clone();
3118 new_sub.this = paren.this.clone();
3119 Some(Expression::Subquery(Box::new(new_sub)))
3120 } else {
3121 None
3122 }
3123 } else {
3124 None
3125 }
3126 }
3127 Expression::Paren(ref outer_paren) => {
3130 if let Expression::Subquery(ref subquery) = outer_paren.this {
3131 if matches!(&subquery.this, Expression::Values(_)) {
3133 Some(outer_paren.this.clone())
3134 }
3135 else if let Expression::Paren(ref paren) = subquery.this {
3137 if matches!(&paren.this, Expression::Values(_)) {
3138 let mut new_sub = subquery.as_ref().clone();
3139 new_sub.this = paren.this.clone();
3140 Some(Expression::Subquery(Box::new(new_sub)))
3141 } else {
3142 None
3143 }
3144 } else {
3145 None
3146 }
3147 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
3148 if matches!(&inner_paren.this, Expression::Values(_)) {
3149 Some(outer_paren.this.clone())
3150 } else {
3151 None
3152 }
3153 } else {
3154 None
3155 }
3156 }
3157 _ => None,
3158 };
3159 if let Some(new_expr) = replacement {
3160 *expr = new_expr;
3161 }
3162}
3163
3164pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
3168 match expr {
3169 Expression::Select(mut select) => {
3170 if let Some(ref mut from) = select.from {
3172 let mut counter = 0usize;
3173 for from_item in from.expressions.iter_mut() {
3174 add_auto_alias_to_from_item(from_item, &mut counter);
3175 }
3176 }
3177 Ok(Expression::Select(select))
3178 }
3179 other => Ok(other),
3180 }
3181}
3182
3183fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
3184 use crate::expressions::Identifier;
3185
3186 match expr {
3187 Expression::Alias(ref mut alias) => {
3188 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
3190 alias.alias = Identifier::new(format!("_t{}", counter));
3191 *counter += 1;
3192 }
3193 }
3194 _ => {}
3195 }
3196}
3197
3198pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
3208 use crate::dialects::transform_recursive;
3209 transform_recursive(expr, &propagate_struct_names_in_expr)
3210}
3211
3212fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
3213 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
3214
3215 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
3217 if elements.len() <= 1 {
3218 return None;
3219 }
3220 if let Some(Expression::Function(ref first_struct)) = elements.first() {
3222 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
3223 let field_names: Vec<Option<String>> = first_struct
3225 .args
3226 .iter()
3227 .map(|arg| {
3228 if let Expression::Alias(a) = arg {
3229 Some(a.alias.name.clone())
3230 } else {
3231 None
3232 }
3233 })
3234 .collect();
3235
3236 if field_names.iter().any(|n| n.is_some()) {
3238 let mut new_elements = Vec::with_capacity(elements.len());
3239 new_elements.push(elements[0].clone());
3240
3241 for elem in &elements[1..] {
3242 if let Expression::Function(ref s) = elem {
3243 if s.name.eq_ignore_ascii_case("STRUCT")
3244 && s.args.len() == field_names.len()
3245 {
3246 let all_unnamed =
3248 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
3249 if all_unnamed {
3250 let new_args: Vec<Expression> = s
3252 .args
3253 .iter()
3254 .zip(field_names.iter())
3255 .map(|(val, name)| {
3256 if let Some(n) = name {
3257 Expression::Alias(Box::new(Alias::new(
3258 val.clone(),
3259 Identifier::new(n.clone()),
3260 )))
3261 } else {
3262 val.clone()
3263 }
3264 })
3265 .collect();
3266 new_elements.push(Expression::Function(Box::new(
3267 Function::new("STRUCT".to_string(), new_args),
3268 )));
3269 continue;
3270 }
3271 }
3272 }
3273 new_elements.push(elem.clone());
3274 }
3275
3276 return Some(new_elements);
3277 }
3278 }
3279 }
3280 None
3281 }
3282
3283 if let Expression::Array(ref arr) = expr {
3285 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3286 return Ok(Expression::Array(Box::new(crate::expressions::Array {
3287 expressions: new_elements,
3288 })));
3289 }
3290 }
3291
3292 if let Expression::ArrayFunc(ref arr) = expr {
3294 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3295 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
3296 expressions: new_elements,
3297 bracket_notation: arr.bracket_notation,
3298 use_list_keyword: arr.use_list_keyword,
3299 })));
3300 }
3301 }
3302
3303 Ok(expr)
3304}
3305
3306pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
3309 use crate::dialects::transform_recursive;
3310 transform_recursive(expr, &unnest_alias_transform_single_select)
3311}
3312
3313pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
3316 use crate::dialects::transform_recursive;
3317 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
3318}
3319
3320fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
3321 if let Expression::Select(mut select) = expr {
3322 if let Some(ref mut from) = select.from {
3323 if from.expressions.len() > 1 {
3324 let mut new_from_exprs = Vec::new();
3325 let mut new_cross_joins = Vec::new();
3326
3327 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3328 if idx == 0 {
3329 new_from_exprs.push(from_item);
3330 } else {
3331 let is_unnest = match &from_item {
3332 Expression::Unnest(_) => true,
3333 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3334 _ => false,
3335 };
3336
3337 if is_unnest {
3338 new_cross_joins.push(crate::expressions::Join {
3339 this: from_item,
3340 on: None,
3341 using: Vec::new(),
3342 kind: JoinKind::Cross,
3343 use_inner_keyword: false,
3344 use_outer_keyword: false,
3345 deferred_condition: false,
3346 join_hint: None,
3347 match_condition: None,
3348 pivots: Vec::new(),
3349 comments: Vec::new(),
3350 nesting_group: 0,
3351 directed: false,
3352 });
3353 } else {
3354 new_from_exprs.push(from_item);
3355 }
3356 }
3357 }
3358
3359 from.expressions = new_from_exprs;
3360 new_cross_joins.append(&mut select.joins);
3361 select.joins = new_cross_joins;
3362 }
3363 }
3364
3365 Ok(Expression::Select(select))
3366 } else {
3367 Ok(expr)
3368 }
3369}
3370
3371pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
3375 use crate::dialects::transform_recursive;
3376 transform_recursive(expr, &wrap_unnest_join_aliases_single)
3377}
3378
3379fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
3380 if let Expression::Select(mut select) = expr {
3381 for join in &mut select.joins {
3383 wrap_unnest_alias_in_join_item(&mut join.this);
3384 }
3385 Ok(Expression::Select(select))
3386 } else {
3387 Ok(expr)
3388 }
3389}
3390
3391fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
3393 use crate::expressions::Identifier;
3394 if let Expression::Alias(alias) = expr {
3395 let is_unnest = match &alias.this {
3397 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
3398 _ => false,
3399 };
3400
3401 if is_unnest && alias.column_aliases.is_empty() {
3402 let original_alias_name = alias.alias.name.clone();
3404 alias.alias = Identifier {
3405 name: "_u".to_string(),
3406 quoted: false,
3407 trailing_comments: Vec::new(),
3408 };
3409 alias.column_aliases = vec![Identifier {
3410 name: original_alias_name,
3411 quoted: false,
3412 trailing_comments: Vec::new(),
3413 }];
3414 }
3415 }
3416}
3417
3418fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
3419 if let Expression::Select(mut select) = expr {
3420 let mut counter = 0usize;
3421
3422 if let Some(ref mut from) = select.from {
3424 for from_item in from.expressions.iter_mut() {
3426 convert_unnest_alias_in_from(from_item, &mut counter);
3427 }
3428
3429 if from.expressions.len() > 1 {
3431 let mut new_from_exprs = Vec::new();
3432 let mut new_cross_joins = Vec::new();
3433
3434 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3435 if idx == 0 {
3436 new_from_exprs.push(from_item);
3438 } else {
3439 let is_unnest = match &from_item {
3441 Expression::Unnest(_) => true,
3442 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3443 _ => false,
3444 };
3445
3446 if is_unnest {
3447 new_cross_joins.push(crate::expressions::Join {
3449 this: from_item,
3450 on: None,
3451 using: Vec::new(),
3452 kind: JoinKind::Cross,
3453 use_inner_keyword: false,
3454 use_outer_keyword: false,
3455 deferred_condition: false,
3456 join_hint: None,
3457 match_condition: None,
3458 pivots: Vec::new(),
3459 comments: Vec::new(),
3460 nesting_group: 0,
3461 directed: false,
3462 });
3463 } else {
3464 new_from_exprs.push(from_item);
3466 }
3467 }
3468 }
3469
3470 from.expressions = new_from_exprs;
3471 new_cross_joins.append(&mut select.joins);
3473 select.joins = new_cross_joins;
3474 }
3475 }
3476
3477 for join in select.joins.iter_mut() {
3479 convert_unnest_alias_in_from(&mut join.this, &mut counter);
3480 }
3481
3482 Ok(Expression::Select(select))
3483 } else {
3484 Ok(expr)
3485 }
3486}
3487
3488fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
3489 use crate::expressions::Identifier;
3490
3491 if let Expression::Alias(ref mut alias) = expr {
3492 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
3494 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
3495
3496 if is_unnest && alias.column_aliases.is_empty() {
3497 let col_alias = alias.alias.clone();
3499 alias.column_aliases = vec![col_alias];
3500 alias.alias = Identifier::new(format!("_t{}", counter));
3501 *counter += 1;
3502 }
3503 }
3504}
3505
3506pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
3513 use crate::expressions::{Alias, Function};
3514
3515 match expr {
3516 Expression::Select(mut select) => {
3517 let mut new_expressions = Vec::new();
3519 let mut changed = false;
3520
3521 for sel_expr in select.expressions.drain(..) {
3522 if let Expression::Alias(ref alias_box) = sel_expr {
3524 if let Expression::Function(ref func) = alias_box.this {
3525 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3526 let arg = func.args[0].clone();
3527 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
3529 (
3530 alias_box.column_aliases[0].name.clone(),
3531 alias_box.column_aliases[1].name.clone(),
3532 )
3533 } else if !alias_box.alias.is_empty() {
3534 ("pos".to_string(), alias_box.alias.name.clone())
3536 } else {
3537 ("pos".to_string(), "col".to_string())
3538 };
3539
3540 let gen_subscripts = Expression::Function(Box::new(Function::new(
3542 "GENERATE_SUBSCRIPTS".to_string(),
3543 vec![
3544 arg.clone(),
3545 Expression::Literal(Literal::Number("1".to_string())),
3546 ],
3547 )));
3548 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3549 gen_subscripts,
3550 Expression::Literal(Literal::Number("1".to_string())),
3551 )));
3552 let pos_alias = Expression::Alias(Box::new(Alias {
3553 this: sub_one,
3554 alias: Identifier::new(pos_name),
3555 column_aliases: Vec::new(),
3556 pre_alias_comments: Vec::new(),
3557 trailing_comments: Vec::new(),
3558 }));
3559
3560 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3562 this: arg,
3563 expressions: Vec::new(),
3564 with_ordinality: false,
3565 alias: None,
3566 offset_alias: None,
3567 }));
3568 let col_alias = Expression::Alias(Box::new(Alias {
3569 this: unnest,
3570 alias: Identifier::new(col_name),
3571 column_aliases: Vec::new(),
3572 pre_alias_comments: Vec::new(),
3573 trailing_comments: Vec::new(),
3574 }));
3575
3576 new_expressions.push(pos_alias);
3577 new_expressions.push(col_alias);
3578 changed = true;
3579 continue;
3580 }
3581 }
3582 }
3583
3584 if let Expression::Function(ref func) = sel_expr {
3586 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3587 let arg = func.args[0].clone();
3588 let pos_name = "pos";
3589 let col_name = "col";
3590
3591 let gen_subscripts = Expression::Function(Box::new(Function::new(
3593 "GENERATE_SUBSCRIPTS".to_string(),
3594 vec![
3595 arg.clone(),
3596 Expression::Literal(Literal::Number("1".to_string())),
3597 ],
3598 )));
3599 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3600 gen_subscripts,
3601 Expression::Literal(Literal::Number("1".to_string())),
3602 )));
3603 let pos_alias = Expression::Alias(Box::new(Alias {
3604 this: sub_one,
3605 alias: Identifier::new(pos_name),
3606 column_aliases: Vec::new(),
3607 pre_alias_comments: Vec::new(),
3608 trailing_comments: Vec::new(),
3609 }));
3610
3611 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3613 this: arg,
3614 expressions: Vec::new(),
3615 with_ordinality: false,
3616 alias: None,
3617 offset_alias: None,
3618 }));
3619 let col_alias = Expression::Alias(Box::new(Alias {
3620 this: unnest,
3621 alias: Identifier::new(col_name),
3622 column_aliases: Vec::new(),
3623 pre_alias_comments: Vec::new(),
3624 trailing_comments: Vec::new(),
3625 }));
3626
3627 new_expressions.push(pos_alias);
3628 new_expressions.push(col_alias);
3629 changed = true;
3630 continue;
3631 }
3632 }
3633
3634 new_expressions.push(sel_expr);
3636 }
3637
3638 if changed {
3639 select.expressions = new_expressions;
3640 } else {
3641 select.expressions = new_expressions;
3642 }
3643
3644 if let Some(ref mut from) = select.from {
3647 expand_posexplode_in_from_duckdb(from)?;
3648 }
3649
3650 Ok(Expression::Select(select))
3651 }
3652 other => Ok(other),
3653 }
3654}
3655
3656fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
3658 use crate::expressions::{Alias, Function};
3659
3660 let mut new_expressions = Vec::new();
3661 let mut _changed = false;
3662
3663 for table_expr in from.expressions.drain(..) {
3664 if let Expression::Alias(ref alias_box) = table_expr {
3666 if let Expression::Function(ref func) = alias_box.this {
3667 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3668 let arg = func.args[0].clone();
3669 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
3670 (
3671 alias_box.column_aliases[0].name.clone(),
3672 alias_box.column_aliases[1].name.clone(),
3673 )
3674 } else {
3675 ("pos".to_string(), "col".to_string())
3676 };
3677
3678 let gen_subscripts = Expression::Function(Box::new(Function::new(
3680 "GENERATE_SUBSCRIPTS".to_string(),
3681 vec![
3682 arg.clone(),
3683 Expression::Literal(Literal::Number("1".to_string())),
3684 ],
3685 )));
3686 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3687 gen_subscripts,
3688 Expression::Literal(Literal::Number("1".to_string())),
3689 )));
3690 let pos_alias = Expression::Alias(Box::new(Alias {
3691 this: sub_one,
3692 alias: Identifier::new(&pos_name),
3693 column_aliases: Vec::new(),
3694 pre_alias_comments: Vec::new(),
3695 trailing_comments: Vec::new(),
3696 }));
3697 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3698 this: arg,
3699 expressions: Vec::new(),
3700 with_ordinality: false,
3701 alias: None,
3702 offset_alias: None,
3703 }));
3704 let col_alias = Expression::Alias(Box::new(Alias {
3705 this: unnest,
3706 alias: Identifier::new(&col_name),
3707 column_aliases: Vec::new(),
3708 pre_alias_comments: Vec::new(),
3709 trailing_comments: Vec::new(),
3710 }));
3711
3712 let mut inner_select = Select::new();
3713 inner_select.expressions = vec![pos_alias, col_alias];
3714
3715 let subquery = Expression::Subquery(Box::new(Subquery {
3716 this: Expression::Select(Box::new(inner_select)),
3717 alias: None,
3718 column_aliases: Vec::new(),
3719 order_by: None,
3720 limit: None,
3721 offset: None,
3722 distribute_by: None,
3723 sort_by: None,
3724 cluster_by: None,
3725 lateral: false,
3726 modifiers_inside: false,
3727 trailing_comments: Vec::new(),
3728 }));
3729 new_expressions.push(subquery);
3730 _changed = true;
3731 continue;
3732 }
3733 }
3734 }
3735
3736 if let Expression::Function(ref func) = table_expr {
3738 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
3739 let arg = func.args[0].clone();
3740
3741 let gen_subscripts = Expression::Function(Box::new(Function::new(
3743 "GENERATE_SUBSCRIPTS".to_string(),
3744 vec![
3745 arg.clone(),
3746 Expression::Literal(Literal::Number("1".to_string())),
3747 ],
3748 )));
3749 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
3750 gen_subscripts,
3751 Expression::Literal(Literal::Number("1".to_string())),
3752 )));
3753 let pos_alias = Expression::Alias(Box::new(Alias {
3754 this: sub_one,
3755 alias: Identifier::new("pos"),
3756 column_aliases: Vec::new(),
3757 pre_alias_comments: Vec::new(),
3758 trailing_comments: Vec::new(),
3759 }));
3760 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3761 this: arg,
3762 expressions: Vec::new(),
3763 with_ordinality: false,
3764 alias: None,
3765 offset_alias: None,
3766 }));
3767 let col_alias = Expression::Alias(Box::new(Alias {
3768 this: unnest,
3769 alias: Identifier::new("col"),
3770 column_aliases: Vec::new(),
3771 pre_alias_comments: Vec::new(),
3772 trailing_comments: Vec::new(),
3773 }));
3774
3775 let mut inner_select = Select::new();
3776 inner_select.expressions = vec![pos_alias, col_alias];
3777
3778 let subquery = Expression::Subquery(Box::new(Subquery {
3779 this: Expression::Select(Box::new(inner_select)),
3780 alias: None,
3781 column_aliases: Vec::new(),
3782 order_by: None,
3783 limit: None,
3784 offset: None,
3785 distribute_by: None,
3786 sort_by: None,
3787 cluster_by: None,
3788 lateral: false,
3789 modifiers_inside: false,
3790 trailing_comments: Vec::new(),
3791 }));
3792 new_expressions.push(subquery);
3793 _changed = true;
3794 continue;
3795 }
3796 }
3797
3798 new_expressions.push(table_expr);
3799 }
3800
3801 from.expressions = new_expressions;
3802 Ok(())
3803}
3804
3805pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
3820 match expr {
3821 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
3822 other => Ok(other),
3823 }
3824}
3825
3826pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
3836 match expr {
3837 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
3838 other => Ok(other),
3839 }
3840}
3841
3842fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
3843 let mut flattened_inputs: Vec<Expression> = Vec::new();
3844 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
3845
3846 for sel_expr in select.expressions.into_iter() {
3847 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
3848
3849 let rewritten = transform_recursive(sel_expr, &|e| {
3850 if let Expression::Lateral(lat) = e {
3851 if let Some(input_expr) = extract_flatten_input(&lat) {
3852 if found_input.borrow().is_none() {
3853 *found_input.borrow_mut() = Some(input_expr);
3854 }
3855 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
3856 }
3857 return Ok(Expression::Lateral(lat));
3858 }
3859 Ok(e)
3860 })?;
3861
3862 if let Some(input) = found_input.into_inner() {
3863 flattened_inputs.push(input);
3864 }
3865 new_selects.push(rewritten);
3866 }
3867
3868 if flattened_inputs.is_empty() {
3869 select.expressions = new_selects;
3870 return Ok(Expression::Select(Box::new(select)));
3871 }
3872
3873 select.expressions = new_selects;
3874
3875 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
3876 let is_first = idx == 0;
3878 let series_alias = if is_first {
3879 "pos".to_string()
3880 } else {
3881 format!("pos_{}", idx + 1)
3882 };
3883 let series_source_alias = if is_first {
3884 "_u".to_string()
3885 } else {
3886 format!("_u_{}", idx * 2 + 1)
3887 };
3888 let unnest_source_alias = if is_first {
3889 "_u_2".to_string()
3890 } else {
3891 format!("_u_{}", idx * 2 + 2)
3892 };
3893 let pos2_alias = if is_first {
3894 "pos_2".to_string()
3895 } else {
3896 format!("{}_2", series_alias)
3897 };
3898 let entity_alias = if is_first {
3899 "entity".to_string()
3900 } else {
3901 format!("entity_{}", idx + 1)
3902 };
3903
3904 let array_size_call = Expression::Function(Box::new(Function::new(
3905 "ARRAY_SIZE".to_string(),
3906 vec![Expression::NamedArgument(Box::new(NamedArgument {
3907 name: Identifier::new("INPUT"),
3908 value: input_expr.clone(),
3909 separator: NamedArgSeparator::DArrow,
3910 }))],
3911 )));
3912
3913 let greatest = Expression::Function(Box::new(Function::new(
3914 "GREATEST".to_string(),
3915 vec![array_size_call.clone()],
3916 )));
3917
3918 let series_end = Expression::Add(Box::new(BinaryOp::new(
3919 Expression::Paren(Box::new(crate::expressions::Paren {
3920 this: Expression::Sub(Box::new(BinaryOp::new(
3921 greatest,
3922 Expression::Literal(Literal::Number("1".to_string())),
3923 ))),
3924 trailing_comments: Vec::new(),
3925 })),
3926 Expression::Literal(Literal::Number("1".to_string())),
3927 )));
3928
3929 let series_range = Expression::Function(Box::new(Function::new(
3930 "ARRAY_GENERATE_RANGE".to_string(),
3931 vec![
3932 Expression::Literal(Literal::Number("0".to_string())),
3933 series_end,
3934 ],
3935 )));
3936
3937 let series_flatten = Expression::Function(Box::new(Function::new(
3938 "FLATTEN".to_string(),
3939 vec![Expression::NamedArgument(Box::new(NamedArgument {
3940 name: Identifier::new("INPUT"),
3941 value: series_range,
3942 separator: NamedArgSeparator::DArrow,
3943 }))],
3944 )));
3945
3946 let series_table = Expression::Function(Box::new(Function::new(
3947 "TABLE".to_string(),
3948 vec![series_flatten],
3949 )));
3950
3951 let series_alias_expr = Expression::Alias(Box::new(Alias {
3952 this: series_table,
3953 alias: Identifier::new(series_source_alias.clone()),
3954 column_aliases: vec![
3955 Identifier::new("seq"),
3956 Identifier::new("key"),
3957 Identifier::new("path"),
3958 Identifier::new("index"),
3959 Identifier::new(series_alias.clone()),
3960 Identifier::new("this"),
3961 ],
3962 pre_alias_comments: Vec::new(),
3963 trailing_comments: Vec::new(),
3964 }));
3965
3966 select.joins.push(Join {
3967 this: series_alias_expr,
3968 on: None,
3969 using: Vec::new(),
3970 kind: JoinKind::Cross,
3971 use_inner_keyword: false,
3972 use_outer_keyword: false,
3973 deferred_condition: false,
3974 join_hint: None,
3975 match_condition: None,
3976 pivots: Vec::new(),
3977 comments: Vec::new(),
3978 nesting_group: 0,
3979 directed: false,
3980 });
3981
3982 let entity_flatten = Expression::Function(Box::new(Function::new(
3983 "FLATTEN".to_string(),
3984 vec![Expression::NamedArgument(Box::new(NamedArgument {
3985 name: Identifier::new("INPUT"),
3986 value: input_expr.clone(),
3987 separator: NamedArgSeparator::DArrow,
3988 }))],
3989 )));
3990
3991 let entity_table = Expression::Function(Box::new(Function::new(
3992 "TABLE".to_string(),
3993 vec![entity_flatten],
3994 )));
3995
3996 let entity_alias_expr = Expression::Alias(Box::new(Alias {
3997 this: entity_table,
3998 alias: Identifier::new(unnest_source_alias.clone()),
3999 column_aliases: vec![
4000 Identifier::new("seq"),
4001 Identifier::new("key"),
4002 Identifier::new("path"),
4003 Identifier::new(pos2_alias.clone()),
4004 Identifier::new(entity_alias.clone()),
4005 Identifier::new("this"),
4006 ],
4007 pre_alias_comments: Vec::new(),
4008 trailing_comments: Vec::new(),
4009 }));
4010
4011 select.joins.push(Join {
4012 this: entity_alias_expr,
4013 on: None,
4014 using: Vec::new(),
4015 kind: JoinKind::Cross,
4016 use_inner_keyword: false,
4017 use_outer_keyword: false,
4018 deferred_condition: false,
4019 join_hint: None,
4020 match_condition: None,
4021 pivots: Vec::new(),
4022 comments: Vec::new(),
4023 nesting_group: 0,
4024 directed: false,
4025 });
4026
4027 let pos_col =
4028 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
4029 let pos2_col =
4030 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
4031
4032 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
4033 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
4034 this: Expression::Sub(Box::new(BinaryOp::new(
4035 array_size_call,
4036 Expression::Literal(Literal::Number("1".to_string())),
4037 ))),
4038 trailing_comments: Vec::new(),
4039 }));
4040 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
4041 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
4042 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
4043 let or_cond = Expression::Or(Box::new(BinaryOp::new(
4044 eq,
4045 Expression::Paren(Box::new(crate::expressions::Paren {
4046 this: and_cond,
4047 trailing_comments: Vec::new(),
4048 })),
4049 )));
4050
4051 select.where_clause = Some(match select.where_clause.take() {
4052 Some(existing) => Where {
4053 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
4054 },
4055 None => Where { this: or_cond },
4056 });
4057 }
4058
4059 Ok(Expression::Select(Box::new(select)))
4060}
4061
4062fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
4063 let Expression::Function(f) = lat.this.as_ref() else {
4064 return None;
4065 };
4066 if !f.name.eq_ignore_ascii_case("FLATTEN") {
4067 return None;
4068 }
4069
4070 for arg in &f.args {
4071 if let Expression::NamedArgument(na) = arg {
4072 if na.name.name.eq_ignore_ascii_case("INPUT") {
4073 return Some(na.value.clone());
4074 }
4075 }
4076 }
4077 f.args.first().cloned()
4078}
4079
4080fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
4081 let cond = Expression::Eq(Box::new(BinaryOp::new(
4082 Expression::qualified_column("_u", "pos"),
4083 Expression::qualified_column("_u_2", "pos_2"),
4084 )));
4085 let true_expr = Expression::qualified_column("_u_2", "entity");
4086 let iff_expr = Expression::Function(Box::new(Function::new(
4087 "IFF".to_string(),
4088 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
4089 )));
4090
4091 lat.this = Box::new(iff_expr);
4092 if lat.column_aliases.is_empty() {
4093 lat.column_aliases = vec![
4094 "SEQ".to_string(),
4095 "KEY".to_string(),
4096 "PATH".to_string(),
4097 "INDEX".to_string(),
4098 "VALUE".to_string(),
4099 "THIS".to_string(),
4100 ];
4101 }
4102 lat
4103}
4104
4105struct ExplodeInfo {
4107 arg_sql: String,
4109 explode_alias: String,
4111 pos_alias: String,
4113 unnest_source_alias: String,
4115}
4116
4117fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
4118 let is_presto = matches!(
4119 target,
4120 DialectType::Presto | DialectType::Trino | DialectType::Athena
4121 );
4122 let is_bigquery = matches!(target, DialectType::BigQuery);
4123
4124 if !is_presto && !is_bigquery {
4125 return Ok(Expression::Select(Box::new(select)));
4126 }
4127
4128 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
4130 if !has_explode {
4131 return Ok(Expression::Select(Box::new(select)));
4132 }
4133
4134 let mut taken_select_names = std::collections::HashSet::new();
4136 let mut taken_source_names = std::collections::HashSet::new();
4137
4138 for sel in &select.expressions {
4140 if let Some(name) = get_output_name(sel) {
4141 taken_select_names.insert(name);
4142 }
4143 }
4144
4145 for sel in &select.expressions {
4147 let explode_expr = find_explode_in_expr(sel);
4148 if let Some(arg) = explode_expr {
4149 if let Some(name) = get_output_name(&arg) {
4150 taken_select_names.insert(name);
4151 }
4152 }
4153 }
4154
4155 if let Some(ref from) = select.from {
4157 for from_expr in &from.expressions {
4158 collect_source_names(from_expr, &mut taken_source_names);
4159 }
4160 }
4161 for join in &select.joins {
4163 collect_source_names(&join.this, &mut taken_source_names);
4164 }
4165
4166 let series_alias = new_name(&mut taken_select_names, "pos");
4168
4169 let series_source_alias = new_name(&mut taken_source_names, "_u");
4171
4172 let target_dialect = Dialect::get(target);
4174
4175 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
4177 let mut new_projections: Vec<String> = Vec::new();
4178
4179 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
4180 let explode_data = extract_explode_data(sel_expr);
4181
4182 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
4183 let arg_sql = target_dialect
4185 .generate(&arg_expr)
4186 .unwrap_or_else(|_| "NULL".to_string());
4187
4188 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
4189
4190 let explode_alias = if let Some(ref ea) = explicit_alias {
4191 taken_select_names.remove(ea.as_str());
4194 let name = new_name(&mut taken_select_names, ea);
4196 name
4197 } else {
4198 new_name(&mut taken_select_names, "col")
4199 };
4200
4201 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
4202 taken_select_names.remove(pa.as_str());
4204 let name = new_name(&mut taken_select_names, pa);
4205 name
4206 } else {
4207 new_name(&mut taken_select_names, "pos")
4208 };
4209
4210 if is_presto {
4212 let if_col = format!(
4214 "IF({}.{} = {}.{}, {}.{}) AS {}",
4215 series_source_alias,
4216 series_alias,
4217 unnest_source_alias,
4218 pos_alias,
4219 unnest_source_alias,
4220 explode_alias,
4221 explode_alias
4222 );
4223 new_projections.push(if_col);
4224
4225 if is_posexplode {
4227 let if_pos = format!(
4228 "IF({}.{} = {}.{}, {}.{}) AS {}",
4229 series_source_alias,
4230 series_alias,
4231 unnest_source_alias,
4232 pos_alias,
4233 unnest_source_alias,
4234 pos_alias,
4235 pos_alias
4236 );
4237 new_projections.push(if_pos);
4238 }
4239 } else {
4240 let if_col = format!(
4242 "IF({} = {}, {}, NULL) AS {}",
4243 series_alias, pos_alias, explode_alias, explode_alias
4244 );
4245 new_projections.push(if_col);
4246
4247 if is_posexplode {
4249 let if_pos = format!(
4250 "IF({} = {}, {}, NULL) AS {}",
4251 series_alias, pos_alias, pos_alias, pos_alias
4252 );
4253 new_projections.push(if_pos);
4254 }
4255 }
4256
4257 explode_infos.push(ExplodeInfo {
4258 arg_sql,
4259 explode_alias,
4260 pos_alias,
4261 unnest_source_alias,
4262 });
4263 } else {
4264 let sel_sql = target_dialect
4266 .generate(sel_expr)
4267 .unwrap_or_else(|_| "*".to_string());
4268 new_projections.push(sel_sql);
4269 }
4270 }
4271
4272 if explode_infos.is_empty() {
4273 return Ok(Expression::Select(Box::new(select)));
4274 }
4275
4276 let mut from_parts: Vec<String> = Vec::new();
4278
4279 if let Some(ref from) = select.from {
4281 for from_expr in &from.expressions {
4282 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
4283 from_parts.push(from_sql);
4284 }
4285 }
4286
4287 let size_exprs: Vec<String> = explode_infos
4289 .iter()
4290 .map(|info| {
4291 if is_presto {
4292 format!("CARDINALITY({})", info.arg_sql)
4293 } else {
4294 format!("ARRAY_LENGTH({})", info.arg_sql)
4295 }
4296 })
4297 .collect();
4298
4299 let greatest_arg = if size_exprs.len() == 1 {
4300 size_exprs[0].clone()
4301 } else {
4302 format!("GREATEST({})", size_exprs.join(", "))
4303 };
4304
4305 let series_sql = if is_presto {
4308 if size_exprs.len() == 1 {
4310 format!(
4311 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
4312 greatest_arg, series_source_alias, series_alias
4313 )
4314 } else {
4315 format!(
4317 "UNNEST(SEQUENCE(1, {})) AS {}({})",
4318 greatest_arg, series_source_alias, series_alias
4319 )
4320 }
4321 } else {
4322 if size_exprs.len() == 1 {
4324 format!(
4325 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
4326 greatest_arg, series_alias
4327 )
4328 } else {
4329 format!(
4331 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
4332 greatest_arg, series_alias
4333 )
4334 }
4335 };
4336
4337 let mut cross_joins: Vec<String> = Vec::new();
4341
4342 for info in &explode_infos {
4343 cross_joins.push(format!(
4345 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
4346 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
4347 ));
4348 }
4349
4350 let mut where_conditions: Vec<String> = Vec::new();
4352
4353 for info in &explode_infos {
4354 let size_expr = if is_presto {
4355 format!("CARDINALITY({})", info.arg_sql)
4356 } else {
4357 format!("ARRAY_LENGTH({})", info.arg_sql)
4358 };
4359
4360 let cond = if is_presto {
4361 format!(
4362 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
4363 series_src = series_source_alias,
4364 series_al = series_alias,
4365 unnest_src = info.unnest_source_alias,
4366 pos_al = info.pos_alias,
4367 size = size_expr
4368 )
4369 } else {
4370 format!(
4371 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
4372 series_al = series_alias,
4373 pos_al = info.pos_alias,
4374 size = size_expr
4375 )
4376 };
4377
4378 where_conditions.push(cond);
4379 }
4380
4381 let where_sql = if where_conditions.len() == 1 {
4383 where_conditions[0].clone()
4384 } else {
4385 where_conditions
4386 .iter()
4387 .map(|c| format!("({})", c))
4388 .collect::<Vec<_>>()
4389 .join(" AND ")
4390 };
4391
4392 let select_part = new_projections.join(", ");
4394
4395 let from_and_joins = if from_parts.is_empty() {
4397 format!("FROM {} {}", series_sql, cross_joins.join(" "))
4399 } else {
4400 format!(
4401 "FROM {} {} {}",
4402 from_parts.join(", "),
4403 format!("CROSS JOIN {}", series_sql),
4404 cross_joins.join(" ")
4405 )
4406 };
4407
4408 let full_sql = format!(
4409 "SELECT {} {} WHERE {}",
4410 select_part, from_and_joins, where_sql
4411 );
4412
4413 let generic_dialect = Dialect::get(DialectType::Generic);
4416 let parsed = generic_dialect.parse(&full_sql);
4417 match parsed {
4418 Ok(mut stmts) if !stmts.is_empty() => {
4419 let mut result = stmts.remove(0);
4420
4421 if is_bigquery {
4425 convert_unnest_presto_to_bigquery(&mut result);
4426 }
4427
4428 Ok(result)
4429 }
4430 _ => {
4431 Ok(Expression::Select(Box::new(select)))
4433 }
4434 }
4435}
4436
4437fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
4441 match expr {
4442 Expression::Select(ref mut select) => {
4443 if let Some(ref mut from) = select.from {
4445 for from_item in from.expressions.iter_mut() {
4446 convert_unnest_presto_to_bigquery(from_item);
4447 }
4448 }
4449 for join in select.joins.iter_mut() {
4451 convert_unnest_presto_to_bigquery(&mut join.this);
4452 }
4453 }
4454 Expression::Alias(ref alias) => {
4455 if let Expression::Unnest(ref unnest) = alias.this {
4457 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
4458 let col_alias = alias.column_aliases[0].clone();
4459 let pos_alias = alias.column_aliases[1].clone();
4460 let mut new_unnest = unnest.as_ref().clone();
4461 new_unnest.alias = Some(col_alias);
4462 new_unnest.offset_alias = Some(pos_alias);
4463 *expr = Expression::Unnest(Box::new(new_unnest));
4465 }
4466 }
4467 }
4468 _ => {}
4469 }
4470}
4471
4472fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
4475 if !names.contains(base) {
4476 names.insert(base.to_string());
4477 return base.to_string();
4478 }
4479 let mut i = 2;
4480 loop {
4481 let candidate = format!("{}_{}", base, i);
4482 if !names.contains(&candidate) {
4483 names.insert(candidate.clone());
4484 return candidate;
4485 }
4486 i += 1;
4487 }
4488}
4489
4490fn expr_contains_explode(expr: &Expression) -> bool {
4492 match expr {
4493 Expression::Explode(_) => true,
4494 Expression::ExplodeOuter(_) => true,
4495 Expression::Function(f) => {
4496 let name = f.name.to_uppercase();
4497 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
4498 }
4499 Expression::Alias(a) => expr_contains_explode(&a.this),
4500 _ => false,
4501 }
4502}
4503
4504fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
4506 match expr {
4507 Expression::Explode(uf) => Some(uf.this.clone()),
4508 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
4509 Expression::Function(f) => {
4510 let name = f.name.to_uppercase();
4511 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
4512 Some(f.args[0].clone())
4513 } else {
4514 None
4515 }
4516 }
4517 Expression::Alias(a) => find_explode_in_expr(&a.this),
4518 _ => None,
4519 }
4520}
4521
4522fn extract_explode_data(
4525 expr: &Expression,
4526) -> Option<(bool, Expression, Option<String>, Option<String>)> {
4527 match expr {
4528 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
4530 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
4531 Expression::Function(f) => {
4533 let name = f.name.to_uppercase();
4534 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
4535 Some((true, f.args[0].clone(), None, None))
4536 } else {
4537 None
4538 }
4539 }
4540 Expression::Alias(a) => {
4542 match &a.this {
4543 Expression::Explode(uf) => {
4544 let alias = if !a.alias.is_empty() {
4545 Some(a.alias.name.clone())
4546 } else {
4547 None
4548 };
4549 Some((false, uf.this.clone(), alias, None))
4550 }
4551 Expression::ExplodeOuter(uf) => {
4552 let alias = if !a.alias.is_empty() {
4553 Some(a.alias.name.clone())
4554 } else {
4555 None
4556 };
4557 Some((false, uf.this.clone(), alias, None))
4558 }
4559 Expression::Function(f) => {
4560 let name = f.name.to_uppercase();
4561 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
4562 if a.column_aliases.len() == 2 {
4564 let pos_alias = a.column_aliases[0].name.clone();
4565 let col_alias = a.column_aliases[1].name.clone();
4566 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
4567 } else if !a.alias.is_empty() {
4568 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
4570 } else {
4571 Some((true, f.args[0].clone(), None, None))
4572 }
4573 } else {
4574 None
4575 }
4576 }
4577 _ => None,
4578 }
4579 }
4580 _ => None,
4581 }
4582}
4583
4584fn get_output_name(expr: &Expression) -> Option<String> {
4586 match expr {
4587 Expression::Alias(a) => {
4588 if !a.alias.is_empty() {
4589 Some(a.alias.name.clone())
4590 } else {
4591 None
4592 }
4593 }
4594 Expression::Column(c) => Some(c.name.name.clone()),
4595 Expression::Identifier(id) => Some(id.name.clone()),
4596 _ => None,
4597 }
4598}
4599
4600fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
4602 match expr {
4603 Expression::Alias(a) => {
4604 if !a.alias.is_empty() {
4605 names.insert(a.alias.name.clone());
4606 }
4607 }
4608 Expression::Subquery(s) => {
4609 if let Some(ref alias) = s.alias {
4610 names.insert(alias.name.clone());
4611 }
4612 }
4613 Expression::Table(t) => {
4614 if let Some(ref alias) = t.alias {
4615 names.insert(alias.name.clone());
4616 } else {
4617 names.insert(t.name.name.clone());
4618 }
4619 }
4620 Expression::Column(c) => {
4621 names.insert(c.name.name.clone());
4622 }
4623 Expression::Identifier(id) => {
4624 names.insert(id.name.clone());
4625 }
4626 _ => {}
4627 }
4628}
4629
4630pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
4633 use crate::dialects::transform_recursive;
4634 transform_recursive(expr, &strip_unnest_column_refs_single)
4635}
4636
4637fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
4638 if let Expression::Select(mut select) = expr {
4639 for join in select.joins.iter_mut() {
4641 strip_unnest_from_expr(&mut join.this);
4642 }
4643 if let Some(ref mut from) = select.from {
4645 for from_item in from.expressions.iter_mut() {
4646 strip_unnest_from_expr(from_item);
4647 }
4648 }
4649 Ok(Expression::Select(select))
4650 } else {
4651 Ok(expr)
4652 }
4653}
4654
4655fn strip_unnest_from_expr(expr: &mut Expression) {
4658 if let Expression::Alias(ref mut alias) = expr {
4659 if let Expression::Unnest(ref unnest) = alias.this {
4660 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
4661 if is_column_ref {
4662 let inner = unnest.this.clone();
4664 alias.this = inner;
4665 }
4666 }
4667 }
4668}
4669
4670pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
4673 use crate::dialects::transform_recursive;
4674 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
4675}
4676
4677fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
4678 if let Expression::Select(mut select) = expr {
4679 if let Some(ref mut from) = select.from {
4681 for from_item in from.expressions.iter_mut() {
4682 try_wrap_unnest_in_subquery(from_item);
4683 }
4684 }
4685
4686 for join in select.joins.iter_mut() {
4688 try_wrap_unnest_in_subquery(&mut join.this);
4689 }
4690
4691 Ok(Expression::Select(select))
4692 } else {
4693 Ok(expr)
4694 }
4695}
4696
4697fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
4699 match expr {
4700 Expression::Array(arr) => arr
4702 .expressions
4703 .iter()
4704 .any(|e| matches!(e, Expression::Struct(_))),
4705 Expression::ArrayFunc(arr) => arr
4706 .expressions
4707 .iter()
4708 .any(|e| matches!(e, Expression::Struct(_))),
4709 Expression::Cast(c) => {
4711 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
4712 }
4713 _ => false,
4714 }
4715}
4716
4717fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
4720 if let Expression::Alias(ref alias) = expr {
4722 if let Expression::Unnest(ref unnest) = alias.this {
4723 if is_struct_array_unnest_arg(&unnest.this) {
4724 let unnest_clone = (**unnest).clone();
4725 let alias_name = alias.alias.clone();
4726 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
4727 *expr = new_expr;
4728 return;
4729 }
4730 }
4731 }
4732
4733 if let Expression::Unnest(ref unnest) = expr {
4735 if is_struct_array_unnest_arg(&unnest.this) {
4736 let unnest_clone = (**unnest).clone();
4737 let new_expr = make_unnest_subquery(unnest_clone, None);
4738 *expr = new_expr;
4739 }
4740 }
4741}
4742
4743fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
4745 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
4747 name: Identifier::new("max_depth".to_string()),
4748 value: Expression::Literal(Literal::Number("2".to_string())),
4749 separator: NamedArgSeparator::DArrow,
4750 }));
4751
4752 let mut unnest_args = vec![unnest.this];
4753 unnest_args.extend(unnest.expressions);
4754 unnest_args.push(max_depth_arg);
4755
4756 let unnest_func =
4757 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
4758
4759 let mut inner_select = Select::new();
4761 inner_select.expressions = vec![unnest_func];
4762 let inner_select = Expression::Select(Box::new(inner_select));
4763
4764 let subquery = Subquery {
4766 this: inner_select,
4767 alias,
4768 column_aliases: Vec::new(),
4769 order_by: None,
4770 limit: None,
4771 offset: None,
4772 distribute_by: None,
4773 sort_by: None,
4774 cluster_by: None,
4775 lateral: false,
4776 modifiers_inside: false,
4777 trailing_comments: Vec::new(),
4778 };
4779
4780 Expression::Subquery(Box::new(subquery))
4781}
4782
4783pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
4795 use crate::expressions::{Limit as LimitClause, Offset as OffsetClause, OrderBy, Star};
4796
4797 match expr {
4798 Expression::Union(mut u) => {
4799 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
4802 if let Expression::Select(ref mut right_select) = u.right {
4804 if right_select.order_by.is_some()
4805 || right_select.limit.is_some()
4806 || right_select.offset.is_some()
4807 {
4808 u.order_by = right_select.order_by.take();
4810 u.limit = right_select.limit.take().map(|l| Box::new(l.this));
4811 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
4812 }
4813 }
4814 }
4815
4816 let has_order_or_limit =
4817 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
4818 if has_order_or_limit {
4819 let order_by: Option<OrderBy> = u.order_by.take();
4821 let union_limit: Option<Box<Expression>> = u.limit.take();
4822 let union_offset: Option<Box<Expression>> = u.offset.take();
4823
4824 let select_limit: Option<LimitClause> = union_limit.map(|l| LimitClause {
4826 this: *l,
4827 percent: false,
4828 comments: Vec::new(),
4829 });
4830
4831 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
4833 this: *o,
4834 rows: None,
4835 });
4836
4837 let subquery = Subquery {
4839 this: Expression::Union(u),
4840 alias: Some(Identifier::new("_l_0")),
4841 column_aliases: Vec::new(),
4842 lateral: false,
4843 modifiers_inside: false,
4844 order_by: None,
4845 limit: None,
4846 offset: None,
4847 distribute_by: None,
4848 sort_by: None,
4849 cluster_by: None,
4850 trailing_comments: Vec::new(),
4851 };
4852
4853 let mut select = Select::default();
4855 select.expressions = vec![Expression::Star(Star {
4856 table: None,
4857 except: None,
4858 replace: None,
4859 rename: None,
4860 trailing_comments: Vec::new(),
4861 })];
4862 select.from = Some(From {
4863 expressions: vec![Expression::Subquery(Box::new(subquery))],
4864 });
4865 select.order_by = order_by;
4866 select.limit = select_limit;
4867 select.offset = select_offset;
4868
4869 Ok(Expression::Select(Box::new(select)))
4870 } else {
4871 Ok(Expression::Union(u))
4872 }
4873 }
4874 _ => Ok(expr),
4875 }
4876}
4877
4878pub fn expand_like_any(expr: Expression) -> Result<Expression> {
4883 use crate::expressions::{BinaryOp, LikeOp};
4884
4885 fn unwrap_parens(e: &Expression) -> &Expression {
4886 match e {
4887 Expression::Paren(p) => unwrap_parens(&p.this),
4888 _ => e,
4889 }
4890 }
4891
4892 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
4893 let inner = unwrap_parens(e);
4894 match inner {
4895 Expression::Tuple(t) => Some(t.expressions.clone()),
4896 _ => None,
4897 }
4898 }
4899
4900 transform_recursive(expr, &|e| {
4901 match e {
4902 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
4903 if let Some(values) = extract_tuple_values(&op.right) {
4904 if values.is_empty() {
4905 return Ok(e);
4906 }
4907 let mut result: Option<Expression> = None;
4909 for val in values {
4910 let like = Expression::Like(Box::new(LikeOp {
4911 left: op.left.clone(),
4912 right: val,
4913 escape: op.escape.clone(),
4914 quantifier: None,
4915 }));
4916 result = Some(match result {
4917 None => like,
4918 Some(prev) => Expression::Or(Box::new(BinaryOp::new(prev, like))),
4919 });
4920 }
4921 Ok(result.unwrap_or(e))
4922 } else {
4923 Ok(e)
4924 }
4925 }
4926 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
4927 if let Some(values) = extract_tuple_values(&op.right) {
4928 if values.is_empty() {
4929 return Ok(e);
4930 }
4931 let mut result: Option<Expression> = None;
4932 for val in values {
4933 let ilike = Expression::ILike(Box::new(LikeOp {
4934 left: op.left.clone(),
4935 right: val,
4936 escape: op.escape.clone(),
4937 quantifier: None,
4938 }));
4939 result = Some(match result {
4940 None => ilike,
4941 Some(prev) => Expression::Or(Box::new(BinaryOp::new(prev, ilike))),
4942 });
4943 }
4944 Ok(result.unwrap_or(e))
4945 } else {
4946 Ok(e)
4947 }
4948 }
4949 _ => Ok(e),
4950 }
4951 })
4952}
4953
4954pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
4962 use crate::expressions::Alias;
4963
4964 fn add_self_aliases_to_select(select: &mut Select) {
4965 let new_expressions: Vec<Expression> = select
4966 .expressions
4967 .iter()
4968 .map(|e| {
4969 match e {
4970 Expression::Column(col) => {
4972 let alias_name = col.name.clone();
4973 Expression::Alias(Box::new(Alias {
4974 this: e.clone(),
4975 alias: alias_name,
4976 column_aliases: Vec::new(),
4977 pre_alias_comments: Vec::new(),
4978 trailing_comments: Vec::new(),
4979 }))
4980 }
4981 _ => e.clone(),
4983 }
4984 })
4985 .collect();
4986 select.expressions = new_expressions;
4987 }
4988
4989 fn walk_and_qualify(expr: &mut Expression) {
4990 match expr {
4991 Expression::Select(ref mut select) => {
4992 if let Some(ref mut from) = select.from {
4994 for e in from.expressions.iter_mut() {
4995 qualify_subquery_expr(e);
4996 walk_and_qualify(e);
4997 }
4998 }
4999 for join in select.joins.iter_mut() {
5001 qualify_subquery_expr(&mut join.this);
5002 walk_and_qualify(&mut join.this);
5003 }
5004 for e in select.expressions.iter_mut() {
5006 walk_and_qualify(e);
5007 }
5008 if let Some(ref mut w) = select.where_clause {
5010 walk_and_qualify(&mut w.this);
5011 }
5012 }
5013 Expression::Subquery(ref mut subquery) => {
5014 walk_and_qualify(&mut subquery.this);
5015 }
5016 Expression::Union(ref mut u) => {
5017 walk_and_qualify(&mut u.left);
5018 walk_and_qualify(&mut u.right);
5019 }
5020 Expression::Intersect(ref mut i) => {
5021 walk_and_qualify(&mut i.left);
5022 walk_and_qualify(&mut i.right);
5023 }
5024 Expression::Except(ref mut e) => {
5025 walk_and_qualify(&mut e.left);
5026 walk_and_qualify(&mut e.right);
5027 }
5028 Expression::Cte(ref mut cte) => {
5029 walk_and_qualify(&mut cte.this);
5030 }
5031 _ => {}
5032 }
5033 }
5034
5035 fn qualify_subquery_expr(expr: &mut Expression) {
5036 match expr {
5037 Expression::Subquery(ref mut subquery) => {
5038 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
5040 if let Expression::Select(ref mut inner_select) = subquery.this {
5041 let has_star = inner_select
5043 .expressions
5044 .iter()
5045 .any(|e| matches!(e, Expression::Star(_)));
5046 if !has_star {
5047 add_self_aliases_to_select(inner_select);
5048 }
5049 }
5050 }
5051 walk_and_qualify(&mut subquery.this);
5053 }
5054 Expression::Alias(ref mut alias) => {
5055 qualify_subquery_expr(&mut alias.this);
5056 }
5057 _ => {}
5058 }
5059 }
5060
5061 let mut result = expr;
5062 walk_and_qualify(&mut result);
5063
5064 if let Expression::Select(ref mut select) = result {
5066 if let Some(ref mut with) = select.with {
5067 for cte in with.ctes.iter_mut() {
5068 if cte.columns.is_empty() {
5070 walk_and_qualify(&mut cte.this);
5072 }
5073 }
5074 }
5075 }
5076
5077 Ok(result)
5078}
5079
5080#[cfg(test)]
5081mod tests {
5082 use super::*;
5083 use crate::dialects::{Dialect, DialectType};
5084 use crate::expressions::Column;
5085
5086 fn gen(expr: &Expression) -> String {
5087 let dialect = Dialect::get(DialectType::Generic);
5088 dialect.generate(expr).unwrap()
5089 }
5090
5091 #[test]
5092 fn test_preprocess() {
5093 let expr = Expression::Boolean(BooleanLiteral { value: true });
5094 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
5095 assert!(matches!(result, Expression::Literal(Literal::Number(_))));
5096 }
5097
5098 #[test]
5099 fn test_preprocess_chain() {
5100 let expr = Expression::Boolean(BooleanLiteral { value: true });
5102 let transforms: Vec<fn(Expression) -> Result<Expression>> =
5104 vec![replace_bool_with_int, replace_int_with_bool];
5105 let result = preprocess(expr, &transforms).unwrap();
5106 if let Expression::Boolean(b) = result {
5109 assert!(b.value);
5110 } else {
5111 panic!("Expected boolean literal");
5112 }
5113 }
5114
5115 #[test]
5116 fn test_unnest_to_explode() {
5117 let unnest = Expression::Unnest(Box::new(UnnestFunc {
5118 this: Expression::Column(Column {
5119 name: Identifier::new("arr".to_string()),
5120 table: None,
5121 join_mark: false,
5122 trailing_comments: vec![],
5123 }),
5124 expressions: Vec::new(),
5125 with_ordinality: false,
5126 alias: None,
5127 offset_alias: None,
5128 }));
5129
5130 let result = unnest_to_explode(unnest).unwrap();
5131 assert!(matches!(result, Expression::Explode(_)));
5132 }
5133
5134 #[test]
5135 fn test_explode_to_unnest() {
5136 let explode = Expression::Explode(Box::new(UnaryFunc {
5137 this: Expression::Column(Column {
5138 name: Identifier::new("arr".to_string()),
5139 table: None,
5140 join_mark: false,
5141 trailing_comments: vec![],
5142 }),
5143 original_name: None,
5144 }));
5145
5146 let result = explode_to_unnest(explode).unwrap();
5147 assert!(matches!(result, Expression::Unnest(_)));
5148 }
5149
5150 #[test]
5151 fn test_replace_bool_with_int() {
5152 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
5153 let result = replace_bool_with_int(true_expr).unwrap();
5154 if let Expression::Literal(Literal::Number(n)) = result {
5155 assert_eq!(n, "1");
5156 } else {
5157 panic!("Expected number literal");
5158 }
5159
5160 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
5161 let result = replace_bool_with_int(false_expr).unwrap();
5162 if let Expression::Literal(Literal::Number(n)) = result {
5163 assert_eq!(n, "0");
5164 } else {
5165 panic!("Expected number literal");
5166 }
5167 }
5168
5169 #[test]
5170 fn test_replace_int_with_bool() {
5171 let one_expr = Expression::Literal(Literal::Number("1".to_string()));
5172 let result = replace_int_with_bool(one_expr).unwrap();
5173 if let Expression::Boolean(b) = result {
5174 assert!(b.value);
5175 } else {
5176 panic!("Expected boolean true");
5177 }
5178
5179 let zero_expr = Expression::Literal(Literal::Number("0".to_string()));
5180 let result = replace_int_with_bool(zero_expr).unwrap();
5181 if let Expression::Boolean(b) = result {
5182 assert!(!b.value);
5183 } else {
5184 panic!("Expected boolean false");
5185 }
5186
5187 let two_expr = Expression::Literal(Literal::Number("2".to_string()));
5189 let result = replace_int_with_bool(two_expr).unwrap();
5190 assert!(matches!(result, Expression::Literal(Literal::Number(_))));
5191 }
5192
5193 #[test]
5194 fn test_strip_data_type_params() {
5195 let decimal = DataType::Decimal {
5197 precision: Some(10),
5198 scale: Some(2),
5199 };
5200 let stripped = strip_data_type_params(decimal);
5201 assert_eq!(
5202 stripped,
5203 DataType::Decimal {
5204 precision: None,
5205 scale: None
5206 }
5207 );
5208
5209 let varchar = DataType::VarChar {
5211 length: Some(255),
5212 parenthesized_length: false,
5213 };
5214 let stripped = strip_data_type_params(varchar);
5215 assert_eq!(
5216 stripped,
5217 DataType::VarChar {
5218 length: None,
5219 parenthesized_length: false
5220 }
5221 );
5222
5223 let char_type = DataType::Char { length: Some(10) };
5225 let stripped = strip_data_type_params(char_type);
5226 assert_eq!(stripped, DataType::Char { length: None });
5227
5228 let timestamp = DataType::Timestamp {
5230 precision: Some(6),
5231 timezone: true,
5232 };
5233 let stripped = strip_data_type_params(timestamp);
5234 assert_eq!(
5235 stripped,
5236 DataType::Timestamp {
5237 precision: None,
5238 timezone: true
5239 }
5240 );
5241
5242 let array = DataType::Array {
5244 element_type: Box::new(DataType::VarChar {
5245 length: Some(100),
5246 parenthesized_length: false,
5247 }),
5248 dimension: None,
5249 };
5250 let stripped = strip_data_type_params(array);
5251 assert_eq!(
5252 stripped,
5253 DataType::Array {
5254 element_type: Box::new(DataType::VarChar {
5255 length: None,
5256 parenthesized_length: false
5257 }),
5258 dimension: None,
5259 }
5260 );
5261
5262 let text = DataType::Text;
5264 let stripped = strip_data_type_params(text);
5265 assert_eq!(stripped, DataType::Text);
5266 }
5267
5268 #[test]
5269 fn test_remove_precision_parameterized_types_cast() {
5270 let cast_expr = Expression::Cast(Box::new(Cast {
5272 this: Expression::Literal(Literal::Number("1".to_string())),
5273 to: DataType::Decimal {
5274 precision: Some(10),
5275 scale: Some(2),
5276 },
5277 trailing_comments: vec![],
5278 double_colon_syntax: false,
5279 format: None,
5280 default: None,
5281 }));
5282
5283 let result = remove_precision_parameterized_types(cast_expr).unwrap();
5284 if let Expression::Cast(cast) = result {
5285 assert_eq!(
5286 cast.to,
5287 DataType::Decimal {
5288 precision: None,
5289 scale: None
5290 }
5291 );
5292 } else {
5293 panic!("Expected Cast expression");
5294 }
5295 }
5296
5297 #[test]
5298 fn test_remove_precision_parameterized_types_varchar() {
5299 let cast_expr = Expression::Cast(Box::new(Cast {
5301 this: Expression::Literal(Literal::String("hello".to_string())),
5302 to: DataType::VarChar {
5303 length: Some(10),
5304 parenthesized_length: false,
5305 },
5306 trailing_comments: vec![],
5307 double_colon_syntax: false,
5308 format: None,
5309 default: None,
5310 }));
5311
5312 let result = remove_precision_parameterized_types(cast_expr).unwrap();
5313 if let Expression::Cast(cast) = result {
5314 assert_eq!(
5315 cast.to,
5316 DataType::VarChar {
5317 length: None,
5318 parenthesized_length: false
5319 }
5320 );
5321 } else {
5322 panic!("Expected Cast expression");
5323 }
5324 }
5325
5326 #[test]
5327 fn test_remove_precision_direct_cast() {
5328 let cast = Expression::Cast(Box::new(Cast {
5332 this: Expression::Literal(Literal::Number("1".to_string())),
5333 to: DataType::Decimal {
5334 precision: Some(10),
5335 scale: Some(2),
5336 },
5337 trailing_comments: vec![],
5338 double_colon_syntax: false,
5339 format: None,
5340 default: None,
5341 }));
5342
5343 let transformed = remove_precision_parameterized_types(cast).unwrap();
5344 let generated = gen(&transformed);
5345
5346 assert!(generated.contains("DECIMAL"));
5348 assert!(!generated.contains("(10"));
5349 }
5350
5351 #[test]
5352 fn test_epoch_cast_to_ts() {
5353 let cast_expr = Expression::Cast(Box::new(Cast {
5355 this: Expression::Literal(Literal::String("epoch".to_string())),
5356 to: DataType::Timestamp {
5357 precision: None,
5358 timezone: false,
5359 },
5360 trailing_comments: vec![],
5361 double_colon_syntax: false,
5362 format: None,
5363 default: None,
5364 }));
5365
5366 let result = epoch_cast_to_ts(cast_expr).unwrap();
5367 if let Expression::Cast(cast) = result {
5368 if let Expression::Literal(Literal::String(s)) = cast.this {
5369 assert_eq!(s, "1970-01-01 00:00:00");
5370 } else {
5371 panic!("Expected string literal");
5372 }
5373 } else {
5374 panic!("Expected Cast expression");
5375 }
5376 }
5377
5378 #[test]
5379 fn test_epoch_cast_to_ts_preserves_non_epoch() {
5380 let cast_expr = Expression::Cast(Box::new(Cast {
5382 this: Expression::Literal(Literal::String("2024-01-15".to_string())),
5383 to: DataType::Timestamp {
5384 precision: None,
5385 timezone: false,
5386 },
5387 trailing_comments: vec![],
5388 double_colon_syntax: false,
5389 format: None,
5390 default: None,
5391 }));
5392
5393 let result = epoch_cast_to_ts(cast_expr).unwrap();
5394 if let Expression::Cast(cast) = result {
5395 if let Expression::Literal(Literal::String(s)) = cast.this {
5396 assert_eq!(s, "2024-01-15");
5397 } else {
5398 panic!("Expected string literal");
5399 }
5400 } else {
5401 panic!("Expected Cast expression");
5402 }
5403 }
5404
5405 #[test]
5406 fn test_unqualify_columns() {
5407 let col = Expression::Column(Column {
5409 name: Identifier::new("id".to_string()),
5410 table: Some(Identifier::new("users".to_string())),
5411 join_mark: false,
5412 trailing_comments: vec![],
5413 });
5414
5415 let result = unqualify_columns(col).unwrap();
5416 if let Expression::Column(c) = result {
5417 assert!(c.table.is_none());
5418 assert_eq!(c.name.name, "id");
5419 } else {
5420 panic!("Expected Column expression");
5421 }
5422 }
5423
5424 #[test]
5425 fn test_is_temporal_type() {
5426 assert!(is_temporal_type(&DataType::Date));
5427 assert!(is_temporal_type(&DataType::Timestamp {
5428 precision: None,
5429 timezone: false
5430 }));
5431 assert!(is_temporal_type(&DataType::Time {
5432 precision: None,
5433 timezone: false
5434 }));
5435 assert!(!is_temporal_type(&DataType::Int {
5436 length: None,
5437 integer_spelling: false
5438 }));
5439 assert!(!is_temporal_type(&DataType::VarChar {
5440 length: None,
5441 parenthesized_length: false
5442 }));
5443 }
5444
5445 #[test]
5446 fn test_eliminate_semi_join_basic() {
5447 use crate::expressions::{Join, TableRef};
5448
5449 let select = Expression::Select(Box::new(Select {
5451 expressions: vec![Expression::Column(Column {
5452 name: Identifier::new("a".to_string()),
5453 table: None,
5454 join_mark: false,
5455 trailing_comments: vec![],
5456 })],
5457 from: Some(From {
5458 expressions: vec![Expression::Table(TableRef::new("t1"))],
5459 }),
5460 joins: vec![Join {
5461 this: Expression::Table(TableRef::new("t2")),
5462 kind: JoinKind::Semi,
5463 on: Some(Expression::Eq(Box::new(BinaryOp {
5464 left: Expression::Column(Column {
5465 name: Identifier::new("x".to_string()),
5466 table: None,
5467 join_mark: false,
5468 trailing_comments: vec![],
5469 }),
5470 right: Expression::Column(Column {
5471 name: Identifier::new("y".to_string()),
5472 table: None,
5473 join_mark: false,
5474 trailing_comments: vec![],
5475 }),
5476 left_comments: vec![],
5477 operator_comments: vec![],
5478 trailing_comments: vec![],
5479 }))),
5480 using: vec![],
5481 use_inner_keyword: false,
5482 use_outer_keyword: false,
5483 deferred_condition: false,
5484 join_hint: None,
5485 match_condition: None,
5486 pivots: Vec::new(),
5487 comments: Vec::new(),
5488 nesting_group: 0,
5489 directed: false,
5490 }],
5491 ..Select::new()
5492 }));
5493
5494 let result = eliminate_semi_and_anti_joins(select).unwrap();
5495 if let Expression::Select(s) = result {
5496 assert!(s.joins.is_empty());
5498 assert!(s.where_clause.is_some());
5500 } else {
5501 panic!("Expected Select expression");
5502 }
5503 }
5504
5505 #[test]
5506 fn test_no_ilike_sql() {
5507 use crate::expressions::LikeOp;
5508
5509 let ilike_expr = Expression::ILike(Box::new(LikeOp {
5511 left: Expression::Column(Column {
5512 name: Identifier::new("name".to_string()),
5513 table: None,
5514 join_mark: false,
5515 trailing_comments: vec![],
5516 }),
5517 right: Expression::Literal(Literal::String("%test%".to_string())),
5518 escape: None,
5519 quantifier: None,
5520 }));
5521
5522 let result = no_ilike_sql(ilike_expr).unwrap();
5523 if let Expression::Like(like) = result {
5524 if let Expression::Function(f) = &like.left {
5526 assert_eq!(f.name, "LOWER");
5527 } else {
5528 panic!("Expected LOWER function on left");
5529 }
5530 if let Expression::Function(f) = &like.right {
5532 assert_eq!(f.name, "LOWER");
5533 } else {
5534 panic!("Expected LOWER function on right");
5535 }
5536 } else {
5537 panic!("Expected Like expression");
5538 }
5539 }
5540
5541 #[test]
5542 fn test_no_trycast_sql() {
5543 let trycast_expr = Expression::TryCast(Box::new(Cast {
5545 this: Expression::Literal(Literal::String("123".to_string())),
5546 to: DataType::Int {
5547 length: None,
5548 integer_spelling: false,
5549 },
5550 trailing_comments: vec![],
5551 double_colon_syntax: false,
5552 format: None,
5553 default: None,
5554 }));
5555
5556 let result = no_trycast_sql(trycast_expr).unwrap();
5557 assert!(matches!(result, Expression::Cast(_)));
5558 }
5559
5560 #[test]
5561 fn test_no_safe_cast_sql() {
5562 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
5564 this: Expression::Literal(Literal::String("123".to_string())),
5565 to: DataType::Int {
5566 length: None,
5567 integer_spelling: false,
5568 },
5569 trailing_comments: vec![],
5570 double_colon_syntax: false,
5571 format: None,
5572 default: None,
5573 }));
5574
5575 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
5576 assert!(matches!(result, Expression::Cast(_)));
5577 }
5578
5579 #[test]
5580 fn test_explode_to_unnest_presto() {
5581 let spark = Dialect::get(DialectType::Spark);
5582 let result = spark
5583 .transpile_to("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
5584 .unwrap();
5585 assert_eq!(
5586 result[0],
5587 "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))"
5588 );
5589 }
5590
5591 #[test]
5592 fn test_explode_to_unnest_bigquery() {
5593 let spark = Dialect::get(DialectType::Spark);
5594 let result = spark
5595 .transpile_to("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
5596 .unwrap();
5597 assert_eq!(
5598 result[0],
5599 "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))"
5600 );
5601 }
5602}