1use crate::dialects::transform_recursive;
10use crate::dialects::{Dialect, DialectType};
11use crate::error::{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, Tuple, UnaryFunc, UnnestFunc, Where, WindowFunction, With,
16 WithinGroup,
17};
18use std::cell::RefCell;
19
20pub fn preprocess<F>(expr: Expression, transforms: &[F]) -> Result<Expression>
29where
30 F: Fn(Expression) -> Result<Expression>,
31{
32 let mut result = expr;
33 for transform in transforms {
34 result = transform(result)?;
35 }
36 Ok(result)
37}
38
39const MAX_TSQL_GROUPING_SETS: usize = 4096;
40
41pub fn expand_distinct_grouping_sets_for_tsql(
44 expr: Expression,
45 target: DialectType,
46) -> Result<Expression> {
47 transform_recursive(expr, &|expr| {
48 let Expression::Select(mut select) = expr else {
49 return Ok(expr);
50 };
51
52 let Some(group_by) = select.group_by.as_mut() else {
53 return Ok(Expression::Select(select));
54 };
55 if group_by.all != Some(false) {
56 return Ok(Expression::Select(select));
57 }
58
59 let mut product = vec![Vec::new()];
60 let mut has_advanced_grouping = false;
61
62 for element in &group_by.expressions {
63 let alternatives = match expand_grouping_element(element, target)? {
64 Some(alternatives) => {
65 has_advanced_grouping = true;
66 alternatives
67 }
68 None => vec![vec![element.clone()]],
69 };
70
71 let expanded_len = product
72 .len()
73 .checked_mul(alternatives.len())
74 .filter(|len| *len <= MAX_TSQL_GROUPING_SETS)
75 .ok_or_else(|| grouping_set_expansion_error(target))?;
76 let mut next = Vec::with_capacity(expanded_len);
77
78 for left in &product {
79 for right in &alternatives {
80 let mut combined = left.clone();
81 for expression in right {
82 if !combined.contains(expression) {
83 combined.push(expression.clone());
84 }
85 }
86 next.push(combined);
87 }
88 }
89 product = next;
90 }
91
92 if !has_advanced_grouping {
93 return Ok(Expression::Select(select));
94 }
95
96 let mut distinct_sets = Vec::with_capacity(product.len());
97 for grouping_set in product {
98 if !distinct_sets.contains(&grouping_set) {
99 distinct_sets.push(grouping_set);
100 }
101 }
102
103 let sets = distinct_sets
104 .into_iter()
105 .map(|expressions| Expression::Tuple(Box::new(Tuple { expressions })))
106 .collect();
107 group_by.all = None;
108 group_by.expressions = vec![Expression::Function(Box::new(Function::new(
109 "GROUPING SETS".to_string(),
110 sets,
111 )))];
112
113 Ok(Expression::Select(select))
114 })
115}
116
117fn expand_grouping_element(
118 expression: &Expression,
119 target: DialectType,
120) -> Result<Option<Vec<Vec<Expression>>>> {
121 match expression {
122 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROLLUP") => {
123 Ok(Some(expand_rollup(&function.args)))
124 }
125 Expression::Function(function) if function.name.eq_ignore_ascii_case("CUBE") => {
126 Ok(Some(expand_cube(&function.args, target)?))
127 }
128 Expression::Function(function) if function.name.eq_ignore_ascii_case("GROUPING SETS") => {
129 Ok(Some(expand_explicit_grouping_sets(&function.args, target)?))
130 }
131 Expression::Rollup(rollup) => Ok(Some(expand_rollup(&rollup.expressions))),
132 Expression::Cube(cube) => Ok(Some(expand_cube(&cube.expressions, target)?)),
133 Expression::GroupingSets(grouping_sets) => Ok(Some(expand_explicit_grouping_sets(
134 &grouping_sets.expressions,
135 target,
136 )?)),
137 _ => Ok(None),
138 }
139}
140
141fn expand_rollup(elements: &[Expression]) -> Vec<Vec<Expression>> {
142 (0..=elements.len())
143 .rev()
144 .map(|end| flatten_grouping_units(&elements[..end]))
145 .collect()
146}
147
148fn expand_cube(elements: &[Expression], target: DialectType) -> Result<Vec<Vec<Expression>>> {
149 let set_count = 1usize
150 .checked_shl(elements.len() as u32)
151 .filter(|count| *count <= MAX_TSQL_GROUPING_SETS)
152 .ok_or_else(|| grouping_set_expansion_error(target))?;
153
154 Ok((0..set_count)
155 .rev()
156 .map(|mask| {
157 let selected = elements
158 .iter()
159 .enumerate()
160 .filter_map(|(index, element)| {
161 let bit = elements.len() - index - 1;
162 (mask & (1usize << bit) != 0).then_some(element)
163 })
164 .cloned()
165 .collect::<Vec<_>>();
166 flatten_grouping_units(&selected)
167 })
168 .collect())
169}
170
171fn expand_explicit_grouping_sets(
172 elements: &[Expression],
173 target: DialectType,
174) -> Result<Vec<Vec<Expression>>> {
175 let mut sets = Vec::new();
176 for element in elements {
177 if let Some(nested) = expand_grouping_element(element, target)? {
178 sets.extend(nested);
179 } else {
180 sets.push(flatten_grouping_unit(element));
181 }
182 if sets.len() > MAX_TSQL_GROUPING_SETS {
183 return Err(grouping_set_expansion_error(target));
184 }
185 }
186 Ok(sets)
187}
188
189fn flatten_grouping_units(elements: &[Expression]) -> Vec<Expression> {
190 elements.iter().flat_map(flatten_grouping_unit).collect()
191}
192
193fn flatten_grouping_unit(expression: &Expression) -> Vec<Expression> {
194 match expression {
195 Expression::Tuple(tuple) => tuple.expressions.clone(),
196 Expression::Paren(paren) => flatten_grouping_unit(&paren.this),
197 _ => vec![expression.clone()],
198 }
199}
200
201fn grouping_set_expansion_error(target: DialectType) -> Error {
202 Error::unsupported(
203 format!("GROUP BY DISTINCT expansion beyond {MAX_TSQL_GROUPING_SETS} grouping sets"),
204 target.to_string(),
205 )
206}
207
208pub fn grouped_percentiles_to_tsql_windows(expr: Expression) -> Result<Expression> {
216 transform_recursive(expr, &grouped_percentiles_to_tsql_windows_inner)
217}
218
219fn grouped_percentiles_to_tsql_windows_inner(expr: Expression) -> Result<Expression> {
220 let Expression::Select(select) = expr else {
221 return Ok(expr);
222 };
223
224 rewrite_grouped_percentile_select(*select).map(|select| Expression::Select(Box::new(select)))
225}
226
227fn rewrite_grouped_percentile_select(select: Select) -> Result<Select> {
228 let Some(group_by) = &select.group_by else {
229 return Ok(select);
230 };
231
232 if select.having.is_some()
233 || group_by.all.is_some()
234 || group_by.totals
235 || group_by.expressions.is_empty()
236 || group_by.expressions.iter().any(is_complex_grouping_expr)
237 {
238 return Ok(select);
239 }
240
241 let partition_by = group_by.expressions.clone();
242 let mut changed = false;
243 let mut rewritten_expressions = Vec::with_capacity(select.expressions.len());
244
245 for expression in &select.expressions {
246 if is_group_projection(expression, &partition_by) {
247 rewritten_expressions.push(expression.clone());
248 continue;
249 }
250
251 let Some(rewritten) = rewrite_grouped_percentile_projection(expression, &partition_by)
252 else {
253 return Ok(select);
254 };
255
256 changed = true;
257 rewritten_expressions.push(rewritten);
258 }
259
260 if !changed {
261 return Ok(select);
262 }
263
264 let mut rewritten = select;
265 rewritten.expressions = rewritten_expressions;
266 rewritten.group_by = None;
267 rewritten.distinct = true;
268 Ok(rewritten)
269}
270
271fn is_complex_grouping_expr(expr: &Expression) -> bool {
272 matches!(
273 expr,
274 Expression::Cube(_) | Expression::Rollup(_) | Expression::GroupingSets(_)
275 ) || matches!(expr, Expression::Function(f) if f.name.eq_ignore_ascii_case("GROUPING SETS"))
276}
277
278fn is_group_projection(expr: &Expression, group_by: &[Expression]) -> bool {
279 let inner = match expr {
280 Expression::Alias(alias) => &alias.this,
281 other => other,
282 };
283
284 group_by.iter().any(|group_expr| inner == group_expr)
285}
286
287fn rewrite_grouped_percentile_projection(
288 expr: &Expression,
289 partition_by: &[Expression],
290) -> Option<Expression> {
291 match expr {
292 Expression::Alias(alias) => {
293 let rewritten = rewrite_grouped_percentile_expr(&alias.this, partition_by)?;
294 let mut alias = alias.as_ref().clone();
295 alias.this = rewritten;
296 Some(Expression::Alias(Box::new(alias)))
297 }
298 other => rewrite_grouped_percentile_expr(other, partition_by),
299 }
300}
301
302fn rewrite_grouped_percentile_expr(
303 expr: &Expression,
304 partition_by: &[Expression],
305) -> Option<Expression> {
306 let Expression::WithinGroup(within_group) = expr else {
307 return None;
308 };
309
310 if !is_percentile_ordered_set(&within_group.this) || within_group.order_by.len() != 1 {
311 return None;
312 }
313
314 let mut order_by = within_group.order_by.clone();
315 order_by[0].nulls_first = None;
319
320 Some(Expression::WindowFunction(Box::new(WindowFunction {
321 this: Expression::WithinGroup(Box::new(WithinGroup {
322 this: within_group.this.clone(),
323 order_by,
324 })),
325 over: Over {
326 window_name: None,
327 partition_by: partition_by.to_vec(),
328 order_by: Vec::new(),
329 frame: None,
330 alias: None,
331 },
332 keep: None,
333 inferred_type: None,
334 })))
335}
336
337fn is_percentile_ordered_set(expr: &Expression) -> bool {
338 match expr {
339 Expression::Function(function) => is_percentile_name(&function.name),
340 Expression::AggregateFunction(function) => is_percentile_name(&function.name),
341 Expression::PercentileCont(_) | Expression::PercentileDisc(_) => true,
342 _ => false,
343 }
344}
345
346fn is_percentile_name(name: &str) -> bool {
347 name.eq_ignore_ascii_case("PERCENTILE_CONT") || name.eq_ignore_ascii_case("PERCENTILE_DISC")
348}
349
350pub fn unnest_to_explode(expr: Expression) -> Result<Expression> {
354 match expr {
355 Expression::Unnest(unnest) => {
356 Ok(Expression::Explode(Box::new(UnaryFunc::new(unnest.this))))
357 }
358 _ => Ok(expr),
359 }
360}
361
362pub fn unnest_to_explode_select(expr: Expression) -> Result<Expression> {
372 transform_recursive(expr, &unnest_to_explode_select_inner)
373}
374
375fn make_udtf_expr(unnest: &UnnestFunc) -> Expression {
378 let has_multi_expr = !unnest.expressions.is_empty();
379 if has_multi_expr {
380 let mut all_args = vec![unnest.this.clone()];
382 all_args.extend(unnest.expressions.iter().cloned());
383 let arrays_zip =
384 Expression::Function(Box::new(Function::new("ARRAYS_ZIP".to_string(), all_args)));
385 Expression::Function(Box::new(Function::new(
386 "INLINE".to_string(),
387 vec![arrays_zip],
388 )))
389 } else {
390 Expression::Explode(Box::new(UnaryFunc::new(unnest.this.clone())))
392 }
393}
394
395fn unnest_to_explode_select_inner(expr: Expression) -> Result<Expression> {
396 let Expression::Select(mut select) = expr else {
397 return Ok(expr);
398 };
399
400 if let Some(ref mut from) = select.from {
402 if from.expressions.len() >= 1 {
403 let mut new_from_exprs = Vec::new();
404 let mut new_lateral_views = Vec::new();
405 let first_is_unnest = is_unnest_expr(&from.expressions[0]);
406
407 for (idx, from_item) in from.expressions.drain(..).enumerate() {
408 if idx == 0 && first_is_unnest {
409 let replaced = replace_from_unnest(from_item);
412 new_from_exprs.push(replaced);
413 } else if idx > 0 && is_unnest_expr(&from_item) {
414 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(from_item);
416 let udtf = make_udtf_expr(&unnest_func);
417 new_lateral_views.push(LateralView {
418 this: udtf,
419 table_alias: alias_name,
420 column_aliases,
421 outer: false,
422 });
423 } else {
424 new_from_exprs.push(from_item);
425 }
426 }
427
428 from.expressions = new_from_exprs;
429 select.lateral_views.extend(new_lateral_views);
431 }
432 }
433
434 let mut remaining_joins = Vec::new();
436 for join in select.joins.drain(..) {
437 if matches!(join.kind, JoinKind::Cross | JoinKind::Inner) {
438 let (is_unnest, is_lateral) = check_join_unnest(&join.this);
439 if is_unnest {
440 let (lateral_alias, lateral_col_aliases, join_expr) = if is_lateral {
442 if let Expression::Lateral(lat) = join.this {
443 let alias = lat.alias.map(|s| Identifier::new(&s));
445 let col_aliases: Vec<Identifier> = lat
446 .column_aliases
447 .iter()
448 .map(|s| Identifier::new(s))
449 .collect();
450 (alias, col_aliases, *lat.this)
451 } else {
452 (None, Vec::new(), join.this)
453 }
454 } else {
455 (None, Vec::new(), join.this)
456 };
457
458 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(join_expr);
459
460 let final_alias = lateral_alias.or(alias_name);
462 let final_col_aliases = if !lateral_col_aliases.is_empty() {
463 lateral_col_aliases
464 } else {
465 column_aliases
466 };
467
468 let table_alias = final_alias.or_else(|| Some(Identifier::new("unnest")));
470 let col_aliases = if final_col_aliases.is_empty() {
471 vec![Identifier::new("unnest")]
472 } else {
473 final_col_aliases
474 };
475
476 let udtf = make_udtf_expr(&unnest_func);
477 select.lateral_views.push(LateralView {
478 this: udtf,
479 table_alias,
480 column_aliases: col_aliases,
481 outer: false,
482 });
483 } else {
484 remaining_joins.push(join);
485 }
486 } else {
487 remaining_joins.push(join);
488 }
489 }
490 select.joins = remaining_joins;
491
492 Ok(Expression::Select(select))
493}
494
495fn is_unnest_expr(expr: &Expression) -> bool {
497 match expr {
498 Expression::Unnest(_) => true,
499 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
500 _ => false,
501 }
502}
503
504fn check_join_unnest(expr: &Expression) -> (bool, bool) {
506 match expr {
507 Expression::Unnest(_) => (true, false),
508 Expression::Alias(a) => {
509 if matches!(a.this, Expression::Unnest(_)) {
510 (true, false)
511 } else {
512 (false, false)
513 }
514 }
515 Expression::Lateral(lat) => match &*lat.this {
516 Expression::Unnest(_) => (true, true),
517 Expression::Alias(a) => {
518 if matches!(a.this, Expression::Unnest(_)) {
519 (true, true)
520 } else {
521 (false, true)
522 }
523 }
524 _ => (false, true),
525 },
526 _ => (false, false),
527 }
528}
529
530fn replace_from_unnest(from_item: Expression) -> Expression {
532 match from_item {
533 Expression::Alias(mut a) => {
534 if let Expression::Unnest(unnest) = a.this {
535 a.this = make_udtf_expr(&unnest);
536 }
537 Expression::Alias(a)
538 }
539 Expression::Unnest(unnest) => make_udtf_expr(&unnest),
540 other => other,
541 }
542}
543
544fn extract_unnest_info(expr: Expression) -> (Option<Identifier>, Vec<Identifier>, UnnestFunc) {
546 match expr {
547 Expression::Alias(a) => {
548 if let Expression::Unnest(unnest) = a.this {
549 (Some(a.alias), a.column_aliases, *unnest)
550 } else {
551 (
553 Some(a.alias),
554 a.column_aliases,
555 UnnestFunc {
556 this: a.this,
557 expressions: Vec::new(),
558 with_ordinality: false,
559 alias: None,
560 offset_alias: None,
561 },
562 )
563 }
564 }
565 Expression::Unnest(unnest) => {
566 let alias = unnest.alias.clone();
567 (alias, Vec::new(), *unnest)
568 }
569 _ => (
570 None,
571 Vec::new(),
572 UnnestFunc {
573 this: expr,
574 expressions: Vec::new(),
575 with_ordinality: false,
576 alias: None,
577 offset_alias: None,
578 },
579 ),
580 }
581}
582
583pub fn explode_to_unnest(expr: Expression) -> Result<Expression> {
585 match expr {
586 Expression::Explode(explode) => Ok(Expression::Unnest(Box::new(UnnestFunc {
587 this: explode.this,
588 expressions: Vec::new(),
589 with_ordinality: false,
590 alias: None,
591 offset_alias: None,
592 }))),
593 _ => Ok(expr),
594 }
595}
596
597pub fn replace_bool_with_int(expr: Expression) -> Result<Expression> {
601 match expr {
602 Expression::Boolean(b) => {
603 let value = if b.value { "1" } else { "0" };
604 Ok(Expression::Literal(Box::new(Literal::Number(
605 value.to_string(),
606 ))))
607 }
608 _ => Ok(expr),
609 }
610}
611
612pub fn replace_int_with_bool(expr: Expression) -> Result<Expression> {
616 match expr {
617 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(n) if n == "1" || n == "0") =>
618 {
619 let Literal::Number(n) = lit.as_ref() else {
620 unreachable!()
621 };
622 Ok(Expression::Boolean(BooleanLiteral { value: n == "1" }))
623 }
624 _ => Ok(expr),
625 }
626}
627
628pub fn remove_precision_parameterized_types(expr: Expression) -> Result<Expression> {
633 Ok(strip_type_params_recursive(expr))
634}
635
636fn strip_type_params_recursive(expr: Expression) -> Expression {
638 match expr {
639 Expression::Cast(mut cast) => {
641 cast.to = strip_data_type_params(cast.to);
642 cast.this = strip_type_params_recursive(cast.this);
644 Expression::Cast(cast)
645 }
646 Expression::TryCast(mut try_cast) => {
648 try_cast.to = strip_data_type_params(try_cast.to);
649 try_cast.this = strip_type_params_recursive(try_cast.this);
650 Expression::TryCast(try_cast)
651 }
652 Expression::SafeCast(mut safe_cast) => {
654 safe_cast.to = strip_data_type_params(safe_cast.to);
655 safe_cast.this = strip_type_params_recursive(safe_cast.this);
656 Expression::SafeCast(safe_cast)
657 }
658 _ => expr,
661 }
662}
663
664fn strip_data_type_params(dt: DataType) -> DataType {
666 match dt {
667 DataType::Decimal { .. } => DataType::Decimal {
669 precision: None,
670 scale: None,
671 },
672 DataType::TinyInt { .. } => DataType::TinyInt { length: None },
673 DataType::SmallInt { .. } => DataType::SmallInt { length: None },
674 DataType::Int { .. } => DataType::Int {
675 length: None,
676 integer_spelling: false,
677 },
678 DataType::BigInt { .. } => DataType::BigInt { length: None },
679
680 DataType::Char { .. } => DataType::Char { length: None },
682 DataType::VarChar { .. } => DataType::VarChar {
683 length: None,
684 parenthesized_length: false,
685 },
686
687 DataType::Binary { .. } => DataType::Binary { length: None },
689 DataType::VarBinary { .. } => DataType::VarBinary { length: None },
690
691 DataType::Bit { .. } => DataType::Bit { length: None },
693 DataType::VarBit { .. } => DataType::VarBit { length: None },
694
695 DataType::Time { .. } => DataType::Time {
697 precision: None,
698 timezone: false,
699 },
700 DataType::Timestamp { timezone, .. } => DataType::Timestamp {
701 precision: None,
702 timezone,
703 },
704
705 DataType::Array {
707 element_type,
708 dimension,
709 } => DataType::Array {
710 element_type: Box::new(strip_data_type_params(*element_type)),
711 dimension,
712 },
713
714 DataType::Map {
716 key_type,
717 value_type,
718 } => DataType::Map {
719 key_type: Box::new(strip_data_type_params(*key_type)),
720 value_type: Box::new(strip_data_type_params(*value_type)),
721 },
722
723 DataType::Struct { fields, nested } => DataType::Struct {
725 fields: fields
726 .into_iter()
727 .map(|f| {
728 StructField::with_options(
729 f.name,
730 strip_data_type_params(f.data_type),
731 f.options,
732 )
733 })
734 .collect(),
735 nested,
736 },
737
738 DataType::Vector { element_type, .. } => DataType::Vector {
740 element_type: element_type.map(|et| Box::new(strip_data_type_params(*et))),
741 dimension: None,
742 },
743
744 DataType::Object { fields, modifier } => DataType::Object {
746 fields: fields
747 .into_iter()
748 .map(|(name, ty, not_null)| (name, strip_data_type_params(ty), not_null))
749 .collect(),
750 modifier,
751 },
752
753 other => other,
755 }
756}
757
758pub fn eliminate_qualify(expr: Expression) -> Result<Expression> {
773 match expr {
774 Expression::Select(mut select) => {
775 if let Some(qualify) = select.qualify.take() {
776 let qualify_filter = qualify.this;
783 let window_alias_name = "_w".to_string();
784 let window_alias_ident = Identifier::new(window_alias_name.clone());
785
786 let (window_expr, outer_where) =
789 extract_window_from_condition(qualify_filter.clone(), &window_alias_ident);
790
791 if let Some(win_expr) = window_expr {
792 let window_alias_expr =
794 Expression::Alias(Box::new(crate::expressions::Alias {
795 this: win_expr,
796 alias: window_alias_ident.clone(),
797 column_aliases: vec![],
798 alias_explicit_as: false,
799 alias_keyword: None,
800 pre_alias_comments: vec![],
801 trailing_comments: vec![],
802 inferred_type: None,
803 }));
804
805 let outer_exprs: Vec<Expression> = select
809 .expressions
810 .iter()
811 .map(|expr| {
812 if let Expression::Alias(a) = expr {
813 Expression::Column(Box::new(crate::expressions::Column {
815 name: a.alias.clone(),
816 table: None,
817 join_mark: false,
818 trailing_comments: vec![],
819 span: None,
820 inferred_type: None,
821 }))
822 } else {
823 expr.clone()
824 }
825 })
826 .collect();
827 select.expressions.push(window_alias_expr);
828
829 let inner_select = Expression::Select(select);
831 let subquery = Subquery {
832 this: inner_select,
833 alias: Some(Identifier::new("_t".to_string())),
834 column_aliases: vec![],
835 alias_explicit_as: false,
836 alias_keyword: None,
837 order_by: None,
838 limit: None,
839 offset: None,
840 distribute_by: None,
841 sort_by: None,
842 cluster_by: None,
843 lateral: false,
844 modifiers_inside: false,
845 trailing_comments: vec![],
846 inferred_type: None,
847 };
848
849 let outer_select = Select {
851 expressions: outer_exprs,
852 from: Some(From {
853 expressions: vec![Expression::Subquery(Box::new(subquery))],
854 }),
855 where_clause: Some(Where { this: outer_where }),
856 ..Select::new()
857 };
858
859 return Ok(Expression::Select(Box::new(outer_select)));
860 } else {
861 let qualify_alias = Expression::Alias(Box::new(crate::expressions::Alias {
863 this: qualify_filter.clone(),
864 alias: window_alias_ident.clone(),
865 column_aliases: vec![],
866 alias_explicit_as: false,
867 alias_keyword: None,
868 pre_alias_comments: vec![],
869 trailing_comments: vec![],
870 inferred_type: None,
871 }));
872
873 let original_exprs = select.expressions.clone();
874 select.expressions.push(qualify_alias);
875
876 let inner_select = Expression::Select(select);
877 let subquery = Subquery {
878 this: inner_select,
879 alias: Some(Identifier::new("_t".to_string())),
880 column_aliases: vec![],
881 alias_explicit_as: false,
882 alias_keyword: None,
883 order_by: None,
884 limit: None,
885 offset: None,
886 distribute_by: None,
887 sort_by: None,
888 cluster_by: None,
889 lateral: false,
890 modifiers_inside: false,
891 trailing_comments: vec![],
892 inferred_type: None,
893 };
894
895 let outer_select = Select {
896 expressions: original_exprs,
897 from: Some(From {
898 expressions: vec![Expression::Subquery(Box::new(subquery))],
899 }),
900 where_clause: Some(Where {
901 this: Expression::Column(Box::new(crate::expressions::Column {
902 name: window_alias_ident,
903 table: None,
904 join_mark: false,
905 trailing_comments: vec![],
906 span: None,
907 inferred_type: None,
908 })),
909 }),
910 ..Select::new()
911 };
912
913 return Ok(Expression::Select(Box::new(outer_select)));
914 }
915 }
916 Ok(Expression::Select(select))
917 }
918 other => Ok(other),
919 }
920}
921
922fn extract_window_from_condition(
926 condition: Expression,
927 alias: &Identifier,
928) -> (Option<Expression>, Expression) {
929 let alias_col = Expression::Column(Box::new(crate::expressions::Column {
930 name: alias.clone(),
931 table: None,
932 join_mark: false,
933 trailing_comments: vec![],
934 span: None,
935 inferred_type: None,
936 }));
937
938 match condition {
940 Expression::Eq(ref op) => {
942 if is_window_expr(&op.left) {
943 (
944 Some(op.left.clone()),
945 Expression::Eq(Box::new(BinaryOp {
946 left: alias_col,
947 right: op.right.clone(),
948 ..(**op).clone()
949 })),
950 )
951 } else if is_window_expr(&op.right) {
952 (
953 Some(op.right.clone()),
954 Expression::Eq(Box::new(BinaryOp {
955 left: op.left.clone(),
956 right: alias_col,
957 ..(**op).clone()
958 })),
959 )
960 } else {
961 (None, condition)
962 }
963 }
964 Expression::Neq(ref op) => {
965 if is_window_expr(&op.left) {
966 (
967 Some(op.left.clone()),
968 Expression::Neq(Box::new(BinaryOp {
969 left: alias_col,
970 right: op.right.clone(),
971 ..(**op).clone()
972 })),
973 )
974 } else if is_window_expr(&op.right) {
975 (
976 Some(op.right.clone()),
977 Expression::Neq(Box::new(BinaryOp {
978 left: op.left.clone(),
979 right: alias_col,
980 ..(**op).clone()
981 })),
982 )
983 } else {
984 (None, condition)
985 }
986 }
987 Expression::Lt(ref op) => {
988 if is_window_expr(&op.left) {
989 (
990 Some(op.left.clone()),
991 Expression::Lt(Box::new(BinaryOp {
992 left: alias_col,
993 right: op.right.clone(),
994 ..(**op).clone()
995 })),
996 )
997 } else if is_window_expr(&op.right) {
998 (
999 Some(op.right.clone()),
1000 Expression::Lt(Box::new(BinaryOp {
1001 left: op.left.clone(),
1002 right: alias_col,
1003 ..(**op).clone()
1004 })),
1005 )
1006 } else {
1007 (None, condition)
1008 }
1009 }
1010 Expression::Lte(ref op) => {
1011 if is_window_expr(&op.left) {
1012 (
1013 Some(op.left.clone()),
1014 Expression::Lte(Box::new(BinaryOp {
1015 left: alias_col,
1016 right: op.right.clone(),
1017 ..(**op).clone()
1018 })),
1019 )
1020 } else if is_window_expr(&op.right) {
1021 (
1022 Some(op.right.clone()),
1023 Expression::Lte(Box::new(BinaryOp {
1024 left: op.left.clone(),
1025 right: alias_col,
1026 ..(**op).clone()
1027 })),
1028 )
1029 } else {
1030 (None, condition)
1031 }
1032 }
1033 Expression::Gt(ref op) => {
1034 if is_window_expr(&op.left) {
1035 (
1036 Some(op.left.clone()),
1037 Expression::Gt(Box::new(BinaryOp {
1038 left: alias_col,
1039 right: op.right.clone(),
1040 ..(**op).clone()
1041 })),
1042 )
1043 } else if is_window_expr(&op.right) {
1044 (
1045 Some(op.right.clone()),
1046 Expression::Gt(Box::new(BinaryOp {
1047 left: op.left.clone(),
1048 right: alias_col,
1049 ..(**op).clone()
1050 })),
1051 )
1052 } else {
1053 (None, condition)
1054 }
1055 }
1056 Expression::Gte(ref op) => {
1057 if is_window_expr(&op.left) {
1058 (
1059 Some(op.left.clone()),
1060 Expression::Gte(Box::new(BinaryOp {
1061 left: alias_col,
1062 right: op.right.clone(),
1063 ..(**op).clone()
1064 })),
1065 )
1066 } else if is_window_expr(&op.right) {
1067 (
1068 Some(op.right.clone()),
1069 Expression::Gte(Box::new(BinaryOp {
1070 left: op.left.clone(),
1071 right: alias_col,
1072 ..(**op).clone()
1073 })),
1074 )
1075 } else {
1076 (None, condition)
1077 }
1078 }
1079 _ if is_window_expr(&condition) => (Some(condition), alias_col),
1081 _ => (None, condition),
1083 }
1084}
1085
1086fn is_window_expr(expr: &Expression) -> bool {
1088 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
1089}
1090
1091pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
1110 eliminate_distinct_on_for_dialect(expr, None, None)
1111}
1112
1113pub fn strip_cte_materialization(expr: Expression) -> Result<Expression> {
1116 transform_recursive(expr, &strip_cte_materialization_single)
1117}
1118
1119fn strip_cte_materialization_single(expr: Expression) -> Result<Expression> {
1120 Ok(match expr {
1121 Expression::Select(mut select) => {
1122 strip_with_cte_materialization(&mut select.with);
1123 Expression::Select(select)
1124 }
1125 Expression::Union(mut union) => {
1126 strip_with_cte_materialization(&mut union.with);
1127 Expression::Union(union)
1128 }
1129 Expression::Intersect(mut intersect) => {
1130 strip_with_cte_materialization(&mut intersect.with);
1131 Expression::Intersect(intersect)
1132 }
1133 Expression::Except(mut except) => {
1134 strip_with_cte_materialization(&mut except.with);
1135 Expression::Except(except)
1136 }
1137 Expression::Pivot(mut pivot) => {
1138 strip_with_cte_materialization(&mut pivot.with);
1139 Expression::Pivot(pivot)
1140 }
1141 Expression::Insert(mut insert) => {
1142 strip_with_cte_materialization(&mut insert.with);
1143 Expression::Insert(insert)
1144 }
1145 Expression::Update(mut update) => {
1146 strip_with_cte_materialization(&mut update.with);
1147 Expression::Update(update)
1148 }
1149 Expression::Delete(mut delete) => {
1150 strip_with_cte_materialization(&mut delete.with);
1151 Expression::Delete(delete)
1152 }
1153 Expression::CreateTable(mut create_table) => {
1154 strip_with_cte_materialization(&mut create_table.with_cte);
1155 Expression::CreateTable(create_table)
1156 }
1157 Expression::With(mut with) => {
1158 strip_cte_materialization_in_with(&mut with);
1159 Expression::With(with)
1160 }
1161 Expression::Cte(mut cte) => {
1162 cte.materialized = None;
1163 Expression::Cte(cte)
1164 }
1165 _ => expr,
1166 })
1167}
1168
1169fn strip_with_cte_materialization(with: &mut Option<With>) {
1170 if let Some(with) = with {
1171 strip_cte_materialization_in_with(with);
1172 }
1173}
1174
1175fn strip_cte_materialization_in_with(with: &mut With) {
1176 for cte in &mut with.ctes {
1177 cte.materialized = None;
1178 }
1179}
1180
1181#[derive(Clone, Copy)]
1182enum DistinctOnNullsMode {
1183 None,
1184 NullsFirst,
1185 CaseExpr,
1186}
1187
1188pub fn eliminate_distinct_on_for_dialect(
1193 expr: Expression,
1194 target: Option<DialectType>,
1195 source: Option<DialectType>,
1196) -> Result<Expression> {
1197 if matches!(
1199 target,
1200 Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)
1201 ) {
1202 return Ok(expr);
1203 }
1204
1205 let nulls_mode = match target {
1210 Some(DialectType::MySQL)
1211 | Some(DialectType::SingleStore)
1212 | Some(DialectType::TSQL)
1213 | Some(DialectType::Fabric) => DistinctOnNullsMode::CaseExpr,
1214 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => {
1215 DistinctOnNullsMode::None
1216 }
1217 Some(DialectType::StarRocks) => {
1218 if matches!(source, Some(DialectType::Redshift)) {
1219 DistinctOnNullsMode::CaseExpr
1220 } else {
1221 DistinctOnNullsMode::None
1222 }
1223 }
1224 _ => DistinctOnNullsMode::NullsFirst,
1226 };
1227
1228 transform_recursive(expr, &|expr| eliminate_distinct_on_select(expr, nulls_mode))
1229}
1230
1231fn eliminate_distinct_on_select(
1232 expr: Expression,
1233 nulls_mode: DistinctOnNullsMode,
1234) -> Result<Expression> {
1235 use crate::expressions::Case;
1236
1237 match expr {
1238 Expression::Select(mut select) => {
1239 if let Some(distinct_cols) = select.distinct_on.take() {
1240 if !distinct_cols.is_empty() {
1241 let row_number_alias = Identifier::new("_row_number".to_string());
1243
1244 let order_exprs = if let Some(ref order_by) = select.order_by {
1246 let mut exprs = order_by.expressions.clone();
1247 match nulls_mode {
1249 DistinctOnNullsMode::NullsFirst => {
1250 for ord in &mut exprs {
1251 if ord.desc && ord.nulls_first.is_none() {
1252 ord.nulls_first = Some(true);
1253 }
1254 }
1255 }
1256 DistinctOnNullsMode::CaseExpr => {
1257 let mut new_exprs = Vec::new();
1260 for ord in &exprs {
1261 if ord.desc && ord.nulls_first.is_none() {
1262 let null_check = Expression::Case(Box::new(Case {
1264 operand: None,
1265 whens: vec![(
1266 Expression::IsNull(Box::new(
1267 crate::expressions::IsNull {
1268 this: ord.this.clone(),
1269 not: false,
1270 postfix_form: false,
1271 },
1272 )),
1273 Expression::Literal(Box::new(Literal::Number(
1274 "1".to_string(),
1275 ))),
1276 )],
1277 else_: Some(Expression::Literal(Box::new(
1278 Literal::Number("0".to_string()),
1279 ))),
1280 comments: Vec::new(),
1281 inferred_type: None,
1282 }));
1283 new_exprs.push(crate::expressions::Ordered {
1284 this: null_check,
1285 desc: true,
1286 nulls_first: None,
1287 explicit_asc: false,
1288 with_fill: None,
1289 });
1290 }
1291 new_exprs.push(ord.clone());
1292 }
1293 exprs = new_exprs;
1294 }
1295 DistinctOnNullsMode::None => {}
1296 }
1297 exprs
1298 } else {
1299 distinct_cols
1300 .iter()
1301 .map(|e| crate::expressions::Ordered {
1302 this: e.clone(),
1303 desc: false,
1304 nulls_first: None,
1305 explicit_asc: false,
1306 with_fill: None,
1307 })
1308 .collect()
1309 };
1310
1311 let row_number_func =
1313 Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
1314 this: Expression::RowNumber(crate::expressions::RowNumber),
1315 over: Over {
1316 partition_by: distinct_cols,
1317 order_by: order_exprs,
1318 frame: None,
1319 window_name: None,
1320 alias: None,
1321 },
1322 keep: None,
1323 inferred_type: None,
1324 }));
1325
1326 let mut inner_aliased_exprs = Vec::new();
1330 let mut outer_select_exprs = Vec::new();
1331 for orig_expr in &select.expressions {
1332 match orig_expr {
1333 Expression::Alias(alias) => {
1334 inner_aliased_exprs.push(orig_expr.clone());
1336 outer_select_exprs.push(Expression::Column(Box::new(
1337 crate::expressions::Column {
1338 name: alias.alias.clone(),
1339 table: None,
1340 join_mark: false,
1341 trailing_comments: vec![],
1342 span: None,
1343 inferred_type: None,
1344 },
1345 )));
1346 }
1347 Expression::Column(col) => {
1348 inner_aliased_exprs.push(Expression::Alias(Box::new(
1350 crate::expressions::Alias {
1351 this: orig_expr.clone(),
1352 alias: col.name.clone(),
1353 column_aliases: vec![],
1354 alias_explicit_as: false,
1355 alias_keyword: None,
1356 pre_alias_comments: vec![],
1357 trailing_comments: vec![],
1358 inferred_type: None,
1359 },
1360 )));
1361 outer_select_exprs.push(Expression::Column(Box::new(
1362 crate::expressions::Column {
1363 name: col.name.clone(),
1364 table: None,
1365 join_mark: false,
1366 trailing_comments: vec![],
1367 span: None,
1368 inferred_type: None,
1369 },
1370 )));
1371 }
1372 _ => {
1373 inner_aliased_exprs.push(orig_expr.clone());
1375 outer_select_exprs.push(orig_expr.clone());
1376 }
1377 }
1378 }
1379
1380 let row_number_alias_expr =
1382 Expression::Alias(Box::new(crate::expressions::Alias {
1383 this: row_number_func,
1384 alias: row_number_alias.clone(),
1385 column_aliases: vec![],
1386 alias_explicit_as: false,
1387 alias_keyword: None,
1388 pre_alias_comments: vec![],
1389 trailing_comments: vec![],
1390 inferred_type: None,
1391 }));
1392 inner_aliased_exprs.push(row_number_alias_expr);
1393
1394 select.expressions = inner_aliased_exprs;
1396
1397 let _inner_order_by = select.order_by.take();
1399
1400 select.distinct = false;
1402
1403 let inner_select = Expression::Select(select);
1405 let subquery = Subquery {
1406 this: inner_select,
1407 alias: Some(Identifier::new("_t".to_string())),
1408 column_aliases: vec![],
1409 alias_explicit_as: false,
1410 alias_keyword: None,
1411 order_by: None,
1412 limit: None,
1413 offset: None,
1414 distribute_by: None,
1415 sort_by: None,
1416 cluster_by: None,
1417 lateral: false,
1418 modifiers_inside: false,
1419 trailing_comments: vec![],
1420 inferred_type: None,
1421 };
1422
1423 let outer_select = Select {
1426 expressions: outer_select_exprs,
1427 from: Some(From {
1428 expressions: vec![Expression::Subquery(Box::new(subquery))],
1429 }),
1430 where_clause: Some(Where {
1431 this: Expression::Eq(Box::new(BinaryOp {
1432 left: Expression::Column(Box::new(crate::expressions::Column {
1433 name: row_number_alias,
1434 table: None,
1435 join_mark: false,
1436 trailing_comments: vec![],
1437 span: None,
1438 inferred_type: None,
1439 })),
1440 right: Expression::Literal(Box::new(Literal::Number(
1441 "1".to_string(),
1442 ))),
1443 left_comments: vec![],
1444 operator_comments: vec![],
1445 trailing_comments: vec![],
1446 inferred_type: None,
1447 })),
1448 }),
1449 ..Select::new()
1450 };
1451
1452 return Ok(Expression::Select(Box::new(outer_select)));
1453 }
1454 }
1455 Ok(Expression::Select(select))
1456 }
1457 other => Ok(other),
1458 }
1459}
1460
1461pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
1469 match expr {
1470 Expression::Select(mut select) => {
1471 let mut new_joins = Vec::new();
1472 let mut extra_where_conditions = Vec::new();
1473
1474 for join in select.joins.drain(..) {
1475 match join.kind {
1476 JoinKind::Semi | JoinKind::LeftSemi => {
1477 if let Some(on_condition) = join.on {
1478 let subquery_select = Select {
1480 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1481 "1".to_string(),
1482 )))],
1483 from: Some(From {
1484 expressions: vec![join.this],
1485 }),
1486 where_clause: Some(Where { this: on_condition }),
1487 ..Select::new()
1488 };
1489
1490 let exists = Expression::Exists(Box::new(Exists {
1491 this: Expression::Subquery(Box::new(Subquery {
1492 this: Expression::Select(Box::new(subquery_select)),
1493 alias: None,
1494 column_aliases: vec![],
1495 alias_explicit_as: false,
1496 alias_keyword: None,
1497 order_by: None,
1498 limit: None,
1499 offset: None,
1500 distribute_by: None,
1501 sort_by: None,
1502 cluster_by: None,
1503 lateral: false,
1504 modifiers_inside: false,
1505 trailing_comments: vec![],
1506 inferred_type: None,
1507 })),
1508 not: false,
1509 }));
1510
1511 extra_where_conditions.push(exists);
1512 }
1513 }
1514 JoinKind::Anti | JoinKind::LeftAnti => {
1515 if let Some(on_condition) = join.on {
1516 let subquery_select = Select {
1518 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1519 "1".to_string(),
1520 )))],
1521 from: Some(From {
1522 expressions: vec![join.this],
1523 }),
1524 where_clause: Some(Where { this: on_condition }),
1525 ..Select::new()
1526 };
1527
1528 let not_exists = Expression::Exists(Box::new(Exists {
1530 this: Expression::Subquery(Box::new(Subquery {
1531 this: Expression::Select(Box::new(subquery_select)),
1532 alias: None,
1533 column_aliases: vec![],
1534 alias_explicit_as: false,
1535 alias_keyword: None,
1536 order_by: None,
1537 limit: None,
1538 offset: None,
1539 distribute_by: None,
1540 sort_by: None,
1541 cluster_by: None,
1542 lateral: false,
1543 modifiers_inside: false,
1544 trailing_comments: vec![],
1545 inferred_type: None,
1546 })),
1547 not: true,
1548 }));
1549
1550 extra_where_conditions.push(not_exists);
1551 }
1552 }
1553 _ => {
1554 new_joins.push(join);
1556 }
1557 }
1558 }
1559
1560 select.joins = new_joins;
1561
1562 if !extra_where_conditions.is_empty() {
1564 let combined = extra_where_conditions
1565 .into_iter()
1566 .reduce(|acc, cond| {
1567 Expression::And(Box::new(BinaryOp {
1568 left: acc,
1569 right: cond,
1570 left_comments: vec![],
1571 operator_comments: vec![],
1572 trailing_comments: vec![],
1573 inferred_type: None,
1574 }))
1575 })
1576 .unwrap();
1577
1578 select.where_clause = match select.where_clause {
1579 Some(Where { this: existing }) => Some(Where {
1580 this: Expression::And(Box::new(BinaryOp {
1581 left: existing,
1582 right: combined,
1583 left_comments: vec![],
1584 operator_comments: vec![],
1585 trailing_comments: vec![],
1586 inferred_type: None,
1587 })),
1588 }),
1589 None => Some(Where { this: combined }),
1590 };
1591 }
1592
1593 Ok(Expression::Select(select))
1594 }
1595 other => Ok(other),
1596 }
1597}
1598
1599pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
1617 match expr {
1618 Expression::Select(mut select) => {
1619 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
1621
1622 if let Some(idx) = full_outer_join_idx {
1623 let full_join_count = select
1625 .joins
1626 .iter()
1627 .filter(|j| j.kind == JoinKind::Full)
1628 .count();
1629 if full_join_count != 1 {
1630 return Ok(Expression::Select(select));
1631 }
1632
1633 let mut right_select = select.clone();
1635
1636 let full_join = &select.joins[idx];
1638 let join_condition = full_join.on.clone();
1639
1640 select.joins[idx].kind = JoinKind::Left;
1642
1643 right_select.joins[idx].kind = JoinKind::Right;
1645
1646 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
1648 if !from.expressions.is_empty() {
1649 let anti_subquery = Expression::Select(Box::new(Select {
1650 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1651 "1".to_string(),
1652 )))],
1653 from: Some(from.clone()),
1654 where_clause: Some(Where {
1655 this: join_cond.clone(),
1656 }),
1657 ..Select::new()
1658 }));
1659
1660 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
1661 inferred_type: None,
1662 this: Expression::Exists(Box::new(Exists {
1663 this: Expression::Subquery(Box::new(Subquery {
1664 this: anti_subquery,
1665 alias: None,
1666 column_aliases: vec![],
1667 alias_explicit_as: false,
1668 alias_keyword: None,
1669 order_by: None,
1670 limit: None,
1671 offset: None,
1672 distribute_by: None,
1673 sort_by: None,
1674 cluster_by: None,
1675 lateral: false,
1676 modifiers_inside: false,
1677 trailing_comments: vec![],
1678 inferred_type: None,
1679 })),
1680 not: false,
1681 })),
1682 }));
1683
1684 right_select.where_clause = Some(Where {
1686 this: match right_select.where_clause {
1687 Some(w) => Expression::And(Box::new(BinaryOp {
1688 left: w.this,
1689 right: not_exists,
1690 left_comments: vec![],
1691 operator_comments: vec![],
1692 trailing_comments: vec![],
1693 inferred_type: None,
1694 })),
1695 None => not_exists,
1696 },
1697 });
1698 }
1699 }
1700
1701 right_select.with = None;
1703
1704 let order_by = select.order_by.take();
1706
1707 let union = crate::expressions::Union {
1709 left: Expression::Select(select),
1710 right: Expression::Select(right_select),
1711 all: true, distinct: false,
1713 with: None,
1714 order_by,
1715 limit: None,
1716 offset: None,
1717 distribute_by: None,
1718 sort_by: None,
1719 cluster_by: None,
1720 by_name: false,
1721 side: None,
1722 kind: None,
1723 corresponding: false,
1724 strict: false,
1725 on_columns: Vec::new(),
1726 };
1727
1728 return Ok(Expression::Union(Box::new(union)));
1729 }
1730
1731 Ok(Expression::Select(select))
1732 }
1733 other => Ok(other),
1734 }
1735}
1736
1737pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
1750 match expr {
1751 Expression::Select(mut select) => {
1752 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
1754 let mut has_recursive = false;
1755
1756 collect_nested_ctes(
1757 &Expression::Select(select.clone()),
1758 &mut collected_ctes,
1759 &mut has_recursive,
1760 true,
1761 );
1762
1763 let mut cte_body_collected: Vec<(String, Vec<crate::expressions::Cte>)> = Vec::new();
1766 if let Some(ref with) = select.with {
1767 for cte in &with.ctes {
1768 let mut body_ctes: Vec<crate::expressions::Cte> = Vec::new();
1769 collect_ctes_from_cte_body(&cte.this, &mut body_ctes, &mut has_recursive);
1770 if !body_ctes.is_empty() {
1771 cte_body_collected.push((cte.alias.name.clone(), body_ctes));
1772 }
1773 }
1774 }
1775
1776 let has_subquery_ctes = !collected_ctes.is_empty();
1777 let has_body_ctes = !cte_body_collected.is_empty();
1778
1779 if has_subquery_ctes || has_body_ctes {
1780 strip_nested_with_clauses(&mut select, true);
1782
1783 if has_body_ctes {
1785 if let Some(ref mut with) = select.with {
1786 for cte in with.ctes.iter_mut() {
1787 strip_with_from_cte_body(&mut cte.this);
1788 }
1789 }
1790 }
1791
1792 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
1793 ctes: Vec::new(),
1794 recursive: false,
1795 leading_comments: vec![],
1796 search: None,
1797 });
1798
1799 if has_recursive {
1800 top_with.recursive = true;
1801 }
1802
1803 if has_body_ctes {
1805 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
1806 for mut cte in top_with.ctes.drain(..) {
1807 if let Some(pos) = cte_body_collected
1809 .iter()
1810 .position(|(name, _)| *name == cte.alias.name)
1811 {
1812 let (_, mut nested) = cte_body_collected.remove(pos);
1813 for nested_cte in nested.iter_mut() {
1815 strip_with_from_cte_body(&mut nested_cte.this);
1816 }
1817 new_ctes.extend(nested);
1818 }
1819 strip_with_from_cte_body(&mut cte.this);
1821 new_ctes.push(cte);
1822 }
1823 top_with.ctes = new_ctes;
1824 }
1825
1826 top_with.ctes.extend(collected_ctes);
1828 }
1829
1830 Ok(Expression::Select(select))
1831 }
1832 other => Ok(other),
1833 }
1834}
1835
1836fn collect_ctes_from_cte_body(
1838 expr: &Expression,
1839 collected: &mut Vec<crate::expressions::Cte>,
1840 has_recursive: &mut bool,
1841) {
1842 if let Expression::Select(select) = expr {
1843 if let Some(ref with) = select.with {
1844 if with.recursive {
1845 *has_recursive = true;
1846 }
1847 for cte in &with.ctes {
1848 collect_ctes_from_cte_body(&cte.this, collected, has_recursive);
1850 collected.push(cte.clone());
1852 }
1853 }
1854 }
1855}
1856
1857fn strip_with_from_cte_body(expr: &mut Expression) {
1859 if let Expression::Select(ref mut select) = expr {
1860 select.with = None;
1861 }
1862}
1863
1864fn strip_nested_with_clauses(select: &mut Select, _is_top_level: bool) {
1866 if let Some(ref mut from) = select.from {
1868 for expr in from.expressions.iter_mut() {
1869 strip_with_from_expr(expr);
1870 }
1871 }
1872 for join in select.joins.iter_mut() {
1874 strip_with_from_expr(&mut join.this);
1875 }
1876 for expr in select.expressions.iter_mut() {
1878 strip_with_from_expr(expr);
1879 }
1880 if let Some(ref mut w) = select.where_clause {
1882 strip_with_from_expr(&mut w.this);
1883 }
1884}
1885
1886fn strip_with_from_expr(expr: &mut Expression) {
1887 match expr {
1888 Expression::Subquery(ref mut subquery) => {
1889 strip_with_from_inner_query(&mut subquery.this);
1890 }
1891 Expression::Alias(ref mut alias) => {
1892 strip_with_from_expr(&mut alias.this);
1893 }
1894 Expression::Select(ref mut select) => {
1895 select.with = None;
1897 strip_nested_with_clauses(select, false);
1899 }
1900 _ => {}
1901 }
1902}
1903
1904fn strip_with_from_inner_query(expr: &mut Expression) {
1905 if let Expression::Select(ref mut select) = expr {
1906 select.with = None;
1907 strip_nested_with_clauses(select, false);
1908 }
1909}
1910
1911fn collect_nested_ctes(
1913 expr: &Expression,
1914 collected: &mut Vec<crate::expressions::Cte>,
1915 has_recursive: &mut bool,
1916 is_top_level: bool,
1917) {
1918 match expr {
1919 Expression::Select(select) => {
1920 if !is_top_level {
1922 if let Some(ref with) = select.with {
1923 if with.recursive {
1924 *has_recursive = true;
1925 }
1926 collected.extend(with.ctes.clone());
1927 }
1928 }
1929
1930 if let Some(ref from) = select.from {
1932 for expr in &from.expressions {
1933 collect_nested_ctes(expr, collected, has_recursive, false);
1934 }
1935 }
1936
1937 for join in &select.joins {
1939 collect_nested_ctes(&join.this, collected, has_recursive, false);
1940 }
1941
1942 for sel_expr in &select.expressions {
1944 collect_nested_ctes(sel_expr, collected, has_recursive, false);
1945 }
1946
1947 if let Some(ref where_clause) = select.where_clause {
1949 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
1950 }
1951 }
1952 Expression::Subquery(subquery) => {
1953 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
1955 }
1956 Expression::Alias(alias) => {
1957 collect_nested_ctes(&alias.this, collected, has_recursive, false);
1958 }
1959 _ => {}
1961 }
1962}
1963
1964pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
1980 match expr {
1981 Expression::Select(mut select) => {
1982 if let Some(named_windows) = select.windows.take() {
1983 let window_map: std::collections::HashMap<String, &Over> = named_windows
1985 .iter()
1986 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
1987 .collect();
1988
1989 select.expressions = select
1991 .expressions
1992 .into_iter()
1993 .map(|e| inline_window_refs(e, &window_map))
1994 .collect();
1995 }
1996 Ok(Expression::Select(select))
1997 }
1998 other => Ok(other),
1999 }
2000}
2001
2002fn inline_window_refs(
2004 expr: Expression,
2005 window_map: &std::collections::HashMap<String, &Over>,
2006) -> Expression {
2007 match expr {
2008 Expression::WindowFunction(mut wf) => {
2009 if let Some(ref name) = wf.over.window_name {
2011 let key = name.name.to_lowercase();
2012 if let Some(named_spec) = window_map.get(&key) {
2013 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
2015 wf.over.partition_by = named_spec.partition_by.clone();
2016 }
2017 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
2018 wf.over.order_by = named_spec.order_by.clone();
2019 }
2020 if wf.over.frame.is_none() && named_spec.frame.is_some() {
2021 wf.over.frame = named_spec.frame.clone();
2022 }
2023 wf.over.window_name = None;
2025 }
2026 }
2027 Expression::WindowFunction(wf)
2028 }
2029 Expression::Alias(mut alias) => {
2030 alias.this = inline_window_refs(alias.this, window_map);
2032 Expression::Alias(alias)
2033 }
2034 other => other,
2037 }
2038}
2039
2040pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
2054 match expr {
2055 Expression::Select(mut select) => {
2056 let has_join_marks = select
2058 .where_clause
2059 .as_ref()
2060 .map_or(false, |w| contains_join_mark(&w.this));
2061
2062 if !has_join_marks {
2063 return Ok(Expression::Select(select));
2064 }
2065
2066 let from_tables: Vec<String> = select
2068 .from
2069 .as_ref()
2070 .map(|f| {
2071 f.expressions
2072 .iter()
2073 .filter_map(|e| get_table_name(e))
2074 .collect()
2075 })
2076 .unwrap_or_default();
2077
2078 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
2080 std::collections::HashMap::new();
2081 let mut remaining_conditions: Vec<Expression> = Vec::new();
2082
2083 if let Some(ref where_clause) = select.where_clause {
2084 extract_join_mark_conditions(
2085 &where_clause.this,
2086 &mut join_conditions,
2087 &mut remaining_conditions,
2088 );
2089 }
2090
2091 let mut new_joins = select.joins.clone();
2093 for (table_name, conditions) in join_conditions {
2094 let table_in_from = from_tables.contains(&table_name);
2096
2097 if table_in_from && !conditions.is_empty() {
2098 let combined_condition = conditions.into_iter().reduce(|a, b| {
2100 Expression::And(Box::new(BinaryOp {
2101 left: a,
2102 right: b,
2103 left_comments: vec![],
2104 operator_comments: vec![],
2105 trailing_comments: vec![],
2106 inferred_type: None,
2107 }))
2108 });
2109
2110 if let Some(ref mut from) = select.from {
2112 if let Some(pos) = from
2113 .expressions
2114 .iter()
2115 .position(|e| get_table_name(e).map_or(false, |n| n == table_name))
2116 {
2117 if from.expressions.len() > 1 {
2118 let join_table = from.expressions.remove(pos);
2119 new_joins.push(crate::expressions::Join {
2120 this: join_table,
2121 kind: JoinKind::Left,
2122 on: combined_condition,
2123 using: vec![],
2124 use_inner_keyword: false,
2125 use_outer_keyword: true,
2126 deferred_condition: false,
2127 join_hint: None,
2128 match_condition: None,
2129 pivots: Vec::new(),
2130 comments: Vec::new(),
2131 nesting_group: 0,
2132 directed: false,
2133 });
2134 }
2135 }
2136 }
2137 }
2138 }
2139
2140 select.joins = new_joins;
2141
2142 if remaining_conditions.is_empty() {
2144 select.where_clause = None;
2145 } else {
2146 let combined = remaining_conditions.into_iter().reduce(|a, b| {
2147 Expression::And(Box::new(BinaryOp {
2148 left: a,
2149 right: b,
2150 left_comments: vec![],
2151 operator_comments: vec![],
2152 trailing_comments: vec![],
2153 inferred_type: None,
2154 }))
2155 });
2156 select.where_clause = combined.map(|c| Where { this: c });
2157 }
2158
2159 clear_join_marks(&mut Expression::Select(select.clone()));
2161
2162 Ok(Expression::Select(select))
2163 }
2164 other => Ok(other),
2165 }
2166}
2167
2168fn contains_join_mark(expr: &Expression) -> bool {
2170 match expr {
2171 Expression::Column(col) => col.join_mark,
2172 Expression::And(op) | Expression::Or(op) => {
2173 contains_join_mark(&op.left) || contains_join_mark(&op.right)
2174 }
2175 Expression::Eq(op)
2176 | Expression::Neq(op)
2177 | Expression::Lt(op)
2178 | Expression::Lte(op)
2179 | Expression::Gt(op)
2180 | Expression::Gte(op) => contains_join_mark(&op.left) || contains_join_mark(&op.right),
2181 Expression::Not(op) => contains_join_mark(&op.this),
2182 _ => false,
2183 }
2184}
2185
2186fn get_table_name(expr: &Expression) -> Option<String> {
2188 match expr {
2189 Expression::Table(t) => Some(t.name.name.clone()),
2190 Expression::Alias(a) => Some(a.alias.name.clone()),
2191 _ => None,
2192 }
2193}
2194
2195fn extract_join_mark_conditions(
2197 expr: &Expression,
2198 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
2199 remaining: &mut Vec<Expression>,
2200) {
2201 match expr {
2202 Expression::And(op) => {
2203 extract_join_mark_conditions(&op.left, join_conditions, remaining);
2204 extract_join_mark_conditions(&op.right, join_conditions, remaining);
2205 }
2206 _ => {
2207 if let Some(table) = get_join_mark_table(expr) {
2208 join_conditions
2209 .entry(table)
2210 .or_insert_with(Vec::new)
2211 .push(expr.clone());
2212 } else {
2213 remaining.push(expr.clone());
2214 }
2215 }
2216 }
2217}
2218
2219fn get_join_mark_table(expr: &Expression) -> Option<String> {
2221 match expr {
2222 Expression::Eq(op)
2223 | Expression::Neq(op)
2224 | Expression::Lt(op)
2225 | Expression::Lte(op)
2226 | Expression::Gt(op)
2227 | Expression::Gte(op) => {
2228 if let Expression::Column(col) = &op.left {
2230 if col.join_mark {
2231 return col.table.as_ref().map(|t| t.name.clone());
2232 }
2233 }
2234 if let Expression::Column(col) = &op.right {
2235 if col.join_mark {
2236 return col.table.as_ref().map(|t| t.name.clone());
2237 }
2238 }
2239 None
2240 }
2241 _ => None,
2242 }
2243}
2244
2245fn clear_join_marks(expr: &mut Expression) {
2247 match expr {
2248 Expression::Column(col) => col.join_mark = false,
2249 Expression::Select(select) => {
2250 if let Some(ref mut w) = select.where_clause {
2251 clear_join_marks(&mut w.this);
2252 }
2253 for sel_expr in &mut select.expressions {
2254 clear_join_marks(sel_expr);
2255 }
2256 }
2257 Expression::And(op) | Expression::Or(op) => {
2258 clear_join_marks(&mut op.left);
2259 clear_join_marks(&mut op.right);
2260 }
2261 Expression::Eq(op)
2262 | Expression::Neq(op)
2263 | Expression::Lt(op)
2264 | Expression::Lte(op)
2265 | Expression::Gt(op)
2266 | Expression::Gte(op) => {
2267 clear_join_marks(&mut op.left);
2268 clear_join_marks(&mut op.right);
2269 }
2270 _ => {}
2271 }
2272}
2273
2274pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
2281 match expr {
2282 Expression::Select(mut select) => {
2283 if let Some(ref mut with) = select.with {
2284 if with.recursive {
2285 let mut counter = 0;
2286 for cte in &mut with.ctes {
2287 if cte.columns.is_empty() {
2288 if let Expression::Select(ref cte_select) = cte.this {
2290 let names: Vec<Identifier> = cte_select
2291 .expressions
2292 .iter()
2293 .map(|e| match e {
2294 Expression::Alias(a) => a.alias.clone(),
2295 Expression::Column(c) => c.name.clone(),
2296 _ => {
2297 counter += 1;
2298 Identifier::new(format!("_c_{}", counter))
2299 }
2300 })
2301 .collect();
2302 cte.columns = names;
2303 }
2304 }
2305 }
2306 }
2307 }
2308 Ok(Expression::Select(select))
2309 }
2310 other => Ok(other),
2311 }
2312}
2313
2314pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
2321 match expr {
2322 Expression::Cast(mut cast) => {
2323 if let Expression::Literal(ref lit) = cast.this {
2324 if let Literal::String(ref s) = lit.as_ref() {
2325 if s.to_lowercase() == "epoch" {
2326 if is_temporal_type(&cast.to) {
2327 cast.this = Expression::Literal(Box::new(Literal::String(
2328 "1970-01-01 00:00:00".to_string(),
2329 )));
2330 }
2331 }
2332 }
2333 }
2334 Ok(Expression::Cast(cast))
2335 }
2336 Expression::TryCast(mut try_cast) => {
2337 if let Expression::Literal(ref lit) = try_cast.this {
2338 if let Literal::String(ref s) = lit.as_ref() {
2339 if s.to_lowercase() == "epoch" {
2340 if is_temporal_type(&try_cast.to) {
2341 try_cast.this = Expression::Literal(Box::new(Literal::String(
2342 "1970-01-01 00:00:00".to_string(),
2343 )));
2344 }
2345 }
2346 }
2347 }
2348 Ok(Expression::TryCast(try_cast))
2349 }
2350 other => Ok(other),
2351 }
2352}
2353
2354fn is_temporal_type(dt: &DataType) -> bool {
2356 matches!(
2357 dt,
2358 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
2359 )
2360}
2361
2362pub fn ensure_bools(expr: Expression) -> Result<Expression> {
2387 let expr = ensure_bools_in_value_context(expr);
2388
2389 Ok(match expr {
2390 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => ensure_bool_condition(expr),
2392 other => other,
2393 })
2394}
2395
2396fn ensure_bools_in_value_context(expr: Expression) -> Expression {
2400 match expr {
2401 Expression::Case(mut case) => {
2402 case.whens = case
2403 .whens
2404 .into_iter()
2405 .map(|(condition, result)| {
2406 let new_condition =
2407 ensure_bool_condition(ensure_bools_in_value_context(condition));
2408 let new_result = ensure_bools_in_value_context(result);
2409 (new_condition, new_result)
2410 })
2411 .collect();
2412 if let Some(else_expr) = case.else_ {
2413 case.else_ = Some(ensure_bools_in_value_context(else_expr));
2414 }
2415 Expression::Case(Box::new(*case))
2416 }
2417 Expression::Select(select) => Expression::Select(Box::new(ensure_bools_in_select(*select))),
2418 Expression::Subquery(mut subquery) => {
2419 subquery.this = ensure_bools_in_value_context(subquery.this);
2420 Expression::Subquery(subquery)
2421 }
2422 Expression::JoinedTable(mut joined_table) => {
2423 joined_table.left = ensure_bools_in_value_context(joined_table.left);
2424 joined_table.joins = joined_table
2425 .joins
2426 .into_iter()
2427 .map(ensure_bools_in_join)
2428 .collect();
2429 joined_table.lateral_views = joined_table
2430 .lateral_views
2431 .into_iter()
2432 .map(|mut lateral_view| {
2433 lateral_view.this = ensure_bools_in_value_context(lateral_view.this);
2434 lateral_view
2435 })
2436 .collect();
2437 Expression::JoinedTable(joined_table)
2438 }
2439 Expression::Union(mut union) => {
2440 let left = std::mem::replace(&mut union.left, Expression::null());
2441 let right = std::mem::replace(&mut union.right, Expression::null());
2442 union.left = ensure_bools_in_value_context(left);
2443 union.right = ensure_bools_in_value_context(right);
2444 if let Some(with) = union.with.take() {
2445 union.with = Some(ensure_bools_in_with(with));
2446 }
2447 Expression::Union(union)
2448 }
2449 Expression::Intersect(mut intersect) => {
2450 let left = std::mem::replace(&mut intersect.left, Expression::null());
2451 let right = std::mem::replace(&mut intersect.right, Expression::null());
2452 intersect.left = ensure_bools_in_value_context(left);
2453 intersect.right = ensure_bools_in_value_context(right);
2454 if let Some(with) = intersect.with.take() {
2455 intersect.with = Some(ensure_bools_in_with(with));
2456 }
2457 Expression::Intersect(intersect)
2458 }
2459 Expression::Except(mut except) => {
2460 let left = std::mem::replace(&mut except.left, Expression::null());
2461 let right = std::mem::replace(&mut except.right, Expression::null());
2462 except.left = ensure_bools_in_value_context(left);
2463 except.right = ensure_bools_in_value_context(right);
2464 if let Some(with) = except.with.take() {
2465 except.with = Some(ensure_bools_in_with(with));
2466 }
2467 Expression::Except(except)
2468 }
2469 Expression::Alias(mut alias) => {
2470 alias.this = ensure_bools_in_value_context(alias.this);
2471 Expression::Alias(alias)
2472 }
2473 Expression::Paren(mut paren) => {
2474 paren.this = ensure_bools_in_value_context(paren.this);
2475 Expression::Paren(paren)
2476 }
2477 other => other,
2478 }
2479}
2480
2481fn ensure_bools_in_select(mut select: Select) -> Select {
2482 select.expressions = select
2483 .expressions
2484 .into_iter()
2485 .map(ensure_bools_in_value_context)
2486 .collect();
2487
2488 if let Some(from) = select.from.take() {
2489 select.from = Some(crate::expressions::From {
2490 expressions: from
2491 .expressions
2492 .into_iter()
2493 .map(ensure_bools_in_value_context)
2494 .collect(),
2495 });
2496 }
2497
2498 select.joins = select.joins.into_iter().map(ensure_bools_in_join).collect();
2499
2500 if let Some(mut where_clause) = select.where_clause.take() {
2501 where_clause.this = ensure_bool_condition(ensure_bools_in_value_context(where_clause.this));
2502 select.where_clause = Some(where_clause);
2503 }
2504
2505 if let Some(mut having) = select.having.take() {
2506 having.this = ensure_bool_condition(ensure_bools_in_value_context(having.this));
2507 select.having = Some(having);
2508 }
2509
2510 if let Some(with) = select.with.take() {
2511 select.with = Some(ensure_bools_in_with(with));
2512 }
2513
2514 select
2515}
2516
2517fn ensure_bools_in_join(mut join: Join) -> Join {
2518 join.this = ensure_bools_in_value_context(join.this);
2519
2520 if let Some(on) = join.on.take() {
2521 join.on = Some(ensure_bool_condition(ensure_bools_in_value_context(on)));
2522 }
2523
2524 if let Some(match_condition) = join.match_condition.take() {
2525 join.match_condition = Some(ensure_bool_condition(ensure_bools_in_value_context(
2526 match_condition,
2527 )));
2528 }
2529
2530 join.pivots = join
2531 .pivots
2532 .into_iter()
2533 .map(ensure_bools_in_value_context)
2534 .collect();
2535
2536 join
2537}
2538
2539fn ensure_bools_in_with(mut with: With) -> With {
2540 with.ctes = with
2541 .ctes
2542 .into_iter()
2543 .map(|mut cte| {
2544 cte.this = ensure_bools_in_value_context(cte.this);
2545 cte
2546 })
2547 .collect();
2548 with
2549}
2550
2551fn is_boolean_expression(expr: &Expression) -> bool {
2554 matches!(
2555 expr,
2556 Expression::Eq(_)
2557 | Expression::Neq(_)
2558 | Expression::Lt(_)
2559 | Expression::Lte(_)
2560 | Expression::Gt(_)
2561 | Expression::Gte(_)
2562 | Expression::Is(_)
2563 | Expression::IsNull(_)
2564 | Expression::IsTrue(_)
2565 | Expression::IsFalse(_)
2566 | Expression::Like(_)
2567 | Expression::ILike(_)
2568 | Expression::StartsWith(_)
2569 | Expression::SimilarTo(_)
2570 | Expression::Glob(_)
2571 | Expression::RegexpLike(_)
2572 | Expression::In(_)
2573 | Expression::Between(_)
2574 | Expression::Exists(_)
2575 | Expression::And(_)
2576 | Expression::Or(_)
2577 | Expression::Not(_)
2578 | Expression::Any(_)
2579 | Expression::All(_)
2580 | Expression::NullSafeEq(_)
2581 | Expression::NullSafeNeq(_)
2582 | Expression::EqualNull(_)
2583 )
2584}
2585
2586fn wrap_neq_zero(expr: Expression) -> Expression {
2588 Expression::Neq(Box::new(BinaryOp {
2589 left: expr,
2590 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2591 left_comments: vec![],
2592 operator_comments: vec![],
2593 trailing_comments: vec![],
2594 inferred_type: None,
2595 }))
2596}
2597
2598pub(crate) fn ensure_bool_condition(expr: Expression) -> Expression {
2604 match expr {
2605 Expression::And(op) => {
2607 let new_op = BinaryOp {
2608 left: ensure_bool_condition(op.left.clone()),
2609 right: ensure_bool_condition(op.right.clone()),
2610 left_comments: op.left_comments.clone(),
2611 operator_comments: op.operator_comments.clone(),
2612 trailing_comments: op.trailing_comments.clone(),
2613 inferred_type: None,
2614 };
2615 Expression::And(Box::new(new_op))
2616 }
2617 Expression::Or(op) => {
2618 let new_op = BinaryOp {
2619 left: ensure_bool_condition(op.left.clone()),
2620 right: ensure_bool_condition(op.right.clone()),
2621 left_comments: op.left_comments.clone(),
2622 operator_comments: op.operator_comments.clone(),
2623 trailing_comments: op.trailing_comments.clone(),
2624 inferred_type: None,
2625 };
2626 Expression::Or(Box::new(new_op))
2627 }
2628 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
2630 this: ensure_bool_condition(op.this.clone()),
2631 inferred_type: None,
2632 })),
2633 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
2635 this: ensure_bool_condition(paren.this.clone()),
2636 trailing_comments: paren.trailing_comments.clone(),
2637 })),
2638 Expression::Boolean(BooleanLiteral { value: true }) => {
2640 Expression::Paren(Box::new(crate::expressions::Paren {
2641 this: Expression::Eq(Box::new(BinaryOp {
2642 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2643 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2644 left_comments: vec![],
2645 operator_comments: vec![],
2646 trailing_comments: vec![],
2647 inferred_type: None,
2648 })),
2649 trailing_comments: vec![],
2650 }))
2651 }
2652 Expression::Boolean(BooleanLiteral { value: false }) => {
2653 Expression::Paren(Box::new(crate::expressions::Paren {
2654 this: Expression::Eq(Box::new(BinaryOp {
2655 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2656 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2657 left_comments: vec![],
2658 operator_comments: vec![],
2659 trailing_comments: vec![],
2660 inferred_type: None,
2661 })),
2662 trailing_comments: vec![],
2663 }))
2664 }
2665 ref e if is_boolean_expression(e) => expr,
2667 _ => wrap_neq_zero(expr),
2670 }
2671}
2672
2673pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
2679 Ok(unqualify_columns_recursive(expr))
2680}
2681
2682fn unqualify_columns_recursive(expr: Expression) -> Expression {
2684 match expr {
2685 Expression::Column(mut col) => {
2686 col.table = None;
2687 Expression::Column(col)
2688 }
2689 Expression::Select(mut select) => {
2690 select.expressions = select
2691 .expressions
2692 .into_iter()
2693 .map(unqualify_columns_recursive)
2694 .collect();
2695 if let Some(ref mut where_clause) = select.where_clause {
2696 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
2697 }
2698 if let Some(ref mut having) = select.having {
2699 having.this = unqualify_columns_recursive(having.this.clone());
2700 }
2701 if let Some(ref mut group_by) = select.group_by {
2702 group_by.expressions = group_by
2703 .expressions
2704 .iter()
2705 .cloned()
2706 .map(unqualify_columns_recursive)
2707 .collect();
2708 }
2709 if let Some(ref mut order_by) = select.order_by {
2710 order_by.expressions = order_by
2711 .expressions
2712 .iter()
2713 .map(|o| crate::expressions::Ordered {
2714 this: unqualify_columns_recursive(o.this.clone()),
2715 desc: o.desc,
2716 nulls_first: o.nulls_first,
2717 explicit_asc: o.explicit_asc,
2718 with_fill: o.with_fill.clone(),
2719 })
2720 .collect();
2721 }
2722 for join in &mut select.joins {
2723 if let Some(ref mut on) = join.on {
2724 *on = unqualify_columns_recursive(on.clone());
2725 }
2726 }
2727 Expression::Select(select)
2728 }
2729 Expression::Alias(mut alias) => {
2730 alias.this = unqualify_columns_recursive(alias.this);
2731 Expression::Alias(alias)
2732 }
2733 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
2735 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
2736 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
2737 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
2738 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
2739 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
2740 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
2741 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
2742 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
2743 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
2744 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
2745 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
2746 Expression::Function(mut func) => {
2748 func.args = func
2749 .args
2750 .into_iter()
2751 .map(unqualify_columns_recursive)
2752 .collect();
2753 Expression::Function(func)
2754 }
2755 Expression::AggregateFunction(mut func) => {
2756 func.args = func
2757 .args
2758 .into_iter()
2759 .map(unqualify_columns_recursive)
2760 .collect();
2761 Expression::AggregateFunction(func)
2762 }
2763 Expression::Case(mut case) => {
2764 case.whens = case
2765 .whens
2766 .into_iter()
2767 .map(|(cond, result)| {
2768 (
2769 unqualify_columns_recursive(cond),
2770 unqualify_columns_recursive(result),
2771 )
2772 })
2773 .collect();
2774 if let Some(else_expr) = case.else_ {
2775 case.else_ = Some(unqualify_columns_recursive(else_expr));
2776 }
2777 Expression::Case(case)
2778 }
2779 other => other,
2781 }
2782}
2783
2784fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
2786 op.left = unqualify_columns_recursive(op.left);
2787 op.right = unqualify_columns_recursive(op.right);
2788 op
2789}
2790
2791pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
2811 match expr {
2812 Expression::Select(mut select) => {
2813 let mut cte_count = 0;
2814 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2815
2816 if let Some(ref mut with) = select.with {
2818 for cte in &mut with.ctes {
2819 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
2820 }
2821 }
2822
2823 if let Some(ref mut from) = select.from {
2825 for table_expr in &mut from.expressions {
2826 if let Some((cte, replacement)) =
2827 try_convert_generate_date_array(table_expr, &mut cte_count)
2828 {
2829 new_ctes.push(cte);
2830 *table_expr = replacement;
2831 }
2832 }
2833 }
2834
2835 for join in &mut select.joins {
2837 if let Some((cte, replacement)) =
2838 try_convert_generate_date_array(&join.this, &mut cte_count)
2839 {
2840 new_ctes.push(cte);
2841 join.this = replacement;
2842 }
2843 }
2844
2845 if !new_ctes.is_empty() {
2847 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
2848 ctes: Vec::new(),
2849 recursive: true, leading_comments: vec![],
2851 search: None,
2852 });
2853 with_clause.recursive = true;
2854
2855 let mut all_ctes = new_ctes;
2857 all_ctes.append(&mut with_clause.ctes);
2858 with_clause.ctes = all_ctes;
2859 }
2860
2861 Ok(Expression::Select(select))
2862 }
2863 other => Ok(other),
2864 }
2865}
2866
2867fn process_expression_for_gda(
2870 expr: &mut Expression,
2871 cte_count: &mut usize,
2872 new_ctes: &mut Vec<crate::expressions::Cte>,
2873) {
2874 match expr {
2875 Expression::Select(ref mut select) => {
2876 if let Some(ref mut from) = select.from {
2878 for table_expr in &mut from.expressions {
2879 if let Some((cte, replacement)) =
2880 try_convert_generate_date_array(table_expr, cte_count)
2881 {
2882 new_ctes.push(cte);
2883 *table_expr = replacement;
2884 }
2885 }
2886 }
2887 for join in &mut select.joins {
2889 if let Some((cte, replacement)) =
2890 try_convert_generate_date_array(&join.this, cte_count)
2891 {
2892 new_ctes.push(cte);
2893 join.this = replacement;
2894 }
2895 }
2896 }
2897 Expression::Union(ref mut u) => {
2898 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
2899 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
2900 }
2901 Expression::Subquery(ref mut sq) => {
2902 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
2903 }
2904 _ => {}
2905 }
2906}
2907
2908fn try_convert_generate_date_array(
2911 expr: &Expression,
2912 cte_count: &mut usize,
2913) -> Option<(crate::expressions::Cte, Expression)> {
2914 try_convert_generate_date_array_with_name(expr, cte_count, None)
2915}
2916
2917fn try_convert_generate_date_array_with_name(
2918 expr: &Expression,
2919 cte_count: &mut usize,
2920 column_name_override: Option<&str>,
2921) -> Option<(crate::expressions::Cte, Expression)> {
2922 fn extract_gda_args(
2924 inner: &Expression,
2925 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
2926 match inner {
2927 Expression::GenerateDateArray(gda) => {
2928 let start = gda.start.as_ref()?;
2929 let end = gda.end.as_ref()?;
2930 let step = gda.step.as_deref();
2931 Some((start, end, step))
2932 }
2933 Expression::GenerateSeries(gs) => {
2934 let start = gs.start.as_deref()?;
2935 let end = gs.end.as_deref()?;
2936 let step = gs.step.as_deref();
2937 Some((start, end, step))
2938 }
2939 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
2940 if f.args.len() >= 2 {
2941 let start = &f.args[0];
2942 let end = &f.args[1];
2943 let step = f.args.get(2);
2944 Some((start, end, step))
2945 } else {
2946 None
2947 }
2948 }
2949 _ => None,
2950 }
2951 }
2952
2953 if let Expression::Unnest(unnest) = expr {
2955 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
2956 let start = start;
2957 let end = end;
2958 let step: Option<&Expression> = step_opt;
2959
2960 let cte_name = if *cte_count == 0 {
2962 "_generated_dates".to_string()
2963 } else {
2964 format!("_generated_dates_{}", cte_count)
2965 };
2966 *cte_count += 1;
2967
2968 let column_name =
2969 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
2970
2971 let cast_to_date = |expr: &Expression| -> Expression {
2973 match expr {
2974 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
2975 if let Expression::Literal(lit) = expr {
2977 if let Literal::Date(d) = lit.as_ref() {
2978 Expression::Cast(Box::new(Cast {
2979 this: Expression::Literal(Box::new(Literal::String(d.clone()))),
2980 to: DataType::Date,
2981 trailing_comments: vec![],
2982 double_colon_syntax: false,
2983 format: None,
2984 default: None,
2985 inferred_type: None,
2986 }))
2987 } else {
2988 expr.clone()
2989 }
2990 } else {
2991 unreachable!()
2992 }
2993 }
2994 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
2995 _ => Expression::Cast(Box::new(Cast {
2996 this: expr.clone(),
2997 to: DataType::Date,
2998 trailing_comments: vec![],
2999 double_colon_syntax: false,
3000 format: None,
3001 default: None,
3002 inferred_type: None,
3003 })),
3004 }
3005 };
3006
3007 let base_select = Select {
3009 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
3010 this: cast_to_date(start),
3011 alias: column_name.clone(),
3012 column_aliases: vec![],
3013 alias_explicit_as: false,
3014 alias_keyword: None,
3015 pre_alias_comments: vec![],
3016 trailing_comments: vec![],
3017 inferred_type: None,
3018 }))],
3019 ..Select::new()
3020 };
3021
3022 let normalize_interval = |expr: &Expression| -> Expression {
3024 if let Expression::Interval(ref iv) = expr {
3025 let mut iv_clone = iv.as_ref().clone();
3026 if let Some(Expression::Literal(ref lit)) = iv_clone.this {
3027 if let Literal::String(ref s) = lit.as_ref() {
3028 if s.parse::<f64>().is_ok() {
3030 iv_clone.this =
3031 Some(Expression::Literal(Box::new(Literal::Number(s.clone()))));
3032 }
3033 }
3034 }
3035 Expression::Interval(Box::new(iv_clone))
3036 } else {
3037 expr.clone()
3038 }
3039 };
3040
3041 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
3044 Expression::Interval(Box::new(crate::expressions::Interval {
3045 this: Some(Expression::Literal(Box::new(Literal::Number(
3046 "1".to_string(),
3047 )))),
3048 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
3049 unit: crate::expressions::IntervalUnit::Day,
3050 use_plural: false,
3051 }),
3052 }))
3053 });
3054
3055 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
3057
3058 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
3059 this: Expression::Column(Box::new(crate::expressions::Column {
3060 name: column_name.clone(),
3061 table: None,
3062 join_mark: false,
3063 trailing_comments: vec![],
3064 span: None,
3065 inferred_type: None,
3066 })),
3067 interval: add_count,
3068 unit: add_unit,
3069 }));
3070
3071 let cast_date_add = Expression::Cast(Box::new(Cast {
3072 this: date_add_expr.clone(),
3073 to: DataType::Date,
3074 trailing_comments: vec![],
3075 double_colon_syntax: false,
3076 format: None,
3077 default: None,
3078 inferred_type: None,
3079 }));
3080
3081 let recursive_select = Select {
3082 expressions: vec![cast_date_add.clone()],
3083 from: Some(From {
3084 expressions: vec![Expression::Table(Box::new(
3085 crate::expressions::TableRef::new(&cte_name),
3086 ))],
3087 }),
3088 where_clause: Some(Where {
3089 this: Expression::Lte(Box::new(BinaryOp {
3090 left: cast_date_add,
3091 right: cast_to_date(end),
3092 left_comments: vec![],
3093 operator_comments: vec![],
3094 trailing_comments: vec![],
3095 inferred_type: None,
3096 })),
3097 }),
3098 ..Select::new()
3099 };
3100
3101 let union = crate::expressions::Union {
3103 left: Expression::Select(Box::new(base_select)),
3104 right: Expression::Select(Box::new(recursive_select)),
3105 all: true, distinct: false,
3107 with: None,
3108 order_by: None,
3109 limit: None,
3110 offset: None,
3111 distribute_by: None,
3112 sort_by: None,
3113 cluster_by: None,
3114 by_name: false,
3115 side: None,
3116 kind: None,
3117 corresponding: false,
3118 strict: false,
3119 on_columns: Vec::new(),
3120 };
3121
3122 let cte = crate::expressions::Cte {
3124 this: Expression::Union(Box::new(union)),
3125 alias: Identifier::new(cte_name.clone()),
3126 columns: vec![column_name.clone()],
3127 materialized: None,
3128 key_expressions: Vec::new(),
3129 alias_first: true,
3130 comments: Vec::new(),
3131 };
3132
3133 let replacement_select = Select {
3135 expressions: vec![Expression::Column(Box::new(crate::expressions::Column {
3136 name: column_name,
3137 table: None,
3138 join_mark: false,
3139 trailing_comments: vec![],
3140 span: None,
3141 inferred_type: None,
3142 }))],
3143 from: Some(From {
3144 expressions: vec![Expression::Table(Box::new(
3145 crate::expressions::TableRef::new(&cte_name),
3146 ))],
3147 }),
3148 ..Select::new()
3149 };
3150
3151 let replacement = Expression::Subquery(Box::new(Subquery {
3152 this: Expression::Select(Box::new(replacement_select)),
3153 alias: Some(Identifier::new(cte_name)),
3154 column_aliases: vec![],
3155 alias_explicit_as: false,
3156 alias_keyword: None,
3157 order_by: None,
3158 limit: None,
3159 offset: None,
3160 distribute_by: None,
3161 sort_by: None,
3162 cluster_by: None,
3163 lateral: false,
3164 modifiers_inside: false,
3165 trailing_comments: vec![],
3166 inferred_type: None,
3167 }));
3168
3169 return Some((cte, replacement));
3170 }
3171 }
3172
3173 if let Expression::Alias(alias) = expr {
3175 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
3177 if let Some((cte, replacement)) =
3178 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
3179 {
3180 if col_name.is_some() {
3183 return Some((cte, replacement));
3184 }
3185 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
3186 this: replacement,
3187 alias: alias.alias.clone(),
3188 column_aliases: alias.column_aliases.clone(),
3189 alias_explicit_as: false,
3190 alias_keyword: None,
3191 pre_alias_comments: alias.pre_alias_comments.clone(),
3192 trailing_comments: alias.trailing_comments.clone(),
3193 inferred_type: None,
3194 }));
3195 return Some((cte, new_alias));
3196 }
3197 }
3198
3199 None
3200}
3201
3202fn extract_interval_unit_and_count(
3207 expr: &Expression,
3208) -> (crate::expressions::IntervalUnit, Expression) {
3209 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
3210
3211 if let Expression::Interval(ref iv) = expr {
3212 if let Some(ref unit_spec) = iv.unit {
3214 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
3215 let count = match &iv.this {
3216 Some(e) => e.clone(),
3217 None => Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3218 };
3219 return (unit.clone(), count);
3220 }
3221 }
3222
3223 if let Some(ref val_expr) = iv.this {
3225 match val_expr {
3226 Expression::Literal(lit)
3227 if matches!(lit.as_ref(), Literal::String(_) | Literal::Number(_)) =>
3228 {
3229 let s = match lit.as_ref() {
3230 Literal::String(s) | Literal::Number(s) => s,
3231 _ => unreachable!(),
3232 };
3233 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
3235 if parts.len() == 2 {
3236 let count_str = parts[0].trim();
3237 let unit_str = parts[1].trim().to_uppercase();
3238 let unit = match unit_str.as_str() {
3239 "YEAR" | "YEARS" => IntervalUnit::Year,
3240 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
3241 "MONTH" | "MONTHS" => IntervalUnit::Month,
3242 "WEEK" | "WEEKS" => IntervalUnit::Week,
3243 "DAY" | "DAYS" => IntervalUnit::Day,
3244 "HOUR" | "HOURS" => IntervalUnit::Hour,
3245 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
3246 "SECOND" | "SECONDS" => IntervalUnit::Second,
3247 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
3248 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
3249 _ => IntervalUnit::Day,
3250 };
3251 return (
3252 unit,
3253 Expression::Literal(Box::new(Literal::Number(count_str.to_string()))),
3254 );
3255 }
3256 if s.parse::<f64>().is_ok() {
3258 return (
3259 IntervalUnit::Day,
3260 Expression::Literal(Box::new(Literal::Number(s.clone()))),
3261 );
3262 }
3263 }
3264 _ => {}
3265 }
3266 }
3267
3268 (
3270 IntervalUnit::Day,
3271 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3272 )
3273 } else {
3274 (
3275 IntervalUnit::Day,
3276 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3277 )
3278 }
3279}
3280
3281pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
3294 match expr {
3295 Expression::ILike(ilike) => {
3296 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
3298 name: "LOWER".to_string(),
3299 args: vec![ilike.left],
3300 distinct: false,
3301 trailing_comments: vec![],
3302 use_bracket_syntax: false,
3303 no_parens: false,
3304 quoted: false,
3305 span: None,
3306 inferred_type: None,
3307 }));
3308
3309 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
3310 name: "LOWER".to_string(),
3311 args: vec![ilike.right],
3312 distinct: false,
3313 trailing_comments: vec![],
3314 use_bracket_syntax: false,
3315 no_parens: false,
3316 quoted: false,
3317 span: None,
3318 inferred_type: None,
3319 }));
3320
3321 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
3322 left: lower_left,
3323 right: lower_right,
3324 escape: ilike.escape,
3325 quantifier: ilike.quantifier,
3326 inferred_type: None,
3327 })))
3328 }
3329 other => Ok(other),
3330 }
3331}
3332
3333pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
3341 match expr {
3342 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
3343 other => Ok(other),
3344 }
3345}
3346
3347pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
3352 match expr {
3353 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
3354 other => Ok(other),
3355 }
3356}
3357
3358pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
3365 Ok(expr)
3367}
3368
3369pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
3383 match expr {
3386 Expression::Table(ref table) => {
3387 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
3390 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3392 this: expr.clone(),
3393 expressions: Vec::new(),
3394 with_ordinality: false,
3395 alias: None,
3396 offset_alias: None,
3397 }));
3398
3399 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
3401 this: unnest,
3402 alias: Identifier::new("_u".to_string()),
3403 column_aliases: vec![],
3404 alias_explicit_as: false,
3405 alias_keyword: None,
3406 pre_alias_comments: vec![],
3407 trailing_comments: vec![],
3408 inferred_type: None,
3409 })));
3410 }
3411 Ok(expr)
3412 }
3413 Expression::GenerateSeries(gs) => {
3414 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3416 this: Expression::GenerateSeries(gs),
3417 expressions: Vec::new(),
3418 with_ordinality: false,
3419 alias: None,
3420 offset_alias: None,
3421 }));
3422 Ok(unnest)
3423 }
3424 other => Ok(other),
3425 }
3426}
3427
3428pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
3439 use crate::dialects::transform_recursive;
3440 transform_recursive(expr, &unwrap_unnest_generate_series_single)
3441}
3442
3443fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
3444 use crate::expressions::*;
3445 match expr {
3447 Expression::Select(mut select) => {
3448 if let Some(ref mut from) = select.from {
3450 for table_expr in &mut from.expressions {
3451 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
3452 *table_expr = replacement;
3453 }
3454 }
3455 }
3456 for join in &mut select.joins {
3458 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
3459 join.this = replacement;
3460 }
3461 }
3462 Ok(Expression::Select(select))
3463 }
3464 other => Ok(other),
3465 }
3466}
3467
3468fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
3471 use crate::expressions::*;
3472
3473 let gen_series = match expr {
3475 Expression::Unnest(unnest) => {
3476 if let Expression::GenerateSeries(ref gs) = unnest.this {
3477 Some(gs.as_ref().clone())
3478 } else {
3479 None
3480 }
3481 }
3482 Expression::Alias(alias) => {
3483 if let Expression::Unnest(ref unnest) = alias.this {
3484 if let Expression::GenerateSeries(ref gs) = unnest.this {
3485 Some(gs.as_ref().clone())
3486 } else {
3487 None
3488 }
3489 } else {
3490 None
3491 }
3492 }
3493 _ => None,
3494 };
3495
3496 let gs = gen_series?;
3497
3498 let value_col = Expression::boxed_column(Column {
3500 name: Identifier::new("value".to_string()),
3501 table: None,
3502 join_mark: false,
3503 trailing_comments: vec![],
3504 span: None,
3505 inferred_type: None,
3506 });
3507
3508 let cast_value = Expression::Cast(Box::new(Cast {
3509 this: value_col,
3510 to: DataType::Date,
3511 trailing_comments: vec![],
3512 double_colon_syntax: false,
3513 format: None,
3514 default: None,
3515 inferred_type: None,
3516 }));
3517
3518 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
3519
3520 let gen_series_aliased = Expression::Alias(Box::new(Alias {
3522 this: gen_series_expr,
3523 alias: Identifier::new("_t".to_string()),
3524 column_aliases: vec![Identifier::new("value".to_string())],
3525 alias_explicit_as: false,
3526 alias_keyword: None,
3527 pre_alias_comments: vec![],
3528 trailing_comments: vec![],
3529 inferred_type: None,
3530 }));
3531
3532 let mut inner_select = Select::new();
3533 inner_select.expressions = vec![cast_value];
3534 inner_select.from = Some(From {
3535 expressions: vec![gen_series_aliased],
3536 });
3537
3538 let inner_select_expr = Expression::Select(Box::new(inner_select));
3539
3540 let subquery = Expression::Subquery(Box::new(Subquery {
3541 this: inner_select_expr,
3542 alias: None,
3543 column_aliases: vec![],
3544 alias_explicit_as: false,
3545 alias_keyword: None,
3546 order_by: None,
3547 limit: None,
3548 offset: None,
3549 distribute_by: None,
3550 sort_by: None,
3551 cluster_by: None,
3552 lateral: false,
3553 modifiers_inside: false,
3554 trailing_comments: vec![],
3555 inferred_type: None,
3556 }));
3557
3558 Some(Expression::Alias(Box::new(Alias {
3560 this: subquery,
3561 alias: Identifier::new("_unnested_generate_series".to_string()),
3562 column_aliases: vec![],
3563 alias_explicit_as: false,
3564 alias_keyword: None,
3565 pre_alias_comments: vec![],
3566 trailing_comments: vec![],
3567 inferred_type: None,
3568 })))
3569}
3570
3571pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
3579 match expr {
3580 Expression::Delete(mut delete) => {
3581 if let Some(ref mut where_clause) = delete.where_clause {
3583 where_clause.this = expand_between_recursive(where_clause.this.clone());
3584 }
3585 Ok(Expression::Delete(delete))
3586 }
3587 other => Ok(other),
3588 }
3589}
3590
3591fn expand_between_recursive(expr: Expression) -> Expression {
3593 match expr {
3594 Expression::Between(between) => {
3597 let this = expand_between_recursive(between.this.clone());
3598 let low = expand_between_recursive(between.low);
3599 let high = expand_between_recursive(between.high);
3600
3601 if between.not {
3602 Expression::Or(Box::new(BinaryOp::new(
3604 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
3605 Expression::Gt(Box::new(BinaryOp::new(this, high))),
3606 )))
3607 } else {
3608 Expression::And(Box::new(BinaryOp::new(
3610 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
3611 Expression::Lte(Box::new(BinaryOp::new(this, high))),
3612 )))
3613 }
3614 }
3615
3616 Expression::And(mut op) => {
3618 op.left = expand_between_recursive(op.left);
3619 op.right = expand_between_recursive(op.right);
3620 Expression::And(op)
3621 }
3622 Expression::Or(mut op) => {
3623 op.left = expand_between_recursive(op.left);
3624 op.right = expand_between_recursive(op.right);
3625 Expression::Or(op)
3626 }
3627 Expression::Not(mut op) => {
3628 op.this = expand_between_recursive(op.this);
3629 Expression::Not(op)
3630 }
3631
3632 Expression::Paren(mut paren) => {
3634 paren.this = expand_between_recursive(paren.this);
3635 Expression::Paren(paren)
3636 }
3637
3638 other => other,
3640 }
3641}
3642
3643pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
3652 match expr {
3653 Expression::Select(mut select) => {
3654 if let Some(ref mut with) = select.with {
3655 for cte in &mut with.ctes {
3656 if !cte.columns.is_empty() {
3657 let is_star = matches!(&cte.this, Expression::Select(s) if
3659 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
3660
3661 if is_star {
3662 cte.columns.clear();
3664 continue;
3665 }
3666
3667 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
3669
3670 if let Expression::Select(ref mut inner_select) = cte.this {
3672 let new_exprs: Vec<Expression> = inner_select
3673 .expressions
3674 .drain(..)
3675 .zip(
3676 column_names
3677 .into_iter()
3678 .chain(std::iter::repeat_with(|| Identifier::new(""))),
3679 )
3680 .map(|(expr, col_name)| {
3681 if col_name.name.is_empty() {
3682 return expr;
3683 }
3684 match expr {
3686 Expression::Alias(mut a) => {
3687 a.alias = col_name;
3688 Expression::Alias(a)
3689 }
3690 other => {
3691 Expression::Alias(Box::new(crate::expressions::Alias {
3692 this: other,
3693 alias: col_name,
3694 column_aliases: Vec::new(),
3695 alias_explicit_as: false,
3696 alias_keyword: None,
3697 pre_alias_comments: Vec::new(),
3698 trailing_comments: Vec::new(),
3699 inferred_type: None,
3700 }))
3701 }
3702 }
3703 })
3704 .collect();
3705 inner_select.expressions = new_exprs;
3706 }
3707 }
3708 }
3709 }
3710 Ok(Expression::Select(select))
3711 }
3712 other => Ok(other),
3713 }
3714}
3715
3716pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
3720 match expr {
3721 Expression::Select(mut select) => {
3722 if let Some(ref mut from) = select.from {
3723 for from_item in from.expressions.iter_mut() {
3724 simplify_paren_values_in_from(from_item);
3725 }
3726 }
3727 Ok(Expression::Select(select))
3728 }
3729 other => Ok(other),
3730 }
3731}
3732
3733fn simplify_paren_values_in_from(expr: &mut Expression) {
3734 let replacement = match expr {
3736 Expression::Subquery(ref subquery) => {
3738 if let Expression::Paren(ref paren) = subquery.this {
3739 if matches!(&paren.this, Expression::Values(_)) {
3740 let mut new_sub = subquery.as_ref().clone();
3741 new_sub.this = paren.this.clone();
3742 Some(Expression::Subquery(Box::new(new_sub)))
3743 } else {
3744 None
3745 }
3746 } else {
3747 None
3748 }
3749 }
3750 Expression::Paren(ref outer_paren) => {
3753 if let Expression::Subquery(ref subquery) = outer_paren.this {
3754 if matches!(&subquery.this, Expression::Values(_)) {
3756 Some(outer_paren.this.clone())
3757 }
3758 else if let Expression::Paren(ref paren) = subquery.this {
3760 if matches!(&paren.this, Expression::Values(_)) {
3761 let mut new_sub = subquery.as_ref().clone();
3762 new_sub.this = paren.this.clone();
3763 Some(Expression::Subquery(Box::new(new_sub)))
3764 } else {
3765 None
3766 }
3767 } else {
3768 None
3769 }
3770 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
3771 if matches!(&inner_paren.this, Expression::Values(_)) {
3772 Some(outer_paren.this.clone())
3773 } else {
3774 None
3775 }
3776 } else {
3777 None
3778 }
3779 }
3780 _ => None,
3781 };
3782 if let Some(new_expr) = replacement {
3783 *expr = new_expr;
3784 }
3785}
3786
3787pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
3791 match expr {
3792 Expression::Select(mut select) => {
3793 if let Some(ref mut from) = select.from {
3795 let mut counter = 0usize;
3796 for from_item in from.expressions.iter_mut() {
3797 add_auto_alias_to_from_item(from_item, &mut counter);
3798 }
3799 }
3800 Ok(Expression::Select(select))
3801 }
3802 other => Ok(other),
3803 }
3804}
3805
3806fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
3807 use crate::expressions::Identifier;
3808
3809 match expr {
3810 Expression::Alias(ref mut alias) => {
3811 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
3813 alias.alias = Identifier::new(format!("_t{}", counter));
3814 *counter += 1;
3815 }
3816 }
3817 _ => {}
3818 }
3819}
3820
3821pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
3831 use crate::dialects::transform_recursive;
3832 transform_recursive(expr, &propagate_struct_names_in_expr)
3833}
3834
3835fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
3836 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
3837
3838 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
3840 if elements.len() <= 1 {
3841 return None;
3842 }
3843 if let Some(Expression::Function(ref first_struct)) = elements.first() {
3845 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
3846 let field_names: Vec<Option<String>> = first_struct
3848 .args
3849 .iter()
3850 .map(|arg| {
3851 if let Expression::Alias(a) = arg {
3852 Some(a.alias.name.clone())
3853 } else {
3854 None
3855 }
3856 })
3857 .collect();
3858
3859 if field_names.iter().any(|n| n.is_some()) {
3861 let mut new_elements = Vec::with_capacity(elements.len());
3862 new_elements.push(elements[0].clone());
3863
3864 for elem in &elements[1..] {
3865 if let Expression::Function(ref s) = elem {
3866 if s.name.eq_ignore_ascii_case("STRUCT")
3867 && s.args.len() == field_names.len()
3868 {
3869 let all_unnamed =
3871 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
3872 if all_unnamed {
3873 let new_args: Vec<Expression> = s
3875 .args
3876 .iter()
3877 .zip(field_names.iter())
3878 .map(|(val, name)| {
3879 if let Some(n) = name {
3880 Expression::Alias(Box::new(Alias::new(
3881 val.clone(),
3882 Identifier::new(n.clone()),
3883 )))
3884 } else {
3885 val.clone()
3886 }
3887 })
3888 .collect();
3889 new_elements.push(Expression::Function(Box::new(
3890 Function::new("STRUCT".to_string(), new_args),
3891 )));
3892 continue;
3893 }
3894 }
3895 }
3896 new_elements.push(elem.clone());
3897 }
3898
3899 return Some(new_elements);
3900 }
3901 }
3902 }
3903 None
3904 }
3905
3906 if let Expression::Array(ref arr) = expr {
3908 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3909 return Ok(Expression::Array(Box::new(crate::expressions::Array {
3910 expressions: new_elements,
3911 })));
3912 }
3913 }
3914
3915 if let Expression::ArrayFunc(ref arr) = expr {
3917 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3918 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
3919 expressions: new_elements,
3920 bracket_notation: arr.bracket_notation,
3921 use_list_keyword: arr.use_list_keyword,
3922 })));
3923 }
3924 }
3925
3926 Ok(expr)
3927}
3928
3929pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
3932 use crate::dialects::transform_recursive;
3933 transform_recursive(expr, &unnest_alias_transform_single_select)
3934}
3935
3936pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
3939 use crate::dialects::transform_recursive;
3940 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
3941}
3942
3943fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
3944 if let Expression::Select(mut select) = expr {
3945 if let Some(ref mut from) = select.from {
3946 if from.expressions.len() > 1 {
3947 let mut new_from_exprs = Vec::new();
3948 let mut new_cross_joins = Vec::new();
3949
3950 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3951 if idx == 0 {
3952 new_from_exprs.push(from_item);
3953 } else {
3954 let is_unnest = match &from_item {
3955 Expression::Unnest(_) => true,
3956 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3957 _ => false,
3958 };
3959
3960 if is_unnest {
3961 new_cross_joins.push(crate::expressions::Join {
3962 this: from_item,
3963 on: None,
3964 using: Vec::new(),
3965 kind: JoinKind::Cross,
3966 use_inner_keyword: false,
3967 use_outer_keyword: false,
3968 deferred_condition: false,
3969 join_hint: None,
3970 match_condition: None,
3971 pivots: Vec::new(),
3972 comments: Vec::new(),
3973 nesting_group: 0,
3974 directed: false,
3975 });
3976 } else {
3977 new_from_exprs.push(from_item);
3978 }
3979 }
3980 }
3981
3982 from.expressions = new_from_exprs;
3983 new_cross_joins.append(&mut select.joins);
3984 select.joins = new_cross_joins;
3985 }
3986 }
3987
3988 Ok(Expression::Select(select))
3989 } else {
3990 Ok(expr)
3991 }
3992}
3993
3994pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
3998 use crate::dialects::transform_recursive;
3999 transform_recursive(expr, &wrap_unnest_join_aliases_single)
4000}
4001
4002fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
4003 if let Expression::Select(mut select) = expr {
4004 for join in &mut select.joins {
4006 wrap_unnest_alias_in_join_item(&mut join.this);
4007 }
4008 Ok(Expression::Select(select))
4009 } else {
4010 Ok(expr)
4011 }
4012}
4013
4014fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
4016 use crate::expressions::Identifier;
4017 if let Expression::Alias(alias) = expr {
4018 let is_unnest = match &alias.this {
4020 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
4021 _ => false,
4022 };
4023
4024 if is_unnest && alias.column_aliases.is_empty() {
4025 let original_alias_name = alias.alias.name.clone();
4027 alias.alias = Identifier {
4028 name: "_u".to_string(),
4029 quoted: false,
4030 trailing_comments: Vec::new(),
4031 span: None,
4032 };
4033 alias.column_aliases = vec![Identifier {
4034 name: original_alias_name,
4035 quoted: false,
4036 trailing_comments: Vec::new(),
4037 span: None,
4038 }];
4039 }
4040 }
4041}
4042
4043fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
4044 if let Expression::Select(mut select) = expr {
4045 let mut counter = 0usize;
4046
4047 if let Some(ref mut from) = select.from {
4049 for from_item in from.expressions.iter_mut() {
4051 convert_unnest_alias_in_from(from_item, &mut counter);
4052 }
4053
4054 if from.expressions.len() > 1 {
4056 let mut new_from_exprs = Vec::new();
4057 let mut new_cross_joins = Vec::new();
4058
4059 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4060 if idx == 0 {
4061 new_from_exprs.push(from_item);
4063 } else {
4064 let is_unnest = match &from_item {
4066 Expression::Unnest(_) => true,
4067 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4068 _ => false,
4069 };
4070
4071 if is_unnest {
4072 new_cross_joins.push(crate::expressions::Join {
4074 this: from_item,
4075 on: None,
4076 using: Vec::new(),
4077 kind: JoinKind::Cross,
4078 use_inner_keyword: false,
4079 use_outer_keyword: false,
4080 deferred_condition: false,
4081 join_hint: None,
4082 match_condition: None,
4083 pivots: Vec::new(),
4084 comments: Vec::new(),
4085 nesting_group: 0,
4086 directed: false,
4087 });
4088 } else {
4089 new_from_exprs.push(from_item);
4091 }
4092 }
4093 }
4094
4095 from.expressions = new_from_exprs;
4096 new_cross_joins.append(&mut select.joins);
4098 select.joins = new_cross_joins;
4099 }
4100 }
4101
4102 for join in select.joins.iter_mut() {
4104 convert_unnest_alias_in_from(&mut join.this, &mut counter);
4105 }
4106
4107 Ok(Expression::Select(select))
4108 } else {
4109 Ok(expr)
4110 }
4111}
4112
4113fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
4114 use crate::expressions::Identifier;
4115
4116 if let Expression::Alias(ref mut alias) = expr {
4117 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
4119 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
4120
4121 if is_unnest && alias.column_aliases.is_empty() {
4122 let col_alias = alias.alias.clone();
4124 alias.column_aliases = vec![col_alias];
4125 alias.alias = Identifier::new(format!("_t{}", counter));
4126 *counter += 1;
4127 }
4128 }
4129}
4130
4131pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
4138 use crate::expressions::{Alias, Function};
4139
4140 match expr {
4141 Expression::Select(mut select) => {
4142 let mut new_expressions = Vec::new();
4144 let mut changed = false;
4145
4146 for sel_expr in select.expressions.drain(..) {
4147 if let Expression::Alias(ref alias_box) = sel_expr {
4149 if let Expression::Function(ref func) = alias_box.this {
4150 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4151 let arg = func.args[0].clone();
4152 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4154 (
4155 alias_box.column_aliases[0].name.clone(),
4156 alias_box.column_aliases[1].name.clone(),
4157 )
4158 } else if !alias_box.alias.is_empty() {
4159 ("pos".to_string(), alias_box.alias.name.clone())
4161 } else {
4162 ("pos".to_string(), "col".to_string())
4163 };
4164
4165 let gen_subscripts = Expression::Function(Box::new(Function::new(
4167 "GENERATE_SUBSCRIPTS".to_string(),
4168 vec![
4169 arg.clone(),
4170 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4171 ],
4172 )));
4173 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4174 gen_subscripts,
4175 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4176 )));
4177 let pos_alias = Expression::Alias(Box::new(Alias {
4178 this: sub_one,
4179 alias: Identifier::new(pos_name),
4180 column_aliases: Vec::new(),
4181 alias_explicit_as: false,
4182 alias_keyword: None,
4183 pre_alias_comments: Vec::new(),
4184 trailing_comments: Vec::new(),
4185 inferred_type: None,
4186 }));
4187
4188 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4190 this: arg,
4191 expressions: Vec::new(),
4192 with_ordinality: false,
4193 alias: None,
4194 offset_alias: None,
4195 }));
4196 let col_alias = Expression::Alias(Box::new(Alias {
4197 this: unnest,
4198 alias: Identifier::new(col_name),
4199 column_aliases: Vec::new(),
4200 alias_explicit_as: false,
4201 alias_keyword: None,
4202 pre_alias_comments: Vec::new(),
4203 trailing_comments: Vec::new(),
4204 inferred_type: None,
4205 }));
4206
4207 new_expressions.push(pos_alias);
4208 new_expressions.push(col_alias);
4209 changed = true;
4210 continue;
4211 }
4212 }
4213 }
4214
4215 if let Expression::Function(ref func) = sel_expr {
4217 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4218 let arg = func.args[0].clone();
4219 let pos_name = "pos";
4220 let col_name = "col";
4221
4222 let gen_subscripts = Expression::Function(Box::new(Function::new(
4224 "GENERATE_SUBSCRIPTS".to_string(),
4225 vec![
4226 arg.clone(),
4227 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4228 ],
4229 )));
4230 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4231 gen_subscripts,
4232 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4233 )));
4234 let pos_alias = Expression::Alias(Box::new(Alias {
4235 this: sub_one,
4236 alias: Identifier::new(pos_name),
4237 column_aliases: Vec::new(),
4238 alias_explicit_as: false,
4239 alias_keyword: None,
4240 pre_alias_comments: Vec::new(),
4241 trailing_comments: Vec::new(),
4242 inferred_type: None,
4243 }));
4244
4245 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4247 this: arg,
4248 expressions: Vec::new(),
4249 with_ordinality: false,
4250 alias: None,
4251 offset_alias: None,
4252 }));
4253 let col_alias = Expression::Alias(Box::new(Alias {
4254 this: unnest,
4255 alias: Identifier::new(col_name),
4256 column_aliases: Vec::new(),
4257 alias_explicit_as: false,
4258 alias_keyword: None,
4259 pre_alias_comments: Vec::new(),
4260 trailing_comments: Vec::new(),
4261 inferred_type: None,
4262 }));
4263
4264 new_expressions.push(pos_alias);
4265 new_expressions.push(col_alias);
4266 changed = true;
4267 continue;
4268 }
4269 }
4270
4271 new_expressions.push(sel_expr);
4273 }
4274
4275 if changed {
4276 select.expressions = new_expressions;
4277 } else {
4278 select.expressions = new_expressions;
4279 }
4280
4281 if let Some(ref mut from) = select.from {
4284 expand_posexplode_in_from_duckdb(from)?;
4285 }
4286
4287 Ok(Expression::Select(select))
4288 }
4289 other => Ok(other),
4290 }
4291}
4292
4293fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
4295 use crate::expressions::{Alias, Function};
4296
4297 let mut new_expressions = Vec::new();
4298 let mut _changed = false;
4299
4300 for table_expr in from.expressions.drain(..) {
4301 if let Expression::Alias(ref alias_box) = table_expr {
4303 if let Expression::Function(ref func) = alias_box.this {
4304 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4305 let arg = func.args[0].clone();
4306 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4307 (
4308 alias_box.column_aliases[0].name.clone(),
4309 alias_box.column_aliases[1].name.clone(),
4310 )
4311 } else {
4312 ("pos".to_string(), "col".to_string())
4313 };
4314
4315 let gen_subscripts = Expression::Function(Box::new(Function::new(
4317 "GENERATE_SUBSCRIPTS".to_string(),
4318 vec![
4319 arg.clone(),
4320 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4321 ],
4322 )));
4323 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4324 gen_subscripts,
4325 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4326 )));
4327 let pos_alias = Expression::Alias(Box::new(Alias {
4328 this: sub_one,
4329 alias: Identifier::new(&pos_name),
4330 column_aliases: Vec::new(),
4331 alias_explicit_as: false,
4332 alias_keyword: None,
4333 pre_alias_comments: Vec::new(),
4334 trailing_comments: Vec::new(),
4335 inferred_type: None,
4336 }));
4337 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4338 this: arg,
4339 expressions: Vec::new(),
4340 with_ordinality: false,
4341 alias: None,
4342 offset_alias: None,
4343 }));
4344 let col_alias = Expression::Alias(Box::new(Alias {
4345 this: unnest,
4346 alias: Identifier::new(&col_name),
4347 column_aliases: Vec::new(),
4348 alias_explicit_as: false,
4349 alias_keyword: None,
4350 pre_alias_comments: Vec::new(),
4351 trailing_comments: Vec::new(),
4352 inferred_type: None,
4353 }));
4354
4355 let mut inner_select = Select::new();
4356 inner_select.expressions = vec![pos_alias, col_alias];
4357
4358 let subquery = Expression::Subquery(Box::new(Subquery {
4359 this: Expression::Select(Box::new(inner_select)),
4360 alias: None,
4361 column_aliases: Vec::new(),
4362 alias_explicit_as: false,
4363 alias_keyword: None,
4364 order_by: None,
4365 limit: None,
4366 offset: None,
4367 distribute_by: None,
4368 sort_by: None,
4369 cluster_by: None,
4370 lateral: false,
4371 modifiers_inside: false,
4372 trailing_comments: Vec::new(),
4373 inferred_type: None,
4374 }));
4375 new_expressions.push(subquery);
4376 _changed = true;
4377 continue;
4378 }
4379 }
4380 }
4381
4382 if let Expression::Function(ref func) = table_expr {
4384 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4385 let arg = func.args[0].clone();
4386
4387 let gen_subscripts = Expression::Function(Box::new(Function::new(
4389 "GENERATE_SUBSCRIPTS".to_string(),
4390 vec![
4391 arg.clone(),
4392 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4393 ],
4394 )));
4395 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4396 gen_subscripts,
4397 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4398 )));
4399 let pos_alias = Expression::Alias(Box::new(Alias {
4400 this: sub_one,
4401 alias: Identifier::new("pos"),
4402 column_aliases: Vec::new(),
4403 alias_explicit_as: false,
4404 alias_keyword: None,
4405 pre_alias_comments: Vec::new(),
4406 trailing_comments: Vec::new(),
4407 inferred_type: None,
4408 }));
4409 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4410 this: arg,
4411 expressions: Vec::new(),
4412 with_ordinality: false,
4413 alias: None,
4414 offset_alias: None,
4415 }));
4416 let col_alias = Expression::Alias(Box::new(Alias {
4417 this: unnest,
4418 alias: Identifier::new("col"),
4419 column_aliases: Vec::new(),
4420 alias_explicit_as: false,
4421 alias_keyword: None,
4422 pre_alias_comments: Vec::new(),
4423 trailing_comments: Vec::new(),
4424 inferred_type: None,
4425 }));
4426
4427 let mut inner_select = Select::new();
4428 inner_select.expressions = vec![pos_alias, col_alias];
4429
4430 let subquery = Expression::Subquery(Box::new(Subquery {
4431 this: Expression::Select(Box::new(inner_select)),
4432 alias: None,
4433 column_aliases: Vec::new(),
4434 alias_explicit_as: false,
4435 alias_keyword: None,
4436 order_by: None,
4437 limit: None,
4438 offset: None,
4439 distribute_by: None,
4440 sort_by: None,
4441 cluster_by: None,
4442 lateral: false,
4443 modifiers_inside: false,
4444 trailing_comments: Vec::new(),
4445 inferred_type: None,
4446 }));
4447 new_expressions.push(subquery);
4448 _changed = true;
4449 continue;
4450 }
4451 }
4452
4453 new_expressions.push(table_expr);
4454 }
4455
4456 from.expressions = new_expressions;
4457 Ok(())
4458}
4459
4460pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
4475 match expr {
4476 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
4477 other => Ok(other),
4478 }
4479}
4480
4481pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
4491 match expr {
4492 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
4493 other => Ok(other),
4494 }
4495}
4496
4497fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
4498 let mut flattened_inputs: Vec<Expression> = Vec::new();
4499 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
4500
4501 for sel_expr in select.expressions.into_iter() {
4502 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
4503
4504 let rewritten = transform_recursive(sel_expr, &|e| {
4505 if let Expression::Lateral(lat) = e {
4506 if let Some(input_expr) = extract_flatten_input(&lat) {
4507 if found_input.borrow().is_none() {
4508 *found_input.borrow_mut() = Some(input_expr);
4509 }
4510 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
4511 }
4512 return Ok(Expression::Lateral(lat));
4513 }
4514 Ok(e)
4515 })?;
4516
4517 if let Some(input) = found_input.into_inner() {
4518 flattened_inputs.push(input);
4519 }
4520 new_selects.push(rewritten);
4521 }
4522
4523 if flattened_inputs.is_empty() {
4524 select.expressions = new_selects;
4525 return Ok(Expression::Select(Box::new(select)));
4526 }
4527
4528 select.expressions = new_selects;
4529
4530 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
4531 let is_first = idx == 0;
4533 let series_alias = if is_first {
4534 "pos".to_string()
4535 } else {
4536 format!("pos_{}", idx + 1)
4537 };
4538 let series_source_alias = if is_first {
4539 "_u".to_string()
4540 } else {
4541 format!("_u_{}", idx * 2 + 1)
4542 };
4543 let unnest_source_alias = if is_first {
4544 "_u_2".to_string()
4545 } else {
4546 format!("_u_{}", idx * 2 + 2)
4547 };
4548 let pos2_alias = if is_first {
4549 "pos_2".to_string()
4550 } else {
4551 format!("{}_2", series_alias)
4552 };
4553 let entity_alias = if is_first {
4554 "entity".to_string()
4555 } else {
4556 format!("entity_{}", idx + 1)
4557 };
4558
4559 let array_size_call = Expression::Function(Box::new(Function::new(
4560 "ARRAY_SIZE".to_string(),
4561 vec![Expression::NamedArgument(Box::new(NamedArgument {
4562 name: Identifier::new("INPUT"),
4563 value: input_expr.clone(),
4564 separator: NamedArgSeparator::DArrow,
4565 }))],
4566 )));
4567
4568 let greatest = Expression::Function(Box::new(Function::new(
4569 "GREATEST".to_string(),
4570 vec![array_size_call.clone()],
4571 )));
4572
4573 let series_end = Expression::Add(Box::new(BinaryOp::new(
4574 Expression::Paren(Box::new(crate::expressions::Paren {
4575 this: Expression::Sub(Box::new(BinaryOp::new(
4576 greatest,
4577 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4578 ))),
4579 trailing_comments: Vec::new(),
4580 })),
4581 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4582 )));
4583
4584 let series_range = Expression::Function(Box::new(Function::new(
4585 "ARRAY_GENERATE_RANGE".to_string(),
4586 vec![
4587 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
4588 series_end,
4589 ],
4590 )));
4591
4592 let series_flatten = Expression::Function(Box::new(Function::new(
4593 "FLATTEN".to_string(),
4594 vec![Expression::NamedArgument(Box::new(NamedArgument {
4595 name: Identifier::new("INPUT"),
4596 value: series_range,
4597 separator: NamedArgSeparator::DArrow,
4598 }))],
4599 )));
4600
4601 let series_table = Expression::Function(Box::new(Function::new(
4602 "TABLE".to_string(),
4603 vec![series_flatten],
4604 )));
4605
4606 let series_alias_expr = Expression::Alias(Box::new(Alias {
4607 this: series_table,
4608 alias: Identifier::new(series_source_alias.clone()),
4609 column_aliases: vec![
4610 Identifier::new("seq"),
4611 Identifier::new("key"),
4612 Identifier::new("path"),
4613 Identifier::new("index"),
4614 Identifier::new(series_alias.clone()),
4615 Identifier::new("this"),
4616 ],
4617 alias_explicit_as: false,
4618 alias_keyword: None,
4619 pre_alias_comments: Vec::new(),
4620 trailing_comments: Vec::new(),
4621 inferred_type: None,
4622 }));
4623
4624 select.joins.push(Join {
4625 this: series_alias_expr,
4626 on: None,
4627 using: Vec::new(),
4628 kind: JoinKind::Cross,
4629 use_inner_keyword: false,
4630 use_outer_keyword: false,
4631 deferred_condition: false,
4632 join_hint: None,
4633 match_condition: None,
4634 pivots: Vec::new(),
4635 comments: Vec::new(),
4636 nesting_group: 0,
4637 directed: false,
4638 });
4639
4640 let entity_flatten = Expression::Function(Box::new(Function::new(
4641 "FLATTEN".to_string(),
4642 vec![Expression::NamedArgument(Box::new(NamedArgument {
4643 name: Identifier::new("INPUT"),
4644 value: input_expr.clone(),
4645 separator: NamedArgSeparator::DArrow,
4646 }))],
4647 )));
4648
4649 let entity_table = Expression::Function(Box::new(Function::new(
4650 "TABLE".to_string(),
4651 vec![entity_flatten],
4652 )));
4653
4654 let entity_alias_expr = Expression::Alias(Box::new(Alias {
4655 this: entity_table,
4656 alias: Identifier::new(unnest_source_alias.clone()),
4657 column_aliases: vec![
4658 Identifier::new("seq"),
4659 Identifier::new("key"),
4660 Identifier::new("path"),
4661 Identifier::new(pos2_alias.clone()),
4662 Identifier::new(entity_alias.clone()),
4663 Identifier::new("this"),
4664 ],
4665 alias_explicit_as: false,
4666 alias_keyword: None,
4667 pre_alias_comments: Vec::new(),
4668 trailing_comments: Vec::new(),
4669 inferred_type: None,
4670 }));
4671
4672 select.joins.push(Join {
4673 this: entity_alias_expr,
4674 on: None,
4675 using: Vec::new(),
4676 kind: JoinKind::Cross,
4677 use_inner_keyword: false,
4678 use_outer_keyword: false,
4679 deferred_condition: false,
4680 join_hint: None,
4681 match_condition: None,
4682 pivots: Vec::new(),
4683 comments: Vec::new(),
4684 nesting_group: 0,
4685 directed: false,
4686 });
4687
4688 let pos_col =
4689 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
4690 let pos2_col =
4691 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
4692
4693 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
4694 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
4695 this: Expression::Sub(Box::new(BinaryOp::new(
4696 array_size_call,
4697 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4698 ))),
4699 trailing_comments: Vec::new(),
4700 }));
4701 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
4702 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
4703 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
4704 let or_cond = Expression::Or(Box::new(BinaryOp::new(
4705 eq,
4706 Expression::Paren(Box::new(crate::expressions::Paren {
4707 this: and_cond,
4708 trailing_comments: Vec::new(),
4709 })),
4710 )));
4711
4712 select.where_clause = Some(match select.where_clause.take() {
4713 Some(existing) => Where {
4714 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
4715 },
4716 None => Where { this: or_cond },
4717 });
4718 }
4719
4720 Ok(Expression::Select(Box::new(select)))
4721}
4722
4723fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
4724 let Expression::Function(f) = lat.this.as_ref() else {
4725 return None;
4726 };
4727 if !f.name.eq_ignore_ascii_case("FLATTEN") {
4728 return None;
4729 }
4730
4731 for arg in &f.args {
4732 if let Expression::NamedArgument(na) = arg {
4733 if na.name.name.eq_ignore_ascii_case("INPUT") {
4734 return Some(na.value.clone());
4735 }
4736 }
4737 }
4738 f.args.first().cloned()
4739}
4740
4741fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
4742 let cond = Expression::Eq(Box::new(BinaryOp::new(
4743 Expression::qualified_column("_u", "pos"),
4744 Expression::qualified_column("_u_2", "pos_2"),
4745 )));
4746 let true_expr = Expression::qualified_column("_u_2", "entity");
4747 let iff_expr = Expression::Function(Box::new(Function::new(
4748 "IFF".to_string(),
4749 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
4750 )));
4751
4752 lat.this = Box::new(iff_expr);
4753 if lat.column_aliases.is_empty() {
4754 lat.column_aliases = vec![
4755 "SEQ".to_string(),
4756 "KEY".to_string(),
4757 "PATH".to_string(),
4758 "INDEX".to_string(),
4759 "VALUE".to_string(),
4760 "THIS".to_string(),
4761 ];
4762 }
4763 lat
4764}
4765
4766struct ExplodeInfo {
4768 arg_sql: String,
4770 explode_alias: String,
4772 pos_alias: String,
4774 unnest_source_alias: String,
4776}
4777
4778fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
4779 let is_presto = matches!(
4780 target,
4781 DialectType::Presto | DialectType::Trino | DialectType::Athena
4782 );
4783 let is_bigquery = matches!(target, DialectType::BigQuery);
4784
4785 if !is_presto && !is_bigquery {
4786 return Ok(Expression::Select(Box::new(select)));
4787 }
4788
4789 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
4791 if !has_explode {
4792 return Ok(Expression::Select(Box::new(select)));
4793 }
4794
4795 let mut taken_select_names = std::collections::HashSet::new();
4797 let mut taken_source_names = std::collections::HashSet::new();
4798
4799 for sel in &select.expressions {
4801 if let Some(name) = get_output_name(sel) {
4802 taken_select_names.insert(name);
4803 }
4804 }
4805
4806 for sel in &select.expressions {
4808 let explode_expr = find_explode_in_expr(sel);
4809 if let Some(arg) = explode_expr {
4810 if let Some(name) = get_output_name(&arg) {
4811 taken_select_names.insert(name);
4812 }
4813 }
4814 }
4815
4816 if let Some(ref from) = select.from {
4818 for from_expr in &from.expressions {
4819 collect_source_names(from_expr, &mut taken_source_names);
4820 }
4821 }
4822 for join in &select.joins {
4824 collect_source_names(&join.this, &mut taken_source_names);
4825 }
4826
4827 let series_alias = new_name(&mut taken_select_names, "pos");
4829
4830 let series_source_alias = new_name(&mut taken_source_names, "_u");
4832
4833 let target_dialect = Dialect::get(target);
4835
4836 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
4838 let mut new_projections: Vec<String> = Vec::new();
4839
4840 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
4841 let explode_data = extract_explode_data(sel_expr);
4842
4843 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
4844 let arg_sql = target_dialect
4846 .generate(&arg_expr)
4847 .unwrap_or_else(|_| "NULL".to_string());
4848
4849 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
4850
4851 let explode_alias = if let Some(ref ea) = explicit_alias {
4852 taken_select_names.remove(ea.as_str());
4855 let name = new_name(&mut taken_select_names, ea);
4857 name
4858 } else {
4859 new_name(&mut taken_select_names, "col")
4860 };
4861
4862 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
4863 taken_select_names.remove(pa.as_str());
4865 let name = new_name(&mut taken_select_names, pa);
4866 name
4867 } else {
4868 new_name(&mut taken_select_names, "pos")
4869 };
4870
4871 if is_presto {
4873 let if_col = format!(
4875 "IF({}.{} = {}.{}, {}.{}) AS {}",
4876 series_source_alias,
4877 series_alias,
4878 unnest_source_alias,
4879 pos_alias,
4880 unnest_source_alias,
4881 explode_alias,
4882 explode_alias
4883 );
4884 new_projections.push(if_col);
4885
4886 if is_posexplode {
4888 let if_pos = format!(
4889 "IF({}.{} = {}.{}, {}.{}) AS {}",
4890 series_source_alias,
4891 series_alias,
4892 unnest_source_alias,
4893 pos_alias,
4894 unnest_source_alias,
4895 pos_alias,
4896 pos_alias
4897 );
4898 new_projections.push(if_pos);
4899 }
4900 } else {
4901 let if_col = format!(
4903 "IF({} = {}, {}, NULL) AS {}",
4904 series_alias, pos_alias, explode_alias, explode_alias
4905 );
4906 new_projections.push(if_col);
4907
4908 if is_posexplode {
4910 let if_pos = format!(
4911 "IF({} = {}, {}, NULL) AS {}",
4912 series_alias, pos_alias, pos_alias, pos_alias
4913 );
4914 new_projections.push(if_pos);
4915 }
4916 }
4917
4918 explode_infos.push(ExplodeInfo {
4919 arg_sql,
4920 explode_alias,
4921 pos_alias,
4922 unnest_source_alias,
4923 });
4924 } else {
4925 let sel_sql = target_dialect
4927 .generate(sel_expr)
4928 .unwrap_or_else(|_| "*".to_string());
4929 new_projections.push(sel_sql);
4930 }
4931 }
4932
4933 if explode_infos.is_empty() {
4934 return Ok(Expression::Select(Box::new(select)));
4935 }
4936
4937 let mut from_parts: Vec<String> = Vec::new();
4939
4940 if let Some(ref from) = select.from {
4942 for from_expr in &from.expressions {
4943 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
4944 from_parts.push(from_sql);
4945 }
4946 }
4947
4948 let size_exprs: Vec<String> = explode_infos
4950 .iter()
4951 .map(|info| {
4952 if is_presto {
4953 format!("CARDINALITY({})", info.arg_sql)
4954 } else {
4955 format!("ARRAY_LENGTH({})", info.arg_sql)
4956 }
4957 })
4958 .collect();
4959
4960 let greatest_arg = if size_exprs.len() == 1 {
4961 size_exprs[0].clone()
4962 } else {
4963 format!("GREATEST({})", size_exprs.join(", "))
4964 };
4965
4966 let series_sql = if is_presto {
4969 if size_exprs.len() == 1 {
4971 format!(
4972 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
4973 greatest_arg, series_source_alias, series_alias
4974 )
4975 } else {
4976 format!(
4978 "UNNEST(SEQUENCE(1, {})) AS {}({})",
4979 greatest_arg, series_source_alias, series_alias
4980 )
4981 }
4982 } else {
4983 if size_exprs.len() == 1 {
4985 format!(
4986 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
4987 greatest_arg, series_alias
4988 )
4989 } else {
4990 format!(
4992 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
4993 greatest_arg, series_alias
4994 )
4995 }
4996 };
4997
4998 let mut cross_joins: Vec<String> = Vec::new();
5002
5003 for info in &explode_infos {
5004 cross_joins.push(format!(
5006 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
5007 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
5008 ));
5009 }
5010
5011 let mut where_conditions: Vec<String> = Vec::new();
5013
5014 for info in &explode_infos {
5015 let size_expr = if is_presto {
5016 format!("CARDINALITY({})", info.arg_sql)
5017 } else {
5018 format!("ARRAY_LENGTH({})", info.arg_sql)
5019 };
5020
5021 let cond = if is_presto {
5022 format!(
5023 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
5024 series_src = series_source_alias,
5025 series_al = series_alias,
5026 unnest_src = info.unnest_source_alias,
5027 pos_al = info.pos_alias,
5028 size = size_expr
5029 )
5030 } else {
5031 format!(
5032 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
5033 series_al = series_alias,
5034 pos_al = info.pos_alias,
5035 size = size_expr
5036 )
5037 };
5038
5039 where_conditions.push(cond);
5040 }
5041
5042 let where_sql = if where_conditions.len() == 1 {
5044 where_conditions[0].clone()
5045 } else {
5046 where_conditions
5047 .iter()
5048 .map(|c| format!("({})", c))
5049 .collect::<Vec<_>>()
5050 .join(" AND ")
5051 };
5052
5053 let select_part = new_projections.join(", ");
5055
5056 let from_and_joins = if from_parts.is_empty() {
5058 format!("FROM {} {}", series_sql, cross_joins.join(" "))
5060 } else {
5061 format!(
5062 "FROM {} {} {}",
5063 from_parts.join(", "),
5064 format!("CROSS JOIN {}", series_sql),
5065 cross_joins.join(" ")
5066 )
5067 };
5068
5069 let full_sql = format!(
5070 "SELECT {} {} WHERE {}",
5071 select_part, from_and_joins, where_sql
5072 );
5073
5074 let generic_dialect = Dialect::get(DialectType::Generic);
5077 let parsed = generic_dialect.parse(&full_sql);
5078 match parsed {
5079 Ok(mut stmts) if !stmts.is_empty() => {
5080 let mut result = stmts.remove(0);
5081
5082 if is_bigquery {
5086 convert_unnest_presto_to_bigquery(&mut result);
5087 }
5088
5089 Ok(result)
5090 }
5091 _ => {
5092 Ok(Expression::Select(Box::new(select)))
5094 }
5095 }
5096}
5097
5098fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
5102 match expr {
5103 Expression::Select(ref mut select) => {
5104 if let Some(ref mut from) = select.from {
5106 for from_item in from.expressions.iter_mut() {
5107 convert_unnest_presto_to_bigquery(from_item);
5108 }
5109 }
5110 for join in select.joins.iter_mut() {
5112 convert_unnest_presto_to_bigquery(&mut join.this);
5113 }
5114 }
5115 Expression::Alias(ref alias) => {
5116 if let Expression::Unnest(ref unnest) = alias.this {
5118 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
5119 let col_alias = alias.column_aliases[0].clone();
5120 let pos_alias = alias.column_aliases[1].clone();
5121 let mut new_unnest = unnest.as_ref().clone();
5122 new_unnest.alias = Some(col_alias);
5123 new_unnest.offset_alias = Some(pos_alias);
5124 *expr = Expression::Unnest(Box::new(new_unnest));
5126 }
5127 }
5128 }
5129 _ => {}
5130 }
5131}
5132
5133fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
5136 if !names.contains(base) {
5137 names.insert(base.to_string());
5138 return base.to_string();
5139 }
5140 let mut i = 2;
5141 loop {
5142 let candidate = format!("{}_{}", base, i);
5143 if !names.contains(&candidate) {
5144 names.insert(candidate.clone());
5145 return candidate;
5146 }
5147 i += 1;
5148 }
5149}
5150
5151fn expr_contains_explode(expr: &Expression) -> bool {
5153 match expr {
5154 Expression::Explode(_) => true,
5155 Expression::ExplodeOuter(_) => true,
5156 Expression::Function(f) => {
5157 let name = f.name.to_uppercase();
5158 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
5159 }
5160 Expression::Alias(a) => expr_contains_explode(&a.this),
5161 _ => false,
5162 }
5163}
5164
5165fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
5167 match expr {
5168 Expression::Explode(uf) => Some(uf.this.clone()),
5169 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
5170 Expression::Function(f) => {
5171 let name = f.name.to_uppercase();
5172 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5173 Some(f.args[0].clone())
5174 } else {
5175 None
5176 }
5177 }
5178 Expression::Alias(a) => find_explode_in_expr(&a.this),
5179 _ => None,
5180 }
5181}
5182
5183fn extract_explode_data(
5186 expr: &Expression,
5187) -> Option<(bool, Expression, Option<String>, Option<String>)> {
5188 match expr {
5189 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
5191 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
5192 Expression::Function(f) => {
5194 let name = f.name.to_uppercase();
5195 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5196 Some((true, f.args[0].clone(), None, None))
5197 } else {
5198 None
5199 }
5200 }
5201 Expression::Alias(a) => {
5203 match &a.this {
5204 Expression::Explode(uf) => {
5205 let alias = if !a.alias.is_empty() {
5206 Some(a.alias.name.clone())
5207 } else {
5208 None
5209 };
5210 Some((false, uf.this.clone(), alias, None))
5211 }
5212 Expression::ExplodeOuter(uf) => {
5213 let alias = if !a.alias.is_empty() {
5214 Some(a.alias.name.clone())
5215 } else {
5216 None
5217 };
5218 Some((false, uf.this.clone(), alias, None))
5219 }
5220 Expression::Function(f) => {
5221 let name = f.name.to_uppercase();
5222 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5223 if a.column_aliases.len() == 2 {
5225 let pos_alias = a.column_aliases[0].name.clone();
5226 let col_alias = a.column_aliases[1].name.clone();
5227 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
5228 } else if !a.alias.is_empty() {
5229 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
5231 } else {
5232 Some((true, f.args[0].clone(), None, None))
5233 }
5234 } else {
5235 None
5236 }
5237 }
5238 _ => None,
5239 }
5240 }
5241 _ => None,
5242 }
5243}
5244
5245fn get_output_name(expr: &Expression) -> Option<String> {
5247 match expr {
5248 Expression::Alias(a) => {
5249 if !a.alias.is_empty() {
5250 Some(a.alias.name.clone())
5251 } else {
5252 None
5253 }
5254 }
5255 Expression::Column(c) => Some(c.name.name.clone()),
5256 Expression::Identifier(id) => Some(id.name.clone()),
5257 _ => None,
5258 }
5259}
5260
5261fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
5263 match expr {
5264 Expression::Alias(a) => {
5265 if !a.alias.is_empty() {
5266 names.insert(a.alias.name.clone());
5267 }
5268 }
5269 Expression::Subquery(s) => {
5270 if let Some(ref alias) = s.alias {
5271 names.insert(alias.name.clone());
5272 }
5273 }
5274 Expression::Table(t) => {
5275 if let Some(ref alias) = t.alias {
5276 names.insert(alias.name.clone());
5277 } else {
5278 names.insert(t.name.name.clone());
5279 }
5280 }
5281 Expression::Column(c) => {
5282 names.insert(c.name.name.clone());
5283 }
5284 Expression::Identifier(id) => {
5285 names.insert(id.name.clone());
5286 }
5287 _ => {}
5288 }
5289}
5290
5291pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
5294 use crate::dialects::transform_recursive;
5295 transform_recursive(expr, &strip_unnest_column_refs_single)
5296}
5297
5298fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
5299 if let Expression::Select(mut select) = expr {
5300 for join in select.joins.iter_mut() {
5302 strip_unnest_from_expr(&mut join.this);
5303 }
5304 if let Some(ref mut from) = select.from {
5306 for from_item in from.expressions.iter_mut() {
5307 strip_unnest_from_expr(from_item);
5308 }
5309 }
5310 Ok(Expression::Select(select))
5311 } else {
5312 Ok(expr)
5313 }
5314}
5315
5316fn strip_unnest_from_expr(expr: &mut Expression) {
5319 if let Expression::Alias(ref mut alias) = expr {
5320 if let Expression::Unnest(ref unnest) = alias.this {
5321 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
5322 if is_column_ref {
5323 let inner = unnest.this.clone();
5325 alias.this = inner;
5326 }
5327 }
5328 }
5329}
5330
5331pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
5334 use crate::dialects::transform_recursive;
5335 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
5336}
5337
5338fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
5339 if let Expression::Select(mut select) = expr {
5340 if let Some(ref mut from) = select.from {
5342 for from_item in from.expressions.iter_mut() {
5343 try_wrap_unnest_in_subquery(from_item);
5344 }
5345 }
5346
5347 for join in select.joins.iter_mut() {
5349 try_wrap_unnest_in_subquery(&mut join.this);
5350 }
5351
5352 Ok(Expression::Select(select))
5353 } else {
5354 Ok(expr)
5355 }
5356}
5357
5358fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
5360 match expr {
5361 Expression::Array(arr) => arr
5363 .expressions
5364 .iter()
5365 .any(|e| matches!(e, Expression::Struct(_))),
5366 Expression::ArrayFunc(arr) => arr
5367 .expressions
5368 .iter()
5369 .any(|e| matches!(e, Expression::Struct(_))),
5370 Expression::Cast(c) => {
5372 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
5373 }
5374 _ => false,
5375 }
5376}
5377
5378fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
5381 if let Expression::Alias(ref alias) = expr {
5383 if let Expression::Unnest(ref unnest) = alias.this {
5384 if is_struct_array_unnest_arg(&unnest.this) {
5385 let unnest_clone = (**unnest).clone();
5386 let alias_name = alias.alias.clone();
5387 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
5388 *expr = new_expr;
5389 return;
5390 }
5391 }
5392 }
5393
5394 if let Expression::Unnest(ref unnest) = expr {
5396 if is_struct_array_unnest_arg(&unnest.this) {
5397 let unnest_clone = (**unnest).clone();
5398 let new_expr = make_unnest_subquery(unnest_clone, None);
5399 *expr = new_expr;
5400 }
5401 }
5402}
5403
5404fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
5406 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
5408 name: Identifier::new("max_depth".to_string()),
5409 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
5410 separator: NamedArgSeparator::DArrow,
5411 }));
5412
5413 let mut unnest_args = vec![unnest.this];
5414 unnest_args.extend(unnest.expressions);
5415 unnest_args.push(max_depth_arg);
5416
5417 let unnest_func =
5418 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
5419
5420 let mut inner_select = Select::new();
5422 inner_select.expressions = vec![unnest_func];
5423 let inner_select = Expression::Select(Box::new(inner_select));
5424
5425 let subquery = Subquery {
5427 this: inner_select,
5428 alias,
5429 column_aliases: Vec::new(),
5430 alias_explicit_as: false,
5431 alias_keyword: None,
5432 order_by: None,
5433 limit: None,
5434 offset: None,
5435 distribute_by: None,
5436 sort_by: None,
5437 cluster_by: None,
5438 lateral: false,
5439 modifiers_inside: false,
5440 trailing_comments: Vec::new(),
5441 inferred_type: None,
5442 };
5443
5444 Expression::Subquery(Box::new(subquery))
5445}
5446
5447pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
5459 use crate::expressions::{Limit as LimitClause, Offset as OffsetClause, OrderBy, Star};
5460
5461 match expr {
5462 Expression::Union(mut u) => {
5463 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
5466 if let Expression::Select(ref mut right_select) = u.right {
5468 if right_select.order_by.is_some()
5469 || right_select.limit.is_some()
5470 || right_select.offset.is_some()
5471 {
5472 u.order_by = right_select.order_by.take();
5474 u.limit = right_select.limit.take().map(|l| Box::new(l.this));
5475 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
5476 }
5477 }
5478 }
5479
5480 let has_order_or_limit =
5481 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
5482 if has_order_or_limit {
5483 let order_by: Option<OrderBy> = u.order_by.take();
5485 let union_limit: Option<Box<Expression>> = u.limit.take();
5486 let union_offset: Option<Box<Expression>> = u.offset.take();
5487
5488 let select_limit: Option<LimitClause> = union_limit.map(|l| LimitClause {
5490 this: *l,
5491 percent: false,
5492 comments: Vec::new(),
5493 });
5494
5495 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
5497 this: *o,
5498 rows: None,
5499 });
5500
5501 let subquery = Subquery {
5503 this: Expression::Union(u),
5504 alias: Some(Identifier::new("_l_0")),
5505 column_aliases: Vec::new(),
5506 alias_explicit_as: true,
5507 alias_keyword: None,
5508 lateral: false,
5509 modifiers_inside: false,
5510 order_by: None,
5511 limit: None,
5512 offset: None,
5513 distribute_by: None,
5514 sort_by: None,
5515 cluster_by: None,
5516 trailing_comments: Vec::new(),
5517 inferred_type: None,
5518 };
5519
5520 let mut select = Select::default();
5522 select.expressions = vec![Expression::Star(Star {
5523 table: None,
5524 except: None,
5525 replace: None,
5526 rename: None,
5527 trailing_comments: Vec::new(),
5528 span: None,
5529 })];
5530 select.from = Some(From {
5531 expressions: vec![Expression::Subquery(Box::new(subquery))],
5532 });
5533 select.order_by = order_by;
5534 select.limit = select_limit;
5535 select.offset = select_offset;
5536
5537 Ok(Expression::Select(Box::new(select)))
5538 } else {
5539 Ok(Expression::Union(u))
5540 }
5541 }
5542 _ => Ok(expr),
5543 }
5544}
5545
5546pub fn expand_like_any(expr: Expression) -> Result<Expression> {
5554 use crate::expressions::{BinaryOp, LikeOp, Paren};
5555
5556 const LIKE_ALL_MARKER: &str = "__LIKE_ALL_EXPANSION__";
5559
5560 fn unwrap_parens(e: &Expression) -> &Expression {
5561 match e {
5562 Expression::Paren(p) => unwrap_parens(&p.this),
5563 _ => e,
5564 }
5565 }
5566
5567 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
5568 let inner = unwrap_parens(e);
5569 match inner {
5570 Expression::Tuple(t) => Some(t.expressions.clone()),
5571 _ if !matches!(e, Expression::Tuple(_)) => Some(vec![inner.clone()]),
5573 _ => None,
5574 }
5575 }
5576
5577 fn expand_like_quantifier(
5579 op: &LikeOp,
5580 values: Vec<Expression>,
5581 is_ilike: bool,
5582 combiner: fn(Expression, Expression) -> Expression,
5583 wrap_marker: bool,
5584 ) -> Expression {
5585 let num_values = values.len();
5586 let mut result: Option<Expression> = None;
5587 for val in values {
5588 let like = if is_ilike {
5589 Expression::ILike(Box::new(LikeOp {
5590 left: op.left.clone(),
5591 right: val,
5592 escape: op.escape.clone(),
5593 quantifier: None,
5594 inferred_type: None,
5595 }))
5596 } else {
5597 Expression::Like(Box::new(LikeOp {
5598 left: op.left.clone(),
5599 right: val,
5600 escape: op.escape.clone(),
5601 quantifier: None,
5602 inferred_type: None,
5603 }))
5604 };
5605 result = Some(match result {
5606 None => like,
5607 Some(prev) => combiner(prev, like),
5608 });
5609 }
5610 let expanded = result.unwrap_or_else(|| unreachable!("values is non-empty"));
5611 if wrap_marker && num_values > 1 {
5615 Expression::Paren(Box::new(Paren {
5616 this: expanded,
5617 trailing_comments: vec![LIKE_ALL_MARKER.to_string()],
5618 }))
5619 } else {
5620 expanded
5621 }
5622 }
5623
5624 fn or_combiner(a: Expression, b: Expression) -> Expression {
5625 Expression::Or(Box::new(BinaryOp::new(a, b)))
5626 }
5627
5628 fn and_combiner(a: Expression, b: Expression) -> Expression {
5629 Expression::And(Box::new(BinaryOp::new(a, b)))
5630 }
5631
5632 fn is_like_all_marker(p: &Paren) -> bool {
5633 p.trailing_comments.len() == 1 && p.trailing_comments[0] == LIKE_ALL_MARKER
5634 }
5635
5636 let result = transform_recursive(expr, &|e| {
5644 match e {
5645 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
5647 if let Some(values) = extract_tuple_values(&op.right) {
5648 if values.is_empty() {
5649 return Ok(e);
5650 }
5651 Ok(expand_like_quantifier(
5652 op,
5653 values,
5654 false,
5655 or_combiner,
5656 false,
5657 ))
5658 } else {
5659 Ok(e)
5660 }
5661 }
5662 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ALL") => {
5664 if let Some(values) = extract_tuple_values(&op.right) {
5665 if values.is_empty() {
5666 return Ok(e);
5667 }
5668 Ok(expand_like_quantifier(
5669 op,
5670 values,
5671 false,
5672 and_combiner,
5673 true,
5674 ))
5675 } else {
5676 Ok(e)
5677 }
5678 }
5679 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
5681 if let Some(values) = extract_tuple_values(&op.right) {
5682 if values.is_empty() {
5683 return Ok(e);
5684 }
5685 Ok(expand_like_quantifier(op, values, true, or_combiner, false))
5686 } else {
5687 Ok(e)
5688 }
5689 }
5690 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ALL") => {
5692 if let Some(values) = extract_tuple_values(&op.right) {
5693 if values.is_empty() {
5694 return Ok(e);
5695 }
5696 Ok(expand_like_quantifier(op, values, true, and_combiner, true))
5697 } else {
5698 Ok(e)
5699 }
5700 }
5701 Expression::And(mut op) => {
5706 if matches!(&op.left, Expression::Or(_)) {
5707 op.left = Expression::Paren(Box::new(Paren {
5708 this: op.left,
5709 trailing_comments: vec![],
5710 }));
5711 }
5712 if matches!(&op.right, Expression::Or(_)) {
5713 op.right = Expression::Paren(Box::new(Paren {
5714 this: op.right,
5715 trailing_comments: vec![],
5716 }));
5717 }
5718 Ok(Expression::And(op))
5719 }
5720 Expression::Or(mut op) => {
5723 if let Expression::Paren(ref mut p) = op.left {
5724 if is_like_all_marker(p) {
5725 p.trailing_comments.clear();
5726 }
5727 }
5728 if let Expression::Paren(ref mut p) = op.right {
5729 if is_like_all_marker(p) {
5730 p.trailing_comments.clear();
5731 }
5732 }
5733 Ok(Expression::Or(op))
5734 }
5735 _ => Ok(e),
5736 }
5737 })?;
5738
5739 transform_recursive(result, &|e| {
5743 if let Expression::Paren(p) = &e {
5744 if is_like_all_marker(p) {
5745 let Expression::Paren(p) = e else {
5746 unreachable!()
5747 };
5748 return Ok(p.this);
5749 }
5750 }
5751 Ok(e)
5752 })
5753}
5754
5755pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
5763 use crate::expressions::Alias;
5764
5765 fn add_self_aliases_to_select(select: &mut Select) {
5766 let new_expressions: Vec<Expression> = select
5767 .expressions
5768 .iter()
5769 .map(|e| {
5770 match e {
5771 Expression::Column(col) => {
5773 let alias_name = col.name.clone();
5774 Expression::Alias(Box::new(Alias {
5775 this: e.clone(),
5776 alias: alias_name,
5777 column_aliases: Vec::new(),
5778 alias_explicit_as: false,
5779 alias_keyword: None,
5780 pre_alias_comments: Vec::new(),
5781 trailing_comments: Vec::new(),
5782 inferred_type: None,
5783 }))
5784 }
5785 _ => e.clone(),
5787 }
5788 })
5789 .collect();
5790 select.expressions = new_expressions;
5791 }
5792
5793 fn walk_and_qualify(expr: &mut Expression) {
5794 match expr {
5795 Expression::Select(ref mut select) => {
5796 if let Some(ref mut from) = select.from {
5798 for e in from.expressions.iter_mut() {
5799 qualify_subquery_expr(e);
5800 walk_and_qualify(e);
5801 }
5802 }
5803 for join in select.joins.iter_mut() {
5805 qualify_subquery_expr(&mut join.this);
5806 walk_and_qualify(&mut join.this);
5807 }
5808 for e in select.expressions.iter_mut() {
5810 walk_and_qualify(e);
5811 }
5812 if let Some(ref mut w) = select.where_clause {
5814 walk_and_qualify(&mut w.this);
5815 }
5816 }
5817 Expression::Subquery(ref mut subquery) => {
5818 walk_and_qualify(&mut subquery.this);
5819 }
5820 Expression::Union(ref mut u) => {
5821 walk_and_qualify(&mut u.left);
5822 walk_and_qualify(&mut u.right);
5823 }
5824 Expression::Intersect(ref mut i) => {
5825 walk_and_qualify(&mut i.left);
5826 walk_and_qualify(&mut i.right);
5827 }
5828 Expression::Except(ref mut e) => {
5829 walk_and_qualify(&mut e.left);
5830 walk_and_qualify(&mut e.right);
5831 }
5832 Expression::Cte(ref mut cte) => {
5833 walk_and_qualify(&mut cte.this);
5834 }
5835 _ => {}
5836 }
5837 }
5838
5839 fn qualify_subquery_expr(expr: &mut Expression) {
5840 match expr {
5841 Expression::Subquery(ref mut subquery) => {
5842 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
5844 if let Expression::Select(ref mut inner_select) = subquery.this {
5845 let has_star = inner_select
5847 .expressions
5848 .iter()
5849 .any(|e| matches!(e, Expression::Star(_)));
5850 if !has_star {
5851 add_self_aliases_to_select(inner_select);
5852 }
5853 }
5854 }
5855 walk_and_qualify(&mut subquery.this);
5857 }
5858 Expression::Alias(ref mut alias) => {
5859 qualify_subquery_expr(&mut alias.this);
5860 }
5861 _ => {}
5862 }
5863 }
5864
5865 let mut result = expr;
5866 walk_and_qualify(&mut result);
5867
5868 if let Expression::Select(ref mut select) = result {
5870 if let Some(ref mut with) = select.with {
5871 for cte in with.ctes.iter_mut() {
5872 if cte.columns.is_empty() {
5874 walk_and_qualify(&mut cte.this);
5876 }
5877 }
5878 }
5879 }
5880
5881 Ok(result)
5882}
5883
5884#[cfg(test)]
5885mod tests {
5886 use super::*;
5887 use crate::dialects::{Dialect, DialectType};
5888 use crate::expressions::Column;
5889
5890 fn gen(expr: &Expression) -> String {
5891 let dialect = Dialect::get(DialectType::Generic);
5892 dialect.generate(expr).unwrap()
5893 }
5894
5895 #[test]
5896 fn test_preprocess() {
5897 let expr = Expression::Boolean(BooleanLiteral { value: true });
5898 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
5899 assert!(
5900 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
5901 );
5902 }
5903
5904 #[test]
5905 fn test_preprocess_chain() {
5906 let expr = Expression::Boolean(BooleanLiteral { value: true });
5908 let transforms: Vec<fn(Expression) -> Result<Expression>> =
5910 vec![replace_bool_with_int, replace_int_with_bool];
5911 let result = preprocess(expr, &transforms).unwrap();
5912 if let Expression::Boolean(b) = result {
5915 assert!(b.value);
5916 } else {
5917 panic!("Expected boolean literal");
5918 }
5919 }
5920
5921 #[test]
5922 fn test_unnest_to_explode() {
5923 let unnest = Expression::Unnest(Box::new(UnnestFunc {
5924 this: Expression::boxed_column(Column {
5925 name: Identifier::new("arr".to_string()),
5926 table: None,
5927 join_mark: false,
5928 trailing_comments: vec![],
5929 span: None,
5930 inferred_type: None,
5931 }),
5932 expressions: Vec::new(),
5933 with_ordinality: false,
5934 alias: None,
5935 offset_alias: None,
5936 }));
5937
5938 let result = unnest_to_explode(unnest).unwrap();
5939 assert!(matches!(result, Expression::Explode(_)));
5940 }
5941
5942 #[test]
5943 fn test_explode_to_unnest() {
5944 let explode = Expression::Explode(Box::new(UnaryFunc {
5945 this: Expression::boxed_column(Column {
5946 name: Identifier::new("arr".to_string()),
5947 table: None,
5948 join_mark: false,
5949 trailing_comments: vec![],
5950 span: None,
5951 inferred_type: None,
5952 }),
5953 original_name: None,
5954 inferred_type: None,
5955 }));
5956
5957 let result = explode_to_unnest(explode).unwrap();
5958 assert!(matches!(result, Expression::Unnest(_)));
5959 }
5960
5961 #[test]
5962 fn test_replace_bool_with_int() {
5963 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
5964 let result = replace_bool_with_int(true_expr).unwrap();
5965 if let Expression::Literal(lit) = result {
5966 if let Literal::Number(n) = lit.as_ref() {
5967 assert_eq!(n, "1");
5968 }
5969 } else {
5970 panic!("Expected number literal");
5971 }
5972
5973 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
5974 let result = replace_bool_with_int(false_expr).unwrap();
5975 if let Expression::Literal(lit) = result {
5976 if let Literal::Number(n) = lit.as_ref() {
5977 assert_eq!(n, "0");
5978 }
5979 } else {
5980 panic!("Expected number literal");
5981 }
5982 }
5983
5984 #[test]
5985 fn test_replace_int_with_bool() {
5986 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
5987 let result = replace_int_with_bool(one_expr).unwrap();
5988 if let Expression::Boolean(b) = result {
5989 assert!(b.value);
5990 } else {
5991 panic!("Expected boolean true");
5992 }
5993
5994 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
5995 let result = replace_int_with_bool(zero_expr).unwrap();
5996 if let Expression::Boolean(b) = result {
5997 assert!(!b.value);
5998 } else {
5999 panic!("Expected boolean false");
6000 }
6001
6002 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
6004 let result = replace_int_with_bool(two_expr).unwrap();
6005 assert!(
6006 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6007 );
6008 }
6009
6010 #[test]
6011 fn test_strip_data_type_params() {
6012 let decimal = DataType::Decimal {
6014 precision: Some(10),
6015 scale: Some(2),
6016 };
6017 let stripped = strip_data_type_params(decimal);
6018 assert_eq!(
6019 stripped,
6020 DataType::Decimal {
6021 precision: None,
6022 scale: None
6023 }
6024 );
6025
6026 let varchar = DataType::VarChar {
6028 length: Some(255),
6029 parenthesized_length: false,
6030 };
6031 let stripped = strip_data_type_params(varchar);
6032 assert_eq!(
6033 stripped,
6034 DataType::VarChar {
6035 length: None,
6036 parenthesized_length: false
6037 }
6038 );
6039
6040 let char_type = DataType::Char { length: Some(10) };
6042 let stripped = strip_data_type_params(char_type);
6043 assert_eq!(stripped, DataType::Char { length: None });
6044
6045 let timestamp = DataType::Timestamp {
6047 precision: Some(6),
6048 timezone: true,
6049 };
6050 let stripped = strip_data_type_params(timestamp);
6051 assert_eq!(
6052 stripped,
6053 DataType::Timestamp {
6054 precision: None,
6055 timezone: true
6056 }
6057 );
6058
6059 let array = DataType::Array {
6061 element_type: Box::new(DataType::VarChar {
6062 length: Some(100),
6063 parenthesized_length: false,
6064 }),
6065 dimension: None,
6066 };
6067 let stripped = strip_data_type_params(array);
6068 assert_eq!(
6069 stripped,
6070 DataType::Array {
6071 element_type: Box::new(DataType::VarChar {
6072 length: None,
6073 parenthesized_length: false
6074 }),
6075 dimension: None,
6076 }
6077 );
6078
6079 let text = DataType::Text;
6081 let stripped = strip_data_type_params(text);
6082 assert_eq!(stripped, DataType::Text);
6083 }
6084
6085 #[test]
6086 fn test_remove_precision_parameterized_types_cast() {
6087 let cast_expr = Expression::Cast(Box::new(Cast {
6089 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6090 to: DataType::Decimal {
6091 precision: Some(10),
6092 scale: Some(2),
6093 },
6094 trailing_comments: vec![],
6095 double_colon_syntax: false,
6096 format: None,
6097 default: None,
6098 inferred_type: None,
6099 }));
6100
6101 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6102 if let Expression::Cast(cast) = result {
6103 assert_eq!(
6104 cast.to,
6105 DataType::Decimal {
6106 precision: None,
6107 scale: None
6108 }
6109 );
6110 } else {
6111 panic!("Expected Cast expression");
6112 }
6113 }
6114
6115 #[test]
6116 fn test_remove_precision_parameterized_types_varchar() {
6117 let cast_expr = Expression::Cast(Box::new(Cast {
6119 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
6120 to: DataType::VarChar {
6121 length: Some(10),
6122 parenthesized_length: false,
6123 },
6124 trailing_comments: vec![],
6125 double_colon_syntax: false,
6126 format: None,
6127 default: None,
6128 inferred_type: None,
6129 }));
6130
6131 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6132 if let Expression::Cast(cast) = result {
6133 assert_eq!(
6134 cast.to,
6135 DataType::VarChar {
6136 length: None,
6137 parenthesized_length: false
6138 }
6139 );
6140 } else {
6141 panic!("Expected Cast expression");
6142 }
6143 }
6144
6145 #[test]
6146 fn test_remove_precision_direct_cast() {
6147 let cast = Expression::Cast(Box::new(Cast {
6151 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6152 to: DataType::Decimal {
6153 precision: Some(10),
6154 scale: Some(2),
6155 },
6156 trailing_comments: vec![],
6157 double_colon_syntax: false,
6158 format: None,
6159 default: None,
6160 inferred_type: None,
6161 }));
6162
6163 let transformed = remove_precision_parameterized_types(cast).unwrap();
6164 let generated = gen(&transformed);
6165
6166 assert!(generated.contains("DECIMAL"));
6168 assert!(!generated.contains("(10"));
6169 }
6170
6171 #[test]
6172 fn test_epoch_cast_to_ts() {
6173 let cast_expr = Expression::Cast(Box::new(Cast {
6175 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
6176 to: DataType::Timestamp {
6177 precision: None,
6178 timezone: false,
6179 },
6180 trailing_comments: vec![],
6181 double_colon_syntax: false,
6182 format: None,
6183 default: None,
6184 inferred_type: None,
6185 }));
6186
6187 let result = epoch_cast_to_ts(cast_expr).unwrap();
6188 if let Expression::Cast(cast) = result {
6189 if let Expression::Literal(lit) = cast.this {
6190 if let Literal::String(s) = lit.as_ref() {
6191 assert_eq!(s, "1970-01-01 00:00:00");
6192 }
6193 } else {
6194 panic!("Expected string literal");
6195 }
6196 } else {
6197 panic!("Expected Cast expression");
6198 }
6199 }
6200
6201 #[test]
6202 fn test_epoch_cast_to_ts_preserves_non_epoch() {
6203 let cast_expr = Expression::Cast(Box::new(Cast {
6205 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
6206 to: DataType::Timestamp {
6207 precision: None,
6208 timezone: false,
6209 },
6210 trailing_comments: vec![],
6211 double_colon_syntax: false,
6212 format: None,
6213 default: None,
6214 inferred_type: None,
6215 }));
6216
6217 let result = epoch_cast_to_ts(cast_expr).unwrap();
6218 if let Expression::Cast(cast) = result {
6219 if let Expression::Literal(lit) = cast.this {
6220 if let Literal::String(s) = lit.as_ref() {
6221 assert_eq!(s, "2024-01-15");
6222 }
6223 } else {
6224 panic!("Expected string literal");
6225 }
6226 } else {
6227 panic!("Expected Cast expression");
6228 }
6229 }
6230
6231 #[test]
6232 fn test_unqualify_columns() {
6233 let col = Expression::boxed_column(Column {
6235 name: Identifier::new("id".to_string()),
6236 table: Some(Identifier::new("users".to_string())),
6237 join_mark: false,
6238 trailing_comments: vec![],
6239 span: None,
6240 inferred_type: None,
6241 });
6242
6243 let result = unqualify_columns(col).unwrap();
6244 if let Expression::Column(c) = result {
6245 assert!(c.table.is_none());
6246 assert_eq!(c.name.name, "id");
6247 } else {
6248 panic!("Expected Column expression");
6249 }
6250 }
6251
6252 #[test]
6253 fn test_is_temporal_type() {
6254 assert!(is_temporal_type(&DataType::Date));
6255 assert!(is_temporal_type(&DataType::Timestamp {
6256 precision: None,
6257 timezone: false
6258 }));
6259 assert!(is_temporal_type(&DataType::Time {
6260 precision: None,
6261 timezone: false
6262 }));
6263 assert!(!is_temporal_type(&DataType::Int {
6264 length: None,
6265 integer_spelling: false
6266 }));
6267 assert!(!is_temporal_type(&DataType::VarChar {
6268 length: None,
6269 parenthesized_length: false
6270 }));
6271 }
6272
6273 #[test]
6274 fn test_eliminate_semi_join_basic() {
6275 use crate::expressions::{Join, TableRef};
6276
6277 let select = Expression::Select(Box::new(Select {
6279 expressions: vec![Expression::boxed_column(Column {
6280 name: Identifier::new("a".to_string()),
6281 table: None,
6282 join_mark: false,
6283 trailing_comments: vec![],
6284 span: None,
6285 inferred_type: None,
6286 })],
6287 from: Some(From {
6288 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
6289 }),
6290 joins: vec![Join {
6291 this: Expression::Table(Box::new(TableRef::new("t2"))),
6292 kind: JoinKind::Semi,
6293 on: Some(Expression::Eq(Box::new(BinaryOp {
6294 left: Expression::boxed_column(Column {
6295 name: Identifier::new("x".to_string()),
6296 table: None,
6297 join_mark: false,
6298 trailing_comments: vec![],
6299 span: None,
6300 inferred_type: None,
6301 }),
6302 right: Expression::boxed_column(Column {
6303 name: Identifier::new("y".to_string()),
6304 table: None,
6305 join_mark: false,
6306 trailing_comments: vec![],
6307 span: None,
6308 inferred_type: None,
6309 }),
6310 left_comments: vec![],
6311 operator_comments: vec![],
6312 trailing_comments: vec![],
6313 inferred_type: None,
6314 }))),
6315 using: vec![],
6316 use_inner_keyword: false,
6317 use_outer_keyword: false,
6318 deferred_condition: false,
6319 join_hint: None,
6320 match_condition: None,
6321 pivots: Vec::new(),
6322 comments: Vec::new(),
6323 nesting_group: 0,
6324 directed: false,
6325 }],
6326 ..Select::new()
6327 }));
6328
6329 let result = eliminate_semi_and_anti_joins(select).unwrap();
6330 if let Expression::Select(s) = result {
6331 assert!(s.joins.is_empty());
6333 assert!(s.where_clause.is_some());
6335 } else {
6336 panic!("Expected Select expression");
6337 }
6338 }
6339
6340 #[test]
6341 fn test_no_ilike_sql() {
6342 use crate::expressions::LikeOp;
6343
6344 let ilike_expr = Expression::ILike(Box::new(LikeOp {
6346 left: Expression::boxed_column(Column {
6347 name: Identifier::new("name".to_string()),
6348 table: None,
6349 join_mark: false,
6350 trailing_comments: vec![],
6351 span: None,
6352 inferred_type: None,
6353 }),
6354 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
6355 escape: None,
6356 quantifier: None,
6357 inferred_type: None,
6358 }));
6359
6360 let result = no_ilike_sql(ilike_expr).unwrap();
6361 if let Expression::Like(like) = result {
6362 if let Expression::Function(f) = &like.left {
6364 assert_eq!(f.name, "LOWER");
6365 } else {
6366 panic!("Expected LOWER function on left");
6367 }
6368 if let Expression::Function(f) = &like.right {
6370 assert_eq!(f.name, "LOWER");
6371 } else {
6372 panic!("Expected LOWER function on right");
6373 }
6374 } else {
6375 panic!("Expected Like expression");
6376 }
6377 }
6378
6379 #[test]
6380 fn test_no_trycast_sql() {
6381 let trycast_expr = Expression::TryCast(Box::new(Cast {
6383 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6384 to: DataType::Int {
6385 length: None,
6386 integer_spelling: false,
6387 },
6388 trailing_comments: vec![],
6389 double_colon_syntax: false,
6390 format: None,
6391 default: None,
6392 inferred_type: None,
6393 }));
6394
6395 let result = no_trycast_sql(trycast_expr).unwrap();
6396 assert!(matches!(result, Expression::Cast(_)));
6397 }
6398
6399 #[test]
6400 fn test_no_safe_cast_sql() {
6401 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
6403 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6404 to: DataType::Int {
6405 length: None,
6406 integer_spelling: false,
6407 },
6408 trailing_comments: vec![],
6409 double_colon_syntax: false,
6410 format: None,
6411 default: None,
6412 inferred_type: None,
6413 }));
6414
6415 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
6416 assert!(matches!(result, Expression::Cast(_)));
6417 }
6418
6419 #[test]
6420 fn test_explode_to_unnest_presto() {
6421 let spark = Dialect::get(DialectType::Spark);
6422 let result = spark
6423 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
6424 .unwrap();
6425 assert_eq!(
6426 result[0],
6427 "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))"
6428 );
6429 }
6430
6431 #[test]
6432 fn test_explode_to_unnest_bigquery() {
6433 let spark = Dialect::get(DialectType::Spark);
6434 let result = spark
6435 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
6436 .unwrap();
6437 assert_eq!(
6438 result[0],
6439 "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))"
6440 );
6441 }
6442}