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 let is_simple_case = case.operand.is_some();
2403 if let Some(operand) = case.operand.take() {
2404 case.operand = Some(ensure_bools_in_value_context(operand));
2405 }
2406 case.whens = case
2407 .whens
2408 .into_iter()
2409 .map(|(condition, result)| {
2410 let new_condition = if is_simple_case {
2411 ensure_bools_in_value_context(condition)
2412 } else {
2413 ensure_bool_condition(ensure_bools_in_value_context(condition))
2414 };
2415 let new_result = ensure_bools_in_value_context(result);
2416 (new_condition, new_result)
2417 })
2418 .collect();
2419 if let Some(else_expr) = case.else_ {
2420 case.else_ = Some(ensure_bools_in_value_context(else_expr));
2421 }
2422 Expression::Case(Box::new(*case))
2423 }
2424 Expression::Select(select) => Expression::Select(Box::new(ensure_bools_in_select(*select))),
2425 Expression::Subquery(mut subquery) => {
2426 subquery.this = ensure_bools_in_value_context(subquery.this);
2427 Expression::Subquery(subquery)
2428 }
2429 Expression::JoinedTable(mut joined_table) => {
2430 joined_table.left = ensure_bools_in_value_context(joined_table.left);
2431 joined_table.joins = joined_table
2432 .joins
2433 .into_iter()
2434 .map(ensure_bools_in_join)
2435 .collect();
2436 joined_table.lateral_views = joined_table
2437 .lateral_views
2438 .into_iter()
2439 .map(|mut lateral_view| {
2440 lateral_view.this = ensure_bools_in_value_context(lateral_view.this);
2441 lateral_view
2442 })
2443 .collect();
2444 Expression::JoinedTable(joined_table)
2445 }
2446 Expression::Union(mut union) => {
2447 let left = std::mem::replace(&mut union.left, Expression::null());
2448 let right = std::mem::replace(&mut union.right, Expression::null());
2449 union.left = ensure_bools_in_value_context(left);
2450 union.right = ensure_bools_in_value_context(right);
2451 if let Some(with) = union.with.take() {
2452 union.with = Some(ensure_bools_in_with(with));
2453 }
2454 Expression::Union(union)
2455 }
2456 Expression::Intersect(mut intersect) => {
2457 let left = std::mem::replace(&mut intersect.left, Expression::null());
2458 let right = std::mem::replace(&mut intersect.right, Expression::null());
2459 intersect.left = ensure_bools_in_value_context(left);
2460 intersect.right = ensure_bools_in_value_context(right);
2461 if let Some(with) = intersect.with.take() {
2462 intersect.with = Some(ensure_bools_in_with(with));
2463 }
2464 Expression::Intersect(intersect)
2465 }
2466 Expression::Except(mut except) => {
2467 let left = std::mem::replace(&mut except.left, Expression::null());
2468 let right = std::mem::replace(&mut except.right, Expression::null());
2469 except.left = ensure_bools_in_value_context(left);
2470 except.right = ensure_bools_in_value_context(right);
2471 if let Some(with) = except.with.take() {
2472 except.with = Some(ensure_bools_in_with(with));
2473 }
2474 Expression::Except(except)
2475 }
2476 Expression::Alias(mut alias) => {
2477 alias.this = ensure_bools_in_value_context(alias.this);
2478 Expression::Alias(alias)
2479 }
2480 Expression::Paren(mut paren) => {
2481 paren.this = ensure_bools_in_value_context(paren.this);
2482 Expression::Paren(paren)
2483 }
2484 other => other,
2485 }
2486}
2487
2488fn ensure_bools_in_select(mut select: Select) -> Select {
2489 select.expressions = select
2490 .expressions
2491 .into_iter()
2492 .map(ensure_bools_in_value_context)
2493 .collect();
2494
2495 if let Some(from) = select.from.take() {
2496 select.from = Some(crate::expressions::From {
2497 expressions: from
2498 .expressions
2499 .into_iter()
2500 .map(ensure_bools_in_value_context)
2501 .collect(),
2502 });
2503 }
2504
2505 select.joins = select.joins.into_iter().map(ensure_bools_in_join).collect();
2506
2507 if let Some(mut where_clause) = select.where_clause.take() {
2508 where_clause.this = ensure_bool_condition(ensure_bools_in_value_context(where_clause.this));
2509 select.where_clause = Some(where_clause);
2510 }
2511
2512 if let Some(mut having) = select.having.take() {
2513 having.this = ensure_bool_condition(ensure_bools_in_value_context(having.this));
2514 select.having = Some(having);
2515 }
2516
2517 if let Some(with) = select.with.take() {
2518 select.with = Some(ensure_bools_in_with(with));
2519 }
2520
2521 select
2522}
2523
2524fn ensure_bools_in_join(mut join: Join) -> Join {
2525 join.this = ensure_bools_in_value_context(join.this);
2526
2527 if let Some(on) = join.on.take() {
2528 join.on = Some(ensure_bool_condition(ensure_bools_in_value_context(on)));
2529 }
2530
2531 if let Some(match_condition) = join.match_condition.take() {
2532 join.match_condition = Some(ensure_bool_condition(ensure_bools_in_value_context(
2533 match_condition,
2534 )));
2535 }
2536
2537 join.pivots = join
2538 .pivots
2539 .into_iter()
2540 .map(ensure_bools_in_value_context)
2541 .collect();
2542
2543 join
2544}
2545
2546fn ensure_bools_in_with(mut with: With) -> With {
2547 with.ctes = with
2548 .ctes
2549 .into_iter()
2550 .map(|mut cte| {
2551 cte.this = ensure_bools_in_value_context(cte.this);
2552 cte
2553 })
2554 .collect();
2555 with
2556}
2557
2558fn is_boolean_expression(expr: &Expression) -> bool {
2561 matches!(
2562 expr,
2563 Expression::Eq(_)
2564 | Expression::Neq(_)
2565 | Expression::Lt(_)
2566 | Expression::Lte(_)
2567 | Expression::Gt(_)
2568 | Expression::Gte(_)
2569 | Expression::Is(_)
2570 | Expression::IsNull(_)
2571 | Expression::IsTrue(_)
2572 | Expression::IsFalse(_)
2573 | Expression::Like(_)
2574 | Expression::ILike(_)
2575 | Expression::StartsWith(_)
2576 | Expression::SimilarTo(_)
2577 | Expression::Glob(_)
2578 | Expression::RegexpLike(_)
2579 | Expression::In(_)
2580 | Expression::Between(_)
2581 | Expression::Exists(_)
2582 | Expression::And(_)
2583 | Expression::Or(_)
2584 | Expression::Not(_)
2585 | Expression::Any(_)
2586 | Expression::All(_)
2587 | Expression::NullSafeEq(_)
2588 | Expression::NullSafeNeq(_)
2589 | Expression::EqualNull(_)
2590 )
2591}
2592
2593fn wrap_neq_zero(expr: Expression) -> Expression {
2595 Expression::Neq(Box::new(BinaryOp {
2596 left: expr,
2597 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2598 left_comments: vec![],
2599 operator_comments: vec![],
2600 trailing_comments: vec![],
2601 inferred_type: None,
2602 }))
2603}
2604
2605pub(crate) fn ensure_bool_condition(expr: Expression) -> Expression {
2611 match expr {
2612 Expression::And(op) => {
2614 let new_op = BinaryOp {
2615 left: ensure_bool_condition(op.left.clone()),
2616 right: ensure_bool_condition(op.right.clone()),
2617 left_comments: op.left_comments.clone(),
2618 operator_comments: op.operator_comments.clone(),
2619 trailing_comments: op.trailing_comments.clone(),
2620 inferred_type: None,
2621 };
2622 Expression::And(Box::new(new_op))
2623 }
2624 Expression::Or(op) => {
2625 let new_op = BinaryOp {
2626 left: ensure_bool_condition(op.left.clone()),
2627 right: ensure_bool_condition(op.right.clone()),
2628 left_comments: op.left_comments.clone(),
2629 operator_comments: op.operator_comments.clone(),
2630 trailing_comments: op.trailing_comments.clone(),
2631 inferred_type: None,
2632 };
2633 Expression::Or(Box::new(new_op))
2634 }
2635 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
2637 this: ensure_bool_condition(op.this.clone()),
2638 inferred_type: None,
2639 })),
2640 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
2642 this: ensure_bool_condition(paren.this.clone()),
2643 trailing_comments: paren.trailing_comments.clone(),
2644 })),
2645 Expression::Boolean(BooleanLiteral { value: true }) => {
2647 Expression::Paren(Box::new(crate::expressions::Paren {
2648 this: Expression::Eq(Box::new(BinaryOp {
2649 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2650 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2651 left_comments: vec![],
2652 operator_comments: vec![],
2653 trailing_comments: vec![],
2654 inferred_type: None,
2655 })),
2656 trailing_comments: vec![],
2657 }))
2658 }
2659 Expression::Boolean(BooleanLiteral { value: false }) => {
2660 Expression::Paren(Box::new(crate::expressions::Paren {
2661 this: Expression::Eq(Box::new(BinaryOp {
2662 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
2663 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
2664 left_comments: vec![],
2665 operator_comments: vec![],
2666 trailing_comments: vec![],
2667 inferred_type: None,
2668 })),
2669 trailing_comments: vec![],
2670 }))
2671 }
2672 ref e if is_boolean_expression(e) => expr,
2674 _ => wrap_neq_zero(expr),
2677 }
2678}
2679
2680pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
2686 Ok(unqualify_columns_recursive(expr))
2687}
2688
2689fn unqualify_columns_recursive(expr: Expression) -> Expression {
2691 match expr {
2692 Expression::Column(mut col) => {
2693 col.table = None;
2694 Expression::Column(col)
2695 }
2696 Expression::Select(mut select) => {
2697 select.expressions = select
2698 .expressions
2699 .into_iter()
2700 .map(unqualify_columns_recursive)
2701 .collect();
2702 if let Some(ref mut where_clause) = select.where_clause {
2703 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
2704 }
2705 if let Some(ref mut having) = select.having {
2706 having.this = unqualify_columns_recursive(having.this.clone());
2707 }
2708 if let Some(ref mut group_by) = select.group_by {
2709 group_by.expressions = group_by
2710 .expressions
2711 .iter()
2712 .cloned()
2713 .map(unqualify_columns_recursive)
2714 .collect();
2715 }
2716 if let Some(ref mut order_by) = select.order_by {
2717 order_by.expressions = order_by
2718 .expressions
2719 .iter()
2720 .map(|o| crate::expressions::Ordered {
2721 this: unqualify_columns_recursive(o.this.clone()),
2722 desc: o.desc,
2723 nulls_first: o.nulls_first,
2724 explicit_asc: o.explicit_asc,
2725 with_fill: o.with_fill.clone(),
2726 })
2727 .collect();
2728 }
2729 for join in &mut select.joins {
2730 if let Some(ref mut on) = join.on {
2731 *on = unqualify_columns_recursive(on.clone());
2732 }
2733 }
2734 Expression::Select(select)
2735 }
2736 Expression::Alias(mut alias) => {
2737 alias.this = unqualify_columns_recursive(alias.this);
2738 Expression::Alias(alias)
2739 }
2740 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
2742 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
2743 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
2744 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
2745 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
2746 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
2747 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
2748 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
2749 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
2750 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
2751 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
2752 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
2753 Expression::Function(mut func) => {
2755 func.args = func
2756 .args
2757 .into_iter()
2758 .map(unqualify_columns_recursive)
2759 .collect();
2760 Expression::Function(func)
2761 }
2762 Expression::AggregateFunction(mut func) => {
2763 func.args = func
2764 .args
2765 .into_iter()
2766 .map(unqualify_columns_recursive)
2767 .collect();
2768 Expression::AggregateFunction(func)
2769 }
2770 Expression::Case(mut case) => {
2771 case.whens = case
2772 .whens
2773 .into_iter()
2774 .map(|(cond, result)| {
2775 (
2776 unqualify_columns_recursive(cond),
2777 unqualify_columns_recursive(result),
2778 )
2779 })
2780 .collect();
2781 if let Some(else_expr) = case.else_ {
2782 case.else_ = Some(unqualify_columns_recursive(else_expr));
2783 }
2784 Expression::Case(case)
2785 }
2786 other => other,
2788 }
2789}
2790
2791fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
2793 op.left = unqualify_columns_recursive(op.left);
2794 op.right = unqualify_columns_recursive(op.right);
2795 op
2796}
2797
2798pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
2818 match expr {
2819 Expression::Select(mut select) => {
2820 let mut cte_count = 0;
2821 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2822
2823 if let Some(ref mut with) = select.with {
2825 for cte in &mut with.ctes {
2826 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
2827 }
2828 }
2829
2830 if let Some(ref mut from) = select.from {
2832 for table_expr in &mut from.expressions {
2833 if let Some((cte, replacement)) =
2834 try_convert_generate_date_array(table_expr, &mut cte_count)
2835 {
2836 new_ctes.push(cte);
2837 *table_expr = replacement;
2838 }
2839 }
2840 }
2841
2842 for join in &mut select.joins {
2844 if let Some((cte, replacement)) =
2845 try_convert_generate_date_array(&join.this, &mut cte_count)
2846 {
2847 new_ctes.push(cte);
2848 join.this = replacement;
2849 }
2850 }
2851
2852 if !new_ctes.is_empty() {
2854 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
2855 ctes: Vec::new(),
2856 recursive: true, leading_comments: vec![],
2858 search: None,
2859 });
2860 with_clause.recursive = true;
2861
2862 let mut all_ctes = new_ctes;
2864 all_ctes.append(&mut with_clause.ctes);
2865 with_clause.ctes = all_ctes;
2866 }
2867
2868 Ok(Expression::Select(select))
2869 }
2870 other => Ok(other),
2871 }
2872}
2873
2874fn process_expression_for_gda(
2877 expr: &mut Expression,
2878 cte_count: &mut usize,
2879 new_ctes: &mut Vec<crate::expressions::Cte>,
2880) {
2881 match expr {
2882 Expression::Select(ref mut select) => {
2883 if let Some(ref mut from) = select.from {
2885 for table_expr in &mut from.expressions {
2886 if let Some((cte, replacement)) =
2887 try_convert_generate_date_array(table_expr, cte_count)
2888 {
2889 new_ctes.push(cte);
2890 *table_expr = replacement;
2891 }
2892 }
2893 }
2894 for join in &mut select.joins {
2896 if let Some((cte, replacement)) =
2897 try_convert_generate_date_array(&join.this, cte_count)
2898 {
2899 new_ctes.push(cte);
2900 join.this = replacement;
2901 }
2902 }
2903 }
2904 Expression::Union(ref mut u) => {
2905 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
2906 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
2907 }
2908 Expression::Subquery(ref mut sq) => {
2909 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
2910 }
2911 _ => {}
2912 }
2913}
2914
2915fn try_convert_generate_date_array(
2918 expr: &Expression,
2919 cte_count: &mut usize,
2920) -> Option<(crate::expressions::Cte, Expression)> {
2921 try_convert_generate_date_array_with_name(expr, cte_count, None)
2922}
2923
2924fn try_convert_generate_date_array_with_name(
2925 expr: &Expression,
2926 cte_count: &mut usize,
2927 column_name_override: Option<&str>,
2928) -> Option<(crate::expressions::Cte, Expression)> {
2929 fn extract_gda_args(
2931 inner: &Expression,
2932 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
2933 match inner {
2934 Expression::GenerateDateArray(gda) => {
2935 let start = gda.start.as_ref()?;
2936 let end = gda.end.as_ref()?;
2937 let step = gda.step.as_deref();
2938 Some((start, end, step))
2939 }
2940 Expression::GenerateSeries(gs) => {
2941 let start = gs.start.as_deref()?;
2942 let end = gs.end.as_deref()?;
2943 let step = gs.step.as_deref();
2944 Some((start, end, step))
2945 }
2946 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
2947 if f.args.len() >= 2 {
2948 let start = &f.args[0];
2949 let end = &f.args[1];
2950 let step = f.args.get(2);
2951 Some((start, end, step))
2952 } else {
2953 None
2954 }
2955 }
2956 _ => None,
2957 }
2958 }
2959
2960 if let Expression::Unnest(unnest) = expr {
2962 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
2963 let start = start;
2964 let end = end;
2965 let step: Option<&Expression> = step_opt;
2966
2967 let cte_name = if *cte_count == 0 {
2969 "_generated_dates".to_string()
2970 } else {
2971 format!("_generated_dates_{}", cte_count)
2972 };
2973 *cte_count += 1;
2974
2975 let column_name =
2976 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
2977
2978 let cast_to_date = |expr: &Expression| -> Expression {
2980 match expr {
2981 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
2982 if let Expression::Literal(lit) = expr {
2984 if let Literal::Date(d) = lit.as_ref() {
2985 Expression::Cast(Box::new(Cast {
2986 this: Expression::Literal(Box::new(Literal::String(d.clone()))),
2987 to: DataType::Date,
2988 trailing_comments: vec![],
2989 double_colon_syntax: false,
2990 format: None,
2991 default: None,
2992 inferred_type: None,
2993 }))
2994 } else {
2995 expr.clone()
2996 }
2997 } else {
2998 unreachable!()
2999 }
3000 }
3001 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
3002 _ => Expression::Cast(Box::new(Cast {
3003 this: expr.clone(),
3004 to: DataType::Date,
3005 trailing_comments: vec![],
3006 double_colon_syntax: false,
3007 format: None,
3008 default: None,
3009 inferred_type: None,
3010 })),
3011 }
3012 };
3013
3014 let base_select = Select {
3016 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
3017 this: cast_to_date(start),
3018 alias: column_name.clone(),
3019 column_aliases: vec![],
3020 alias_explicit_as: false,
3021 alias_keyword: None,
3022 pre_alias_comments: vec![],
3023 trailing_comments: vec![],
3024 inferred_type: None,
3025 }))],
3026 ..Select::new()
3027 };
3028
3029 let normalize_interval = |expr: &Expression| -> Expression {
3031 if let Expression::Interval(ref iv) = expr {
3032 let mut iv_clone = iv.as_ref().clone();
3033 if let Some(Expression::Literal(ref lit)) = iv_clone.this {
3034 if let Literal::String(ref s) = lit.as_ref() {
3035 if s.parse::<f64>().is_ok() {
3037 iv_clone.this =
3038 Some(Expression::Literal(Box::new(Literal::Number(s.clone()))));
3039 }
3040 }
3041 }
3042 Expression::Interval(Box::new(iv_clone))
3043 } else {
3044 expr.clone()
3045 }
3046 };
3047
3048 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
3051 Expression::Interval(Box::new(crate::expressions::Interval {
3052 this: Some(Expression::Literal(Box::new(Literal::Number(
3053 "1".to_string(),
3054 )))),
3055 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
3056 unit: crate::expressions::IntervalUnit::Day,
3057 use_plural: false,
3058 }),
3059 }))
3060 });
3061
3062 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
3064
3065 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
3066 this: Expression::Column(Box::new(crate::expressions::Column {
3067 name: column_name.clone(),
3068 table: None,
3069 join_mark: false,
3070 trailing_comments: vec![],
3071 span: None,
3072 inferred_type: None,
3073 })),
3074 interval: add_count,
3075 unit: add_unit,
3076 }));
3077
3078 let cast_date_add = Expression::Cast(Box::new(Cast {
3079 this: date_add_expr.clone(),
3080 to: DataType::Date,
3081 trailing_comments: vec![],
3082 double_colon_syntax: false,
3083 format: None,
3084 default: None,
3085 inferred_type: None,
3086 }));
3087
3088 let recursive_select = Select {
3089 expressions: vec![cast_date_add.clone()],
3090 from: Some(From {
3091 expressions: vec![Expression::Table(Box::new(
3092 crate::expressions::TableRef::new(&cte_name),
3093 ))],
3094 }),
3095 where_clause: Some(Where {
3096 this: Expression::Lte(Box::new(BinaryOp {
3097 left: cast_date_add,
3098 right: cast_to_date(end),
3099 left_comments: vec![],
3100 operator_comments: vec![],
3101 trailing_comments: vec![],
3102 inferred_type: None,
3103 })),
3104 }),
3105 ..Select::new()
3106 };
3107
3108 let union = crate::expressions::Union {
3110 left: Expression::Select(Box::new(base_select)),
3111 right: Expression::Select(Box::new(recursive_select)),
3112 all: true, distinct: false,
3114 with: None,
3115 order_by: None,
3116 limit: None,
3117 offset: None,
3118 distribute_by: None,
3119 sort_by: None,
3120 cluster_by: None,
3121 by_name: false,
3122 side: None,
3123 kind: None,
3124 corresponding: false,
3125 strict: false,
3126 on_columns: Vec::new(),
3127 };
3128
3129 let cte = crate::expressions::Cte {
3131 this: Expression::Union(Box::new(union)),
3132 alias: Identifier::new(cte_name.clone()),
3133 columns: vec![column_name.clone()],
3134 materialized: None,
3135 key_expressions: Vec::new(),
3136 alias_first: true,
3137 comments: Vec::new(),
3138 };
3139
3140 let replacement_select = Select {
3142 expressions: vec![Expression::Column(Box::new(crate::expressions::Column {
3143 name: column_name,
3144 table: None,
3145 join_mark: false,
3146 trailing_comments: vec![],
3147 span: None,
3148 inferred_type: None,
3149 }))],
3150 from: Some(From {
3151 expressions: vec![Expression::Table(Box::new(
3152 crate::expressions::TableRef::new(&cte_name),
3153 ))],
3154 }),
3155 ..Select::new()
3156 };
3157
3158 let replacement = Expression::Subquery(Box::new(Subquery {
3159 this: Expression::Select(Box::new(replacement_select)),
3160 alias: Some(Identifier::new(cte_name)),
3161 column_aliases: vec![],
3162 alias_explicit_as: false,
3163 alias_keyword: None,
3164 order_by: None,
3165 limit: None,
3166 offset: None,
3167 distribute_by: None,
3168 sort_by: None,
3169 cluster_by: None,
3170 lateral: false,
3171 modifiers_inside: false,
3172 trailing_comments: vec![],
3173 inferred_type: None,
3174 }));
3175
3176 return Some((cte, replacement));
3177 }
3178 }
3179
3180 if let Expression::Alias(alias) = expr {
3182 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
3184 if let Some((cte, replacement)) =
3185 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
3186 {
3187 if col_name.is_some() {
3190 return Some((cte, replacement));
3191 }
3192 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
3193 this: replacement,
3194 alias: alias.alias.clone(),
3195 column_aliases: alias.column_aliases.clone(),
3196 alias_explicit_as: false,
3197 alias_keyword: None,
3198 pre_alias_comments: alias.pre_alias_comments.clone(),
3199 trailing_comments: alias.trailing_comments.clone(),
3200 inferred_type: None,
3201 }));
3202 return Some((cte, new_alias));
3203 }
3204 }
3205
3206 None
3207}
3208
3209fn extract_interval_unit_and_count(
3214 expr: &Expression,
3215) -> (crate::expressions::IntervalUnit, Expression) {
3216 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
3217
3218 if let Expression::Interval(ref iv) = expr {
3219 if let Some(ref unit_spec) = iv.unit {
3221 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
3222 let count = match &iv.this {
3223 Some(e) => e.clone(),
3224 None => Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3225 };
3226 return (unit.clone(), count);
3227 }
3228 }
3229
3230 if let Some(ref val_expr) = iv.this {
3232 match val_expr {
3233 Expression::Literal(lit)
3234 if matches!(lit.as_ref(), Literal::String(_) | Literal::Number(_)) =>
3235 {
3236 let s = match lit.as_ref() {
3237 Literal::String(s) | Literal::Number(s) => s,
3238 _ => unreachable!(),
3239 };
3240 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
3242 if parts.len() == 2 {
3243 let count_str = parts[0].trim();
3244 let unit_str = parts[1].trim().to_uppercase();
3245 let unit = match unit_str.as_str() {
3246 "YEAR" | "YEARS" => IntervalUnit::Year,
3247 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
3248 "MONTH" | "MONTHS" => IntervalUnit::Month,
3249 "WEEK" | "WEEKS" => IntervalUnit::Week,
3250 "DAY" | "DAYS" => IntervalUnit::Day,
3251 "HOUR" | "HOURS" => IntervalUnit::Hour,
3252 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
3253 "SECOND" | "SECONDS" => IntervalUnit::Second,
3254 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
3255 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
3256 _ => IntervalUnit::Day,
3257 };
3258 return (
3259 unit,
3260 Expression::Literal(Box::new(Literal::Number(count_str.to_string()))),
3261 );
3262 }
3263 if s.parse::<f64>().is_ok() {
3265 return (
3266 IntervalUnit::Day,
3267 Expression::Literal(Box::new(Literal::Number(s.clone()))),
3268 );
3269 }
3270 }
3271 _ => {}
3272 }
3273 }
3274
3275 (
3277 IntervalUnit::Day,
3278 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3279 )
3280 } else {
3281 (
3282 IntervalUnit::Day,
3283 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3284 )
3285 }
3286}
3287
3288pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
3301 match expr {
3302 Expression::ILike(ilike) => {
3303 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
3305 name: "LOWER".to_string(),
3306 args: vec![ilike.left],
3307 distinct: false,
3308 trailing_comments: vec![],
3309 use_bracket_syntax: false,
3310 no_parens: false,
3311 quoted: false,
3312 span: None,
3313 inferred_type: None,
3314 }));
3315
3316 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
3317 name: "LOWER".to_string(),
3318 args: vec![ilike.right],
3319 distinct: false,
3320 trailing_comments: vec![],
3321 use_bracket_syntax: false,
3322 no_parens: false,
3323 quoted: false,
3324 span: None,
3325 inferred_type: None,
3326 }));
3327
3328 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
3329 left: lower_left,
3330 right: lower_right,
3331 escape: ilike.escape,
3332 quantifier: ilike.quantifier,
3333 inferred_type: None,
3334 })))
3335 }
3336 other => Ok(other),
3337 }
3338}
3339
3340pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
3348 match expr {
3349 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
3350 other => Ok(other),
3351 }
3352}
3353
3354pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
3359 match expr {
3360 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
3361 other => Ok(other),
3362 }
3363}
3364
3365pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
3372 Ok(expr)
3374}
3375
3376pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
3390 match expr {
3393 Expression::Table(ref table) => {
3394 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
3397 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3399 this: expr.clone(),
3400 expressions: Vec::new(),
3401 with_ordinality: false,
3402 alias: None,
3403 offset_alias: None,
3404 }));
3405
3406 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
3408 this: unnest,
3409 alias: Identifier::new("_u".to_string()),
3410 column_aliases: vec![],
3411 alias_explicit_as: false,
3412 alias_keyword: None,
3413 pre_alias_comments: vec![],
3414 trailing_comments: vec![],
3415 inferred_type: None,
3416 })));
3417 }
3418 Ok(expr)
3419 }
3420 Expression::GenerateSeries(gs) => {
3421 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3423 this: Expression::GenerateSeries(gs),
3424 expressions: Vec::new(),
3425 with_ordinality: false,
3426 alias: None,
3427 offset_alias: None,
3428 }));
3429 Ok(unnest)
3430 }
3431 other => Ok(other),
3432 }
3433}
3434
3435pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
3446 use crate::dialects::transform_recursive;
3447 transform_recursive(expr, &unwrap_unnest_generate_series_single)
3448}
3449
3450fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
3451 use crate::expressions::*;
3452 match expr {
3454 Expression::Select(mut select) => {
3455 if let Some(ref mut from) = select.from {
3457 for table_expr in &mut from.expressions {
3458 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
3459 *table_expr = replacement;
3460 }
3461 }
3462 }
3463 for join in &mut select.joins {
3465 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
3466 join.this = replacement;
3467 }
3468 }
3469 Ok(Expression::Select(select))
3470 }
3471 other => Ok(other),
3472 }
3473}
3474
3475fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
3478 use crate::expressions::*;
3479
3480 let gen_series = match expr {
3482 Expression::Unnest(unnest) => {
3483 if let Expression::GenerateSeries(ref gs) = unnest.this {
3484 Some(gs.as_ref().clone())
3485 } else {
3486 None
3487 }
3488 }
3489 Expression::Alias(alias) => {
3490 if let Expression::Unnest(ref unnest) = alias.this {
3491 if let Expression::GenerateSeries(ref gs) = unnest.this {
3492 Some(gs.as_ref().clone())
3493 } else {
3494 None
3495 }
3496 } else {
3497 None
3498 }
3499 }
3500 _ => None,
3501 };
3502
3503 let gs = gen_series?;
3504
3505 let value_col = Expression::boxed_column(Column {
3507 name: Identifier::new("value".to_string()),
3508 table: None,
3509 join_mark: false,
3510 trailing_comments: vec![],
3511 span: None,
3512 inferred_type: None,
3513 });
3514
3515 let cast_value = Expression::Cast(Box::new(Cast {
3516 this: value_col,
3517 to: DataType::Date,
3518 trailing_comments: vec![],
3519 double_colon_syntax: false,
3520 format: None,
3521 default: None,
3522 inferred_type: None,
3523 }));
3524
3525 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
3526
3527 let gen_series_aliased = Expression::Alias(Box::new(Alias {
3529 this: gen_series_expr,
3530 alias: Identifier::new("_t".to_string()),
3531 column_aliases: vec![Identifier::new("value".to_string())],
3532 alias_explicit_as: false,
3533 alias_keyword: None,
3534 pre_alias_comments: vec![],
3535 trailing_comments: vec![],
3536 inferred_type: None,
3537 }));
3538
3539 let mut inner_select = Select::new();
3540 inner_select.expressions = vec![cast_value];
3541 inner_select.from = Some(From {
3542 expressions: vec![gen_series_aliased],
3543 });
3544
3545 let inner_select_expr = Expression::Select(Box::new(inner_select));
3546
3547 let subquery = Expression::Subquery(Box::new(Subquery {
3548 this: inner_select_expr,
3549 alias: None,
3550 column_aliases: vec![],
3551 alias_explicit_as: false,
3552 alias_keyword: None,
3553 order_by: None,
3554 limit: None,
3555 offset: None,
3556 distribute_by: None,
3557 sort_by: None,
3558 cluster_by: None,
3559 lateral: false,
3560 modifiers_inside: false,
3561 trailing_comments: vec![],
3562 inferred_type: None,
3563 }));
3564
3565 Some(Expression::Alias(Box::new(Alias {
3567 this: subquery,
3568 alias: Identifier::new("_unnested_generate_series".to_string()),
3569 column_aliases: vec![],
3570 alias_explicit_as: false,
3571 alias_keyword: None,
3572 pre_alias_comments: vec![],
3573 trailing_comments: vec![],
3574 inferred_type: None,
3575 })))
3576}
3577
3578pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
3586 match expr {
3587 Expression::Delete(mut delete) => {
3588 if let Some(ref mut where_clause) = delete.where_clause {
3590 where_clause.this = expand_between_recursive(where_clause.this.clone());
3591 }
3592 Ok(Expression::Delete(delete))
3593 }
3594 other => Ok(other),
3595 }
3596}
3597
3598fn expand_between_recursive(expr: Expression) -> Expression {
3600 match expr {
3601 Expression::Between(between) => {
3604 let this = expand_between_recursive(between.this.clone());
3605 let low = expand_between_recursive(between.low);
3606 let high = expand_between_recursive(between.high);
3607
3608 if between.not {
3609 Expression::Or(Box::new(BinaryOp::new(
3611 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
3612 Expression::Gt(Box::new(BinaryOp::new(this, high))),
3613 )))
3614 } else {
3615 Expression::And(Box::new(BinaryOp::new(
3617 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
3618 Expression::Lte(Box::new(BinaryOp::new(this, high))),
3619 )))
3620 }
3621 }
3622
3623 Expression::And(mut op) => {
3625 op.left = expand_between_recursive(op.left);
3626 op.right = expand_between_recursive(op.right);
3627 Expression::And(op)
3628 }
3629 Expression::Or(mut op) => {
3630 op.left = expand_between_recursive(op.left);
3631 op.right = expand_between_recursive(op.right);
3632 Expression::Or(op)
3633 }
3634 Expression::Not(mut op) => {
3635 op.this = expand_between_recursive(op.this);
3636 Expression::Not(op)
3637 }
3638
3639 Expression::Paren(mut paren) => {
3641 paren.this = expand_between_recursive(paren.this);
3642 Expression::Paren(paren)
3643 }
3644
3645 other => other,
3647 }
3648}
3649
3650pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
3659 match expr {
3660 Expression::Select(mut select) => {
3661 if let Some(ref mut with) = select.with {
3662 for cte in &mut with.ctes {
3663 if !cte.columns.is_empty() {
3664 let is_star = matches!(&cte.this, Expression::Select(s) if
3666 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
3667
3668 if is_star {
3669 cte.columns.clear();
3671 continue;
3672 }
3673
3674 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
3676
3677 if let Expression::Select(ref mut inner_select) = cte.this {
3679 let new_exprs: Vec<Expression> = inner_select
3680 .expressions
3681 .drain(..)
3682 .zip(
3683 column_names
3684 .into_iter()
3685 .chain(std::iter::repeat_with(|| Identifier::new(""))),
3686 )
3687 .map(|(expr, col_name)| {
3688 if col_name.name.is_empty() {
3689 return expr;
3690 }
3691 match expr {
3693 Expression::Alias(mut a) => {
3694 a.alias = col_name;
3695 Expression::Alias(a)
3696 }
3697 other => {
3698 Expression::Alias(Box::new(crate::expressions::Alias {
3699 this: other,
3700 alias: col_name,
3701 column_aliases: Vec::new(),
3702 alias_explicit_as: false,
3703 alias_keyword: None,
3704 pre_alias_comments: Vec::new(),
3705 trailing_comments: Vec::new(),
3706 inferred_type: None,
3707 }))
3708 }
3709 }
3710 })
3711 .collect();
3712 inner_select.expressions = new_exprs;
3713 }
3714 }
3715 }
3716 }
3717 Ok(Expression::Select(select))
3718 }
3719 other => Ok(other),
3720 }
3721}
3722
3723pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
3727 match expr {
3728 Expression::Select(mut select) => {
3729 if let Some(ref mut from) = select.from {
3730 for from_item in from.expressions.iter_mut() {
3731 simplify_paren_values_in_from(from_item);
3732 }
3733 }
3734 Ok(Expression::Select(select))
3735 }
3736 other => Ok(other),
3737 }
3738}
3739
3740fn simplify_paren_values_in_from(expr: &mut Expression) {
3741 let replacement = match expr {
3743 Expression::Subquery(ref subquery) => {
3745 if let Expression::Paren(ref paren) = subquery.this {
3746 if matches!(&paren.this, Expression::Values(_)) {
3747 let mut new_sub = subquery.as_ref().clone();
3748 new_sub.this = paren.this.clone();
3749 Some(Expression::Subquery(Box::new(new_sub)))
3750 } else {
3751 None
3752 }
3753 } else {
3754 None
3755 }
3756 }
3757 Expression::Paren(ref outer_paren) => {
3760 if let Expression::Subquery(ref subquery) = outer_paren.this {
3761 if matches!(&subquery.this, Expression::Values(_)) {
3763 Some(outer_paren.this.clone())
3764 }
3765 else if let Expression::Paren(ref paren) = subquery.this {
3767 if matches!(&paren.this, Expression::Values(_)) {
3768 let mut new_sub = subquery.as_ref().clone();
3769 new_sub.this = paren.this.clone();
3770 Some(Expression::Subquery(Box::new(new_sub)))
3771 } else {
3772 None
3773 }
3774 } else {
3775 None
3776 }
3777 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
3778 if matches!(&inner_paren.this, Expression::Values(_)) {
3779 Some(outer_paren.this.clone())
3780 } else {
3781 None
3782 }
3783 } else {
3784 None
3785 }
3786 }
3787 _ => None,
3788 };
3789 if let Some(new_expr) = replacement {
3790 *expr = new_expr;
3791 }
3792}
3793
3794pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
3798 match expr {
3799 Expression::Select(mut select) => {
3800 if let Some(ref mut from) = select.from {
3802 let mut counter = 0usize;
3803 for from_item in from.expressions.iter_mut() {
3804 add_auto_alias_to_from_item(from_item, &mut counter);
3805 }
3806 }
3807 Ok(Expression::Select(select))
3808 }
3809 other => Ok(other),
3810 }
3811}
3812
3813fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
3814 use crate::expressions::Identifier;
3815
3816 match expr {
3817 Expression::Alias(ref mut alias) => {
3818 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
3820 alias.alias = Identifier::new(format!("_t{}", counter));
3821 *counter += 1;
3822 }
3823 }
3824 _ => {}
3825 }
3826}
3827
3828pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
3838 use crate::dialects::transform_recursive;
3839 transform_recursive(expr, &propagate_struct_names_in_expr)
3840}
3841
3842fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
3843 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
3844
3845 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
3847 if elements.len() <= 1 {
3848 return None;
3849 }
3850 if let Some(Expression::Function(ref first_struct)) = elements.first() {
3852 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
3853 let field_names: Vec<Option<String>> = first_struct
3855 .args
3856 .iter()
3857 .map(|arg| {
3858 if let Expression::Alias(a) = arg {
3859 Some(a.alias.name.clone())
3860 } else {
3861 None
3862 }
3863 })
3864 .collect();
3865
3866 if field_names.iter().any(|n| n.is_some()) {
3868 let mut new_elements = Vec::with_capacity(elements.len());
3869 new_elements.push(elements[0].clone());
3870
3871 for elem in &elements[1..] {
3872 if let Expression::Function(ref s) = elem {
3873 if s.name.eq_ignore_ascii_case("STRUCT")
3874 && s.args.len() == field_names.len()
3875 {
3876 let all_unnamed =
3878 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
3879 if all_unnamed {
3880 let new_args: Vec<Expression> = s
3882 .args
3883 .iter()
3884 .zip(field_names.iter())
3885 .map(|(val, name)| {
3886 if let Some(n) = name {
3887 Expression::Alias(Box::new(Alias::new(
3888 val.clone(),
3889 Identifier::new(n.clone()),
3890 )))
3891 } else {
3892 val.clone()
3893 }
3894 })
3895 .collect();
3896 new_elements.push(Expression::Function(Box::new(
3897 Function::new("STRUCT".to_string(), new_args),
3898 )));
3899 continue;
3900 }
3901 }
3902 }
3903 new_elements.push(elem.clone());
3904 }
3905
3906 return Some(new_elements);
3907 }
3908 }
3909 }
3910 None
3911 }
3912
3913 if let Expression::Array(ref arr) = expr {
3915 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3916 return Ok(Expression::Array(Box::new(crate::expressions::Array {
3917 expressions: new_elements,
3918 })));
3919 }
3920 }
3921
3922 if let Expression::ArrayFunc(ref arr) = expr {
3924 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
3925 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
3926 expressions: new_elements,
3927 bracket_notation: arr.bracket_notation,
3928 use_list_keyword: arr.use_list_keyword,
3929 })));
3930 }
3931 }
3932
3933 Ok(expr)
3934}
3935
3936pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
3939 use crate::dialects::transform_recursive;
3940 transform_recursive(expr, &unnest_alias_transform_single_select)
3941}
3942
3943pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
3946 use crate::dialects::transform_recursive;
3947 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
3948}
3949
3950fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
3951 if let Expression::Select(mut select) = expr {
3952 if let Some(ref mut from) = select.from {
3953 if from.expressions.len() > 1 {
3954 let mut new_from_exprs = Vec::new();
3955 let mut new_cross_joins = Vec::new();
3956
3957 for (idx, from_item) in from.expressions.drain(..).enumerate() {
3958 if idx == 0 {
3959 new_from_exprs.push(from_item);
3960 } else {
3961 let is_unnest = match &from_item {
3962 Expression::Unnest(_) => true,
3963 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
3964 _ => false,
3965 };
3966
3967 if is_unnest {
3968 new_cross_joins.push(crate::expressions::Join {
3969 this: from_item,
3970 on: None,
3971 using: Vec::new(),
3972 kind: JoinKind::Cross,
3973 use_inner_keyword: false,
3974 use_outer_keyword: false,
3975 deferred_condition: false,
3976 join_hint: None,
3977 match_condition: None,
3978 pivots: Vec::new(),
3979 comments: Vec::new(),
3980 nesting_group: 0,
3981 directed: false,
3982 });
3983 } else {
3984 new_from_exprs.push(from_item);
3985 }
3986 }
3987 }
3988
3989 from.expressions = new_from_exprs;
3990 new_cross_joins.append(&mut select.joins);
3991 select.joins = new_cross_joins;
3992 }
3993 }
3994
3995 Ok(Expression::Select(select))
3996 } else {
3997 Ok(expr)
3998 }
3999}
4000
4001pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
4005 use crate::dialects::transform_recursive;
4006 transform_recursive(expr, &wrap_unnest_join_aliases_single)
4007}
4008
4009fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
4010 if let Expression::Select(mut select) = expr {
4011 for join in &mut select.joins {
4013 wrap_unnest_alias_in_join_item(&mut join.this);
4014 }
4015 Ok(Expression::Select(select))
4016 } else {
4017 Ok(expr)
4018 }
4019}
4020
4021fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
4023 use crate::expressions::Identifier;
4024 if let Expression::Alias(alias) = expr {
4025 let is_unnest = match &alias.this {
4027 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
4028 _ => false,
4029 };
4030
4031 if is_unnest && alias.column_aliases.is_empty() {
4032 let original_alias_name = alias.alias.name.clone();
4034 alias.alias = Identifier {
4035 name: "_u".to_string(),
4036 quoted: false,
4037 trailing_comments: Vec::new(),
4038 span: None,
4039 };
4040 alias.column_aliases = vec![Identifier {
4041 name: original_alias_name,
4042 quoted: false,
4043 trailing_comments: Vec::new(),
4044 span: None,
4045 }];
4046 }
4047 }
4048}
4049
4050fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
4051 if let Expression::Select(mut select) = expr {
4052 let mut counter = 0usize;
4053
4054 if let Some(ref mut from) = select.from {
4056 for from_item in from.expressions.iter_mut() {
4058 convert_unnest_alias_in_from(from_item, &mut counter);
4059 }
4060
4061 if from.expressions.len() > 1 {
4063 let mut new_from_exprs = Vec::new();
4064 let mut new_cross_joins = Vec::new();
4065
4066 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4067 if idx == 0 {
4068 new_from_exprs.push(from_item);
4070 } else {
4071 let is_unnest = match &from_item {
4073 Expression::Unnest(_) => true,
4074 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4075 _ => false,
4076 };
4077
4078 if is_unnest {
4079 new_cross_joins.push(crate::expressions::Join {
4081 this: from_item,
4082 on: None,
4083 using: Vec::new(),
4084 kind: JoinKind::Cross,
4085 use_inner_keyword: false,
4086 use_outer_keyword: false,
4087 deferred_condition: false,
4088 join_hint: None,
4089 match_condition: None,
4090 pivots: Vec::new(),
4091 comments: Vec::new(),
4092 nesting_group: 0,
4093 directed: false,
4094 });
4095 } else {
4096 new_from_exprs.push(from_item);
4098 }
4099 }
4100 }
4101
4102 from.expressions = new_from_exprs;
4103 new_cross_joins.append(&mut select.joins);
4105 select.joins = new_cross_joins;
4106 }
4107 }
4108
4109 for join in select.joins.iter_mut() {
4111 convert_unnest_alias_in_from(&mut join.this, &mut counter);
4112 }
4113
4114 Ok(Expression::Select(select))
4115 } else {
4116 Ok(expr)
4117 }
4118}
4119
4120fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
4121 use crate::expressions::Identifier;
4122
4123 if let Expression::Alias(ref mut alias) = expr {
4124 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
4126 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
4127
4128 if is_unnest && alias.column_aliases.is_empty() {
4129 let col_alias = alias.alias.clone();
4131 alias.column_aliases = vec![col_alias];
4132 alias.alias = Identifier::new(format!("_t{}", counter));
4133 *counter += 1;
4134 }
4135 }
4136}
4137
4138pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
4145 use crate::expressions::{Alias, Function};
4146
4147 match expr {
4148 Expression::Select(mut select) => {
4149 let mut new_expressions = Vec::new();
4151 let mut changed = false;
4152
4153 for sel_expr in select.expressions.drain(..) {
4154 if let Expression::Alias(ref alias_box) = sel_expr {
4156 if let Expression::Function(ref func) = alias_box.this {
4157 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4158 let arg = func.args[0].clone();
4159 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4161 (
4162 alias_box.column_aliases[0].name.clone(),
4163 alias_box.column_aliases[1].name.clone(),
4164 )
4165 } else if !alias_box.alias.is_empty() {
4166 ("pos".to_string(), alias_box.alias.name.clone())
4168 } else {
4169 ("pos".to_string(), "col".to_string())
4170 };
4171
4172 let gen_subscripts = Expression::Function(Box::new(Function::new(
4174 "GENERATE_SUBSCRIPTS".to_string(),
4175 vec![
4176 arg.clone(),
4177 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4178 ],
4179 )));
4180 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4181 gen_subscripts,
4182 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4183 )));
4184 let pos_alias = Expression::Alias(Box::new(Alias {
4185 this: sub_one,
4186 alias: Identifier::new(pos_name),
4187 column_aliases: Vec::new(),
4188 alias_explicit_as: false,
4189 alias_keyword: None,
4190 pre_alias_comments: Vec::new(),
4191 trailing_comments: Vec::new(),
4192 inferred_type: None,
4193 }));
4194
4195 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4197 this: arg,
4198 expressions: Vec::new(),
4199 with_ordinality: false,
4200 alias: None,
4201 offset_alias: None,
4202 }));
4203 let col_alias = Expression::Alias(Box::new(Alias {
4204 this: unnest,
4205 alias: Identifier::new(col_name),
4206 column_aliases: Vec::new(),
4207 alias_explicit_as: false,
4208 alias_keyword: None,
4209 pre_alias_comments: Vec::new(),
4210 trailing_comments: Vec::new(),
4211 inferred_type: None,
4212 }));
4213
4214 new_expressions.push(pos_alias);
4215 new_expressions.push(col_alias);
4216 changed = true;
4217 continue;
4218 }
4219 }
4220 }
4221
4222 if let Expression::Function(ref func) = sel_expr {
4224 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4225 let arg = func.args[0].clone();
4226 let pos_name = "pos";
4227 let col_name = "col";
4228
4229 let gen_subscripts = Expression::Function(Box::new(Function::new(
4231 "GENERATE_SUBSCRIPTS".to_string(),
4232 vec![
4233 arg.clone(),
4234 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4235 ],
4236 )));
4237 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4238 gen_subscripts,
4239 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4240 )));
4241 let pos_alias = Expression::Alias(Box::new(Alias {
4242 this: sub_one,
4243 alias: Identifier::new(pos_name),
4244 column_aliases: Vec::new(),
4245 alias_explicit_as: false,
4246 alias_keyword: None,
4247 pre_alias_comments: Vec::new(),
4248 trailing_comments: Vec::new(),
4249 inferred_type: None,
4250 }));
4251
4252 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4254 this: arg,
4255 expressions: Vec::new(),
4256 with_ordinality: false,
4257 alias: None,
4258 offset_alias: None,
4259 }));
4260 let col_alias = Expression::Alias(Box::new(Alias {
4261 this: unnest,
4262 alias: Identifier::new(col_name),
4263 column_aliases: Vec::new(),
4264 alias_explicit_as: false,
4265 alias_keyword: None,
4266 pre_alias_comments: Vec::new(),
4267 trailing_comments: Vec::new(),
4268 inferred_type: None,
4269 }));
4270
4271 new_expressions.push(pos_alias);
4272 new_expressions.push(col_alias);
4273 changed = true;
4274 continue;
4275 }
4276 }
4277
4278 new_expressions.push(sel_expr);
4280 }
4281
4282 if changed {
4283 select.expressions = new_expressions;
4284 } else {
4285 select.expressions = new_expressions;
4286 }
4287
4288 if let Some(ref mut from) = select.from {
4291 expand_posexplode_in_from_duckdb(from)?;
4292 }
4293
4294 Ok(Expression::Select(select))
4295 }
4296 other => Ok(other),
4297 }
4298}
4299
4300fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
4302 use crate::expressions::{Alias, Function};
4303
4304 let mut new_expressions = Vec::new();
4305 let mut _changed = false;
4306
4307 for table_expr in from.expressions.drain(..) {
4308 if let Expression::Alias(ref alias_box) = table_expr {
4310 if let Expression::Function(ref func) = alias_box.this {
4311 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4312 let arg = func.args[0].clone();
4313 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4314 (
4315 alias_box.column_aliases[0].name.clone(),
4316 alias_box.column_aliases[1].name.clone(),
4317 )
4318 } else {
4319 ("pos".to_string(), "col".to_string())
4320 };
4321
4322 let gen_subscripts = Expression::Function(Box::new(Function::new(
4324 "GENERATE_SUBSCRIPTS".to_string(),
4325 vec![
4326 arg.clone(),
4327 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4328 ],
4329 )));
4330 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4331 gen_subscripts,
4332 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4333 )));
4334 let pos_alias = Expression::Alias(Box::new(Alias {
4335 this: sub_one,
4336 alias: Identifier::new(&pos_name),
4337 column_aliases: Vec::new(),
4338 alias_explicit_as: false,
4339 alias_keyword: None,
4340 pre_alias_comments: Vec::new(),
4341 trailing_comments: Vec::new(),
4342 inferred_type: None,
4343 }));
4344 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4345 this: arg,
4346 expressions: Vec::new(),
4347 with_ordinality: false,
4348 alias: None,
4349 offset_alias: None,
4350 }));
4351 let col_alias = Expression::Alias(Box::new(Alias {
4352 this: unnest,
4353 alias: Identifier::new(&col_name),
4354 column_aliases: Vec::new(),
4355 alias_explicit_as: false,
4356 alias_keyword: None,
4357 pre_alias_comments: Vec::new(),
4358 trailing_comments: Vec::new(),
4359 inferred_type: None,
4360 }));
4361
4362 let mut inner_select = Select::new();
4363 inner_select.expressions = vec![pos_alias, col_alias];
4364
4365 let subquery = Expression::Subquery(Box::new(Subquery {
4366 this: Expression::Select(Box::new(inner_select)),
4367 alias: None,
4368 column_aliases: Vec::new(),
4369 alias_explicit_as: false,
4370 alias_keyword: None,
4371 order_by: None,
4372 limit: None,
4373 offset: None,
4374 distribute_by: None,
4375 sort_by: None,
4376 cluster_by: None,
4377 lateral: false,
4378 modifiers_inside: false,
4379 trailing_comments: Vec::new(),
4380 inferred_type: None,
4381 }));
4382 new_expressions.push(subquery);
4383 _changed = true;
4384 continue;
4385 }
4386 }
4387 }
4388
4389 if let Expression::Function(ref func) = table_expr {
4391 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4392 let arg = func.args[0].clone();
4393
4394 let gen_subscripts = Expression::Function(Box::new(Function::new(
4396 "GENERATE_SUBSCRIPTS".to_string(),
4397 vec![
4398 arg.clone(),
4399 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4400 ],
4401 )));
4402 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4403 gen_subscripts,
4404 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4405 )));
4406 let pos_alias = Expression::Alias(Box::new(Alias {
4407 this: sub_one,
4408 alias: Identifier::new("pos"),
4409 column_aliases: Vec::new(),
4410 alias_explicit_as: false,
4411 alias_keyword: None,
4412 pre_alias_comments: Vec::new(),
4413 trailing_comments: Vec::new(),
4414 inferred_type: None,
4415 }));
4416 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4417 this: arg,
4418 expressions: Vec::new(),
4419 with_ordinality: false,
4420 alias: None,
4421 offset_alias: None,
4422 }));
4423 let col_alias = Expression::Alias(Box::new(Alias {
4424 this: unnest,
4425 alias: Identifier::new("col"),
4426 column_aliases: Vec::new(),
4427 alias_explicit_as: false,
4428 alias_keyword: None,
4429 pre_alias_comments: Vec::new(),
4430 trailing_comments: Vec::new(),
4431 inferred_type: None,
4432 }));
4433
4434 let mut inner_select = Select::new();
4435 inner_select.expressions = vec![pos_alias, col_alias];
4436
4437 let subquery = Expression::Subquery(Box::new(Subquery {
4438 this: Expression::Select(Box::new(inner_select)),
4439 alias: None,
4440 column_aliases: Vec::new(),
4441 alias_explicit_as: false,
4442 alias_keyword: None,
4443 order_by: None,
4444 limit: None,
4445 offset: None,
4446 distribute_by: None,
4447 sort_by: None,
4448 cluster_by: None,
4449 lateral: false,
4450 modifiers_inside: false,
4451 trailing_comments: Vec::new(),
4452 inferred_type: None,
4453 }));
4454 new_expressions.push(subquery);
4455 _changed = true;
4456 continue;
4457 }
4458 }
4459
4460 new_expressions.push(table_expr);
4461 }
4462
4463 from.expressions = new_expressions;
4464 Ok(())
4465}
4466
4467pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
4482 match expr {
4483 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
4484 other => Ok(other),
4485 }
4486}
4487
4488pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
4498 match expr {
4499 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
4500 other => Ok(other),
4501 }
4502}
4503
4504fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
4505 let mut flattened_inputs: Vec<Expression> = Vec::new();
4506 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
4507
4508 for sel_expr in select.expressions.into_iter() {
4509 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
4510
4511 let rewritten = transform_recursive(sel_expr, &|e| {
4512 if let Expression::Lateral(lat) = e {
4513 if let Some(input_expr) = extract_flatten_input(&lat) {
4514 if found_input.borrow().is_none() {
4515 *found_input.borrow_mut() = Some(input_expr);
4516 }
4517 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
4518 }
4519 return Ok(Expression::Lateral(lat));
4520 }
4521 Ok(e)
4522 })?;
4523
4524 if let Some(input) = found_input.into_inner() {
4525 flattened_inputs.push(input);
4526 }
4527 new_selects.push(rewritten);
4528 }
4529
4530 if flattened_inputs.is_empty() {
4531 select.expressions = new_selects;
4532 return Ok(Expression::Select(Box::new(select)));
4533 }
4534
4535 select.expressions = new_selects;
4536
4537 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
4538 let is_first = idx == 0;
4540 let series_alias = if is_first {
4541 "pos".to_string()
4542 } else {
4543 format!("pos_{}", idx + 1)
4544 };
4545 let series_source_alias = if is_first {
4546 "_u".to_string()
4547 } else {
4548 format!("_u_{}", idx * 2 + 1)
4549 };
4550 let unnest_source_alias = if is_first {
4551 "_u_2".to_string()
4552 } else {
4553 format!("_u_{}", idx * 2 + 2)
4554 };
4555 let pos2_alias = if is_first {
4556 "pos_2".to_string()
4557 } else {
4558 format!("{}_2", series_alias)
4559 };
4560 let entity_alias = if is_first {
4561 "entity".to_string()
4562 } else {
4563 format!("entity_{}", idx + 1)
4564 };
4565
4566 let array_size_call = Expression::Function(Box::new(Function::new(
4567 "ARRAY_SIZE".to_string(),
4568 vec![Expression::NamedArgument(Box::new(NamedArgument {
4569 name: Identifier::new("INPUT"),
4570 value: input_expr.clone(),
4571 separator: NamedArgSeparator::DArrow,
4572 }))],
4573 )));
4574
4575 let greatest = Expression::Function(Box::new(Function::new(
4576 "GREATEST".to_string(),
4577 vec![array_size_call.clone()],
4578 )));
4579
4580 let series_end = Expression::Add(Box::new(BinaryOp::new(
4581 Expression::Paren(Box::new(crate::expressions::Paren {
4582 this: Expression::Sub(Box::new(BinaryOp::new(
4583 greatest,
4584 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4585 ))),
4586 trailing_comments: Vec::new(),
4587 })),
4588 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4589 )));
4590
4591 let series_range = Expression::Function(Box::new(Function::new(
4592 "ARRAY_GENERATE_RANGE".to_string(),
4593 vec![
4594 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
4595 series_end,
4596 ],
4597 )));
4598
4599 let series_flatten = Expression::Function(Box::new(Function::new(
4600 "FLATTEN".to_string(),
4601 vec![Expression::NamedArgument(Box::new(NamedArgument {
4602 name: Identifier::new("INPUT"),
4603 value: series_range,
4604 separator: NamedArgSeparator::DArrow,
4605 }))],
4606 )));
4607
4608 let series_table = Expression::Function(Box::new(Function::new(
4609 "TABLE".to_string(),
4610 vec![series_flatten],
4611 )));
4612
4613 let series_alias_expr = Expression::Alias(Box::new(Alias {
4614 this: series_table,
4615 alias: Identifier::new(series_source_alias.clone()),
4616 column_aliases: vec![
4617 Identifier::new("seq"),
4618 Identifier::new("key"),
4619 Identifier::new("path"),
4620 Identifier::new("index"),
4621 Identifier::new(series_alias.clone()),
4622 Identifier::new("this"),
4623 ],
4624 alias_explicit_as: false,
4625 alias_keyword: None,
4626 pre_alias_comments: Vec::new(),
4627 trailing_comments: Vec::new(),
4628 inferred_type: None,
4629 }));
4630
4631 select.joins.push(Join {
4632 this: series_alias_expr,
4633 on: None,
4634 using: Vec::new(),
4635 kind: JoinKind::Cross,
4636 use_inner_keyword: false,
4637 use_outer_keyword: false,
4638 deferred_condition: false,
4639 join_hint: None,
4640 match_condition: None,
4641 pivots: Vec::new(),
4642 comments: Vec::new(),
4643 nesting_group: 0,
4644 directed: false,
4645 });
4646
4647 let entity_flatten = Expression::Function(Box::new(Function::new(
4648 "FLATTEN".to_string(),
4649 vec![Expression::NamedArgument(Box::new(NamedArgument {
4650 name: Identifier::new("INPUT"),
4651 value: input_expr.clone(),
4652 separator: NamedArgSeparator::DArrow,
4653 }))],
4654 )));
4655
4656 let entity_table = Expression::Function(Box::new(Function::new(
4657 "TABLE".to_string(),
4658 vec![entity_flatten],
4659 )));
4660
4661 let entity_alias_expr = Expression::Alias(Box::new(Alias {
4662 this: entity_table,
4663 alias: Identifier::new(unnest_source_alias.clone()),
4664 column_aliases: vec![
4665 Identifier::new("seq"),
4666 Identifier::new("key"),
4667 Identifier::new("path"),
4668 Identifier::new(pos2_alias.clone()),
4669 Identifier::new(entity_alias.clone()),
4670 Identifier::new("this"),
4671 ],
4672 alias_explicit_as: false,
4673 alias_keyword: None,
4674 pre_alias_comments: Vec::new(),
4675 trailing_comments: Vec::new(),
4676 inferred_type: None,
4677 }));
4678
4679 select.joins.push(Join {
4680 this: entity_alias_expr,
4681 on: None,
4682 using: Vec::new(),
4683 kind: JoinKind::Cross,
4684 use_inner_keyword: false,
4685 use_outer_keyword: false,
4686 deferred_condition: false,
4687 join_hint: None,
4688 match_condition: None,
4689 pivots: Vec::new(),
4690 comments: Vec::new(),
4691 nesting_group: 0,
4692 directed: false,
4693 });
4694
4695 let pos_col =
4696 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
4697 let pos2_col =
4698 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
4699
4700 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
4701 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
4702 this: Expression::Sub(Box::new(BinaryOp::new(
4703 array_size_call,
4704 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4705 ))),
4706 trailing_comments: Vec::new(),
4707 }));
4708 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
4709 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
4710 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
4711 let or_cond = Expression::Or(Box::new(BinaryOp::new(
4712 eq,
4713 Expression::Paren(Box::new(crate::expressions::Paren {
4714 this: and_cond,
4715 trailing_comments: Vec::new(),
4716 })),
4717 )));
4718
4719 select.where_clause = Some(match select.where_clause.take() {
4720 Some(existing) => Where {
4721 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
4722 },
4723 None => Where { this: or_cond },
4724 });
4725 }
4726
4727 Ok(Expression::Select(Box::new(select)))
4728}
4729
4730fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
4731 let Expression::Function(f) = lat.this.as_ref() else {
4732 return None;
4733 };
4734 if !f.name.eq_ignore_ascii_case("FLATTEN") {
4735 return None;
4736 }
4737
4738 for arg in &f.args {
4739 if let Expression::NamedArgument(na) = arg {
4740 if na.name.name.eq_ignore_ascii_case("INPUT") {
4741 return Some(na.value.clone());
4742 }
4743 }
4744 }
4745 f.args.first().cloned()
4746}
4747
4748fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
4749 let cond = Expression::Eq(Box::new(BinaryOp::new(
4750 Expression::qualified_column("_u", "pos"),
4751 Expression::qualified_column("_u_2", "pos_2"),
4752 )));
4753 let true_expr = Expression::qualified_column("_u_2", "entity");
4754 let iff_expr = Expression::Function(Box::new(Function::new(
4755 "IFF".to_string(),
4756 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
4757 )));
4758
4759 lat.this = Box::new(iff_expr);
4760 if lat.column_aliases.is_empty() {
4761 lat.column_aliases = vec![
4762 "SEQ".to_string(),
4763 "KEY".to_string(),
4764 "PATH".to_string(),
4765 "INDEX".to_string(),
4766 "VALUE".to_string(),
4767 "THIS".to_string(),
4768 ];
4769 }
4770 lat
4771}
4772
4773struct ExplodeInfo {
4775 arg_sql: String,
4777 explode_alias: String,
4779 pos_alias: String,
4781 unnest_source_alias: String,
4783}
4784
4785fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
4786 let is_presto = matches!(
4787 target,
4788 DialectType::Presto | DialectType::Trino | DialectType::Athena
4789 );
4790 let is_bigquery = matches!(target, DialectType::BigQuery);
4791
4792 if !is_presto && !is_bigquery {
4793 return Ok(Expression::Select(Box::new(select)));
4794 }
4795
4796 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
4798 if !has_explode {
4799 return Ok(Expression::Select(Box::new(select)));
4800 }
4801
4802 let mut taken_select_names = std::collections::HashSet::new();
4804 let mut taken_source_names = std::collections::HashSet::new();
4805
4806 for sel in &select.expressions {
4808 if let Some(name) = get_output_name(sel) {
4809 taken_select_names.insert(name);
4810 }
4811 }
4812
4813 for sel in &select.expressions {
4815 let explode_expr = find_explode_in_expr(sel);
4816 if let Some(arg) = explode_expr {
4817 if let Some(name) = get_output_name(&arg) {
4818 taken_select_names.insert(name);
4819 }
4820 }
4821 }
4822
4823 if let Some(ref from) = select.from {
4825 for from_expr in &from.expressions {
4826 collect_source_names(from_expr, &mut taken_source_names);
4827 }
4828 }
4829 for join in &select.joins {
4831 collect_source_names(&join.this, &mut taken_source_names);
4832 }
4833
4834 let series_alias = new_name(&mut taken_select_names, "pos");
4836
4837 let series_source_alias = new_name(&mut taken_source_names, "_u");
4839
4840 let target_dialect = Dialect::get(target);
4842
4843 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
4845 let mut new_projections: Vec<String> = Vec::new();
4846
4847 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
4848 let explode_data = extract_explode_data(sel_expr);
4849
4850 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
4851 let arg_sql = target_dialect
4853 .generate(&arg_expr)
4854 .unwrap_or_else(|_| "NULL".to_string());
4855
4856 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
4857
4858 let explode_alias = if let Some(ref ea) = explicit_alias {
4859 taken_select_names.remove(ea.as_str());
4862 let name = new_name(&mut taken_select_names, ea);
4864 name
4865 } else {
4866 new_name(&mut taken_select_names, "col")
4867 };
4868
4869 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
4870 taken_select_names.remove(pa.as_str());
4872 let name = new_name(&mut taken_select_names, pa);
4873 name
4874 } else {
4875 new_name(&mut taken_select_names, "pos")
4876 };
4877
4878 if is_presto {
4880 let if_col = format!(
4882 "IF({}.{} = {}.{}, {}.{}) AS {}",
4883 series_source_alias,
4884 series_alias,
4885 unnest_source_alias,
4886 pos_alias,
4887 unnest_source_alias,
4888 explode_alias,
4889 explode_alias
4890 );
4891 new_projections.push(if_col);
4892
4893 if is_posexplode {
4895 let if_pos = format!(
4896 "IF({}.{} = {}.{}, {}.{}) AS {}",
4897 series_source_alias,
4898 series_alias,
4899 unnest_source_alias,
4900 pos_alias,
4901 unnest_source_alias,
4902 pos_alias,
4903 pos_alias
4904 );
4905 new_projections.push(if_pos);
4906 }
4907 } else {
4908 let if_col = format!(
4910 "IF({} = {}, {}, NULL) AS {}",
4911 series_alias, pos_alias, explode_alias, explode_alias
4912 );
4913 new_projections.push(if_col);
4914
4915 if is_posexplode {
4917 let if_pos = format!(
4918 "IF({} = {}, {}, NULL) AS {}",
4919 series_alias, pos_alias, pos_alias, pos_alias
4920 );
4921 new_projections.push(if_pos);
4922 }
4923 }
4924
4925 explode_infos.push(ExplodeInfo {
4926 arg_sql,
4927 explode_alias,
4928 pos_alias,
4929 unnest_source_alias,
4930 });
4931 } else {
4932 let sel_sql = target_dialect
4934 .generate(sel_expr)
4935 .unwrap_or_else(|_| "*".to_string());
4936 new_projections.push(sel_sql);
4937 }
4938 }
4939
4940 if explode_infos.is_empty() {
4941 return Ok(Expression::Select(Box::new(select)));
4942 }
4943
4944 let mut from_parts: Vec<String> = Vec::new();
4946
4947 if let Some(ref from) = select.from {
4949 for from_expr in &from.expressions {
4950 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
4951 from_parts.push(from_sql);
4952 }
4953 }
4954
4955 let size_exprs: Vec<String> = explode_infos
4957 .iter()
4958 .map(|info| {
4959 if is_presto {
4960 format!("CARDINALITY({})", info.arg_sql)
4961 } else {
4962 format!("ARRAY_LENGTH({})", info.arg_sql)
4963 }
4964 })
4965 .collect();
4966
4967 let greatest_arg = if size_exprs.len() == 1 {
4968 size_exprs[0].clone()
4969 } else {
4970 format!("GREATEST({})", size_exprs.join(", "))
4971 };
4972
4973 let series_sql = if is_presto {
4976 if size_exprs.len() == 1 {
4978 format!(
4979 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
4980 greatest_arg, series_source_alias, series_alias
4981 )
4982 } else {
4983 format!(
4985 "UNNEST(SEQUENCE(1, {})) AS {}({})",
4986 greatest_arg, series_source_alias, series_alias
4987 )
4988 }
4989 } else {
4990 if size_exprs.len() == 1 {
4992 format!(
4993 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
4994 greatest_arg, series_alias
4995 )
4996 } else {
4997 format!(
4999 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
5000 greatest_arg, series_alias
5001 )
5002 }
5003 };
5004
5005 let mut cross_joins: Vec<String> = Vec::new();
5009
5010 for info in &explode_infos {
5011 cross_joins.push(format!(
5013 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
5014 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
5015 ));
5016 }
5017
5018 let mut where_conditions: Vec<String> = Vec::new();
5020
5021 for info in &explode_infos {
5022 let size_expr = if is_presto {
5023 format!("CARDINALITY({})", info.arg_sql)
5024 } else {
5025 format!("ARRAY_LENGTH({})", info.arg_sql)
5026 };
5027
5028 let cond = if is_presto {
5029 format!(
5030 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
5031 series_src = series_source_alias,
5032 series_al = series_alias,
5033 unnest_src = info.unnest_source_alias,
5034 pos_al = info.pos_alias,
5035 size = size_expr
5036 )
5037 } else {
5038 format!(
5039 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
5040 series_al = series_alias,
5041 pos_al = info.pos_alias,
5042 size = size_expr
5043 )
5044 };
5045
5046 where_conditions.push(cond);
5047 }
5048
5049 let where_sql = if where_conditions.len() == 1 {
5051 where_conditions[0].clone()
5052 } else {
5053 where_conditions
5054 .iter()
5055 .map(|c| format!("({})", c))
5056 .collect::<Vec<_>>()
5057 .join(" AND ")
5058 };
5059
5060 let select_part = new_projections.join(", ");
5062
5063 let from_and_joins = if from_parts.is_empty() {
5065 format!("FROM {} {}", series_sql, cross_joins.join(" "))
5067 } else {
5068 format!(
5069 "FROM {} {} {}",
5070 from_parts.join(", "),
5071 format!("CROSS JOIN {}", series_sql),
5072 cross_joins.join(" ")
5073 )
5074 };
5075
5076 let full_sql = format!(
5077 "SELECT {} {} WHERE {}",
5078 select_part, from_and_joins, where_sql
5079 );
5080
5081 let generic_dialect = Dialect::get(DialectType::Generic);
5084 let parsed = generic_dialect.parse(&full_sql);
5085 match parsed {
5086 Ok(mut stmts) if !stmts.is_empty() => {
5087 let mut result = stmts.remove(0);
5088
5089 if is_bigquery {
5093 convert_unnest_presto_to_bigquery(&mut result);
5094 }
5095
5096 Ok(result)
5097 }
5098 _ => {
5099 Ok(Expression::Select(Box::new(select)))
5101 }
5102 }
5103}
5104
5105fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
5109 match expr {
5110 Expression::Select(ref mut select) => {
5111 if let Some(ref mut from) = select.from {
5113 for from_item in from.expressions.iter_mut() {
5114 convert_unnest_presto_to_bigquery(from_item);
5115 }
5116 }
5117 for join in select.joins.iter_mut() {
5119 convert_unnest_presto_to_bigquery(&mut join.this);
5120 }
5121 }
5122 Expression::Alias(ref alias) => {
5123 if let Expression::Unnest(ref unnest) = alias.this {
5125 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
5126 let col_alias = alias.column_aliases[0].clone();
5127 let pos_alias = alias.column_aliases[1].clone();
5128 let mut new_unnest = unnest.as_ref().clone();
5129 new_unnest.alias = Some(col_alias);
5130 new_unnest.offset_alias = Some(pos_alias);
5131 *expr = Expression::Unnest(Box::new(new_unnest));
5133 }
5134 }
5135 }
5136 _ => {}
5137 }
5138}
5139
5140fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
5143 if !names.contains(base) {
5144 names.insert(base.to_string());
5145 return base.to_string();
5146 }
5147 let mut i = 2;
5148 loop {
5149 let candidate = format!("{}_{}", base, i);
5150 if !names.contains(&candidate) {
5151 names.insert(candidate.clone());
5152 return candidate;
5153 }
5154 i += 1;
5155 }
5156}
5157
5158fn expr_contains_explode(expr: &Expression) -> bool {
5160 match expr {
5161 Expression::Explode(_) => true,
5162 Expression::ExplodeOuter(_) => true,
5163 Expression::Function(f) => {
5164 let name = f.name.to_uppercase();
5165 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
5166 }
5167 Expression::Alias(a) => expr_contains_explode(&a.this),
5168 _ => false,
5169 }
5170}
5171
5172fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
5174 match expr {
5175 Expression::Explode(uf) => Some(uf.this.clone()),
5176 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
5177 Expression::Function(f) => {
5178 let name = f.name.to_uppercase();
5179 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5180 Some(f.args[0].clone())
5181 } else {
5182 None
5183 }
5184 }
5185 Expression::Alias(a) => find_explode_in_expr(&a.this),
5186 _ => None,
5187 }
5188}
5189
5190fn extract_explode_data(
5193 expr: &Expression,
5194) -> Option<(bool, Expression, Option<String>, Option<String>)> {
5195 match expr {
5196 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
5198 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
5199 Expression::Function(f) => {
5201 let name = f.name.to_uppercase();
5202 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5203 Some((true, f.args[0].clone(), None, None))
5204 } else {
5205 None
5206 }
5207 }
5208 Expression::Alias(a) => {
5210 match &a.this {
5211 Expression::Explode(uf) => {
5212 let alias = if !a.alias.is_empty() {
5213 Some(a.alias.name.clone())
5214 } else {
5215 None
5216 };
5217 Some((false, uf.this.clone(), alias, None))
5218 }
5219 Expression::ExplodeOuter(uf) => {
5220 let alias = if !a.alias.is_empty() {
5221 Some(a.alias.name.clone())
5222 } else {
5223 None
5224 };
5225 Some((false, uf.this.clone(), alias, None))
5226 }
5227 Expression::Function(f) => {
5228 let name = f.name.to_uppercase();
5229 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5230 if a.column_aliases.len() == 2 {
5232 let pos_alias = a.column_aliases[0].name.clone();
5233 let col_alias = a.column_aliases[1].name.clone();
5234 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
5235 } else if !a.alias.is_empty() {
5236 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
5238 } else {
5239 Some((true, f.args[0].clone(), None, None))
5240 }
5241 } else {
5242 None
5243 }
5244 }
5245 _ => None,
5246 }
5247 }
5248 _ => None,
5249 }
5250}
5251
5252fn get_output_name(expr: &Expression) -> Option<String> {
5254 match expr {
5255 Expression::Alias(a) => {
5256 if !a.alias.is_empty() {
5257 Some(a.alias.name.clone())
5258 } else {
5259 None
5260 }
5261 }
5262 Expression::Column(c) => Some(c.name.name.clone()),
5263 Expression::Identifier(id) => Some(id.name.clone()),
5264 _ => None,
5265 }
5266}
5267
5268fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
5270 match expr {
5271 Expression::Alias(a) => {
5272 if !a.alias.is_empty() {
5273 names.insert(a.alias.name.clone());
5274 }
5275 }
5276 Expression::Subquery(s) => {
5277 if let Some(ref alias) = s.alias {
5278 names.insert(alias.name.clone());
5279 }
5280 }
5281 Expression::Table(t) => {
5282 if let Some(ref alias) = t.alias {
5283 names.insert(alias.name.clone());
5284 } else {
5285 names.insert(t.name.name.clone());
5286 }
5287 }
5288 Expression::Column(c) => {
5289 names.insert(c.name.name.clone());
5290 }
5291 Expression::Identifier(id) => {
5292 names.insert(id.name.clone());
5293 }
5294 _ => {}
5295 }
5296}
5297
5298pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
5301 use crate::dialects::transform_recursive;
5302 transform_recursive(expr, &strip_unnest_column_refs_single)
5303}
5304
5305fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
5306 if let Expression::Select(mut select) = expr {
5307 for join in select.joins.iter_mut() {
5309 strip_unnest_from_expr(&mut join.this);
5310 }
5311 if let Some(ref mut from) = select.from {
5313 for from_item in from.expressions.iter_mut() {
5314 strip_unnest_from_expr(from_item);
5315 }
5316 }
5317 Ok(Expression::Select(select))
5318 } else {
5319 Ok(expr)
5320 }
5321}
5322
5323fn strip_unnest_from_expr(expr: &mut Expression) {
5326 if let Expression::Alias(ref mut alias) = expr {
5327 if let Expression::Unnest(ref unnest) = alias.this {
5328 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
5329 if is_column_ref {
5330 let inner = unnest.this.clone();
5332 alias.this = inner;
5333 }
5334 }
5335 }
5336}
5337
5338pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
5341 use crate::dialects::transform_recursive;
5342 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
5343}
5344
5345fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
5346 if let Expression::Select(mut select) = expr {
5347 if let Some(ref mut from) = select.from {
5349 for from_item in from.expressions.iter_mut() {
5350 try_wrap_unnest_in_subquery(from_item);
5351 }
5352 }
5353
5354 for join in select.joins.iter_mut() {
5356 try_wrap_unnest_in_subquery(&mut join.this);
5357 }
5358
5359 Ok(Expression::Select(select))
5360 } else {
5361 Ok(expr)
5362 }
5363}
5364
5365fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
5367 match expr {
5368 Expression::Array(arr) => arr
5370 .expressions
5371 .iter()
5372 .any(|e| matches!(e, Expression::Struct(_))),
5373 Expression::ArrayFunc(arr) => arr
5374 .expressions
5375 .iter()
5376 .any(|e| matches!(e, Expression::Struct(_))),
5377 Expression::Cast(c) => {
5379 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
5380 }
5381 _ => false,
5382 }
5383}
5384
5385fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
5388 if let Expression::Alias(ref alias) = expr {
5390 if let Expression::Unnest(ref unnest) = alias.this {
5391 if is_struct_array_unnest_arg(&unnest.this) {
5392 let unnest_clone = (**unnest).clone();
5393 let alias_name = alias.alias.clone();
5394 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
5395 *expr = new_expr;
5396 return;
5397 }
5398 }
5399 }
5400
5401 if let Expression::Unnest(ref unnest) = expr {
5403 if is_struct_array_unnest_arg(&unnest.this) {
5404 let unnest_clone = (**unnest).clone();
5405 let new_expr = make_unnest_subquery(unnest_clone, None);
5406 *expr = new_expr;
5407 }
5408 }
5409}
5410
5411fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
5413 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
5415 name: Identifier::new("max_depth".to_string()),
5416 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
5417 separator: NamedArgSeparator::DArrow,
5418 }));
5419
5420 let mut unnest_args = vec![unnest.this];
5421 unnest_args.extend(unnest.expressions);
5422 unnest_args.push(max_depth_arg);
5423
5424 let unnest_func =
5425 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
5426
5427 let mut inner_select = Select::new();
5429 inner_select.expressions = vec![unnest_func];
5430 let inner_select = Expression::Select(Box::new(inner_select));
5431
5432 let subquery = Subquery {
5434 this: inner_select,
5435 alias,
5436 column_aliases: Vec::new(),
5437 alias_explicit_as: false,
5438 alias_keyword: None,
5439 order_by: None,
5440 limit: None,
5441 offset: None,
5442 distribute_by: None,
5443 sort_by: None,
5444 cluster_by: None,
5445 lateral: false,
5446 modifiers_inside: false,
5447 trailing_comments: Vec::new(),
5448 inferred_type: None,
5449 };
5450
5451 Expression::Subquery(Box::new(subquery))
5452}
5453
5454pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
5466 use crate::expressions::{Limit as LimitClause, Offset as OffsetClause, OrderBy, Star};
5467
5468 match expr {
5469 Expression::Union(mut u) => {
5470 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
5473 if let Expression::Select(ref mut right_select) = u.right {
5475 if right_select.order_by.is_some()
5476 || right_select.limit.is_some()
5477 || right_select.offset.is_some()
5478 {
5479 u.order_by = right_select.order_by.take();
5481 u.limit = right_select.limit.take().map(|l| Box::new(l.this));
5482 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
5483 }
5484 }
5485 }
5486
5487 let has_order_or_limit =
5488 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
5489 if has_order_or_limit {
5490 let order_by: Option<OrderBy> = u.order_by.take();
5492 let union_limit: Option<Box<Expression>> = u.limit.take();
5493 let union_offset: Option<Box<Expression>> = u.offset.take();
5494
5495 let select_limit: Option<LimitClause> = union_limit.map(|l| LimitClause {
5497 this: *l,
5498 percent: false,
5499 comments: Vec::new(),
5500 });
5501
5502 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
5504 this: *o,
5505 rows: None,
5506 });
5507
5508 let subquery = Subquery {
5510 this: Expression::Union(u),
5511 alias: Some(Identifier::new("_l_0")),
5512 column_aliases: Vec::new(),
5513 alias_explicit_as: true,
5514 alias_keyword: None,
5515 lateral: false,
5516 modifiers_inside: false,
5517 order_by: None,
5518 limit: None,
5519 offset: None,
5520 distribute_by: None,
5521 sort_by: None,
5522 cluster_by: None,
5523 trailing_comments: Vec::new(),
5524 inferred_type: None,
5525 };
5526
5527 let mut select = Select::default();
5529 select.expressions = vec![Expression::Star(Star {
5530 table: None,
5531 except: None,
5532 replace: None,
5533 rename: None,
5534 trailing_comments: Vec::new(),
5535 span: None,
5536 })];
5537 select.from = Some(From {
5538 expressions: vec![Expression::Subquery(Box::new(subquery))],
5539 });
5540 select.order_by = order_by;
5541 select.limit = select_limit;
5542 select.offset = select_offset;
5543
5544 Ok(Expression::Select(Box::new(select)))
5545 } else {
5546 Ok(Expression::Union(u))
5547 }
5548 }
5549 _ => Ok(expr),
5550 }
5551}
5552
5553pub fn expand_like_any(expr: Expression) -> Result<Expression> {
5561 use crate::expressions::{BinaryOp, LikeOp, Paren};
5562
5563 const LIKE_ALL_MARKER: &str = "__LIKE_ALL_EXPANSION__";
5566
5567 fn unwrap_parens(e: &Expression) -> &Expression {
5568 match e {
5569 Expression::Paren(p) => unwrap_parens(&p.this),
5570 _ => e,
5571 }
5572 }
5573
5574 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
5575 let inner = unwrap_parens(e);
5576 match inner {
5577 Expression::Tuple(t) => Some(t.expressions.clone()),
5578 _ if !matches!(e, Expression::Tuple(_)) => Some(vec![inner.clone()]),
5580 _ => None,
5581 }
5582 }
5583
5584 fn expand_like_quantifier(
5586 op: &LikeOp,
5587 values: Vec<Expression>,
5588 is_ilike: bool,
5589 combiner: fn(Expression, Expression) -> Expression,
5590 wrap_marker: bool,
5591 ) -> Expression {
5592 let num_values = values.len();
5593 let mut result: Option<Expression> = None;
5594 for val in values {
5595 let like = if is_ilike {
5596 Expression::ILike(Box::new(LikeOp {
5597 left: op.left.clone(),
5598 right: val,
5599 escape: op.escape.clone(),
5600 quantifier: None,
5601 inferred_type: None,
5602 }))
5603 } else {
5604 Expression::Like(Box::new(LikeOp {
5605 left: op.left.clone(),
5606 right: val,
5607 escape: op.escape.clone(),
5608 quantifier: None,
5609 inferred_type: None,
5610 }))
5611 };
5612 result = Some(match result {
5613 None => like,
5614 Some(prev) => combiner(prev, like),
5615 });
5616 }
5617 let expanded = result.unwrap_or_else(|| unreachable!("values is non-empty"));
5618 if wrap_marker && num_values > 1 {
5622 Expression::Paren(Box::new(Paren {
5623 this: expanded,
5624 trailing_comments: vec![LIKE_ALL_MARKER.to_string()],
5625 }))
5626 } else {
5627 expanded
5628 }
5629 }
5630
5631 fn or_combiner(a: Expression, b: Expression) -> Expression {
5632 Expression::Or(Box::new(BinaryOp::new(a, b)))
5633 }
5634
5635 fn and_combiner(a: Expression, b: Expression) -> Expression {
5636 Expression::And(Box::new(BinaryOp::new(a, b)))
5637 }
5638
5639 fn is_like_all_marker(p: &Paren) -> bool {
5640 p.trailing_comments.len() == 1 && p.trailing_comments[0] == LIKE_ALL_MARKER
5641 }
5642
5643 let result = transform_recursive(expr, &|e| {
5651 match e {
5652 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
5654 if let Some(values) = extract_tuple_values(&op.right) {
5655 if values.is_empty() {
5656 return Ok(e);
5657 }
5658 Ok(expand_like_quantifier(
5659 op,
5660 values,
5661 false,
5662 or_combiner,
5663 false,
5664 ))
5665 } else {
5666 Ok(e)
5667 }
5668 }
5669 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ALL") => {
5671 if let Some(values) = extract_tuple_values(&op.right) {
5672 if values.is_empty() {
5673 return Ok(e);
5674 }
5675 Ok(expand_like_quantifier(
5676 op,
5677 values,
5678 false,
5679 and_combiner,
5680 true,
5681 ))
5682 } else {
5683 Ok(e)
5684 }
5685 }
5686 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
5688 if let Some(values) = extract_tuple_values(&op.right) {
5689 if values.is_empty() {
5690 return Ok(e);
5691 }
5692 Ok(expand_like_quantifier(op, values, true, or_combiner, false))
5693 } else {
5694 Ok(e)
5695 }
5696 }
5697 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ALL") => {
5699 if let Some(values) = extract_tuple_values(&op.right) {
5700 if values.is_empty() {
5701 return Ok(e);
5702 }
5703 Ok(expand_like_quantifier(op, values, true, and_combiner, true))
5704 } else {
5705 Ok(e)
5706 }
5707 }
5708 Expression::And(mut op) => {
5713 if matches!(&op.left, Expression::Or(_)) {
5714 op.left = Expression::Paren(Box::new(Paren {
5715 this: op.left,
5716 trailing_comments: vec![],
5717 }));
5718 }
5719 if matches!(&op.right, Expression::Or(_)) {
5720 op.right = Expression::Paren(Box::new(Paren {
5721 this: op.right,
5722 trailing_comments: vec![],
5723 }));
5724 }
5725 Ok(Expression::And(op))
5726 }
5727 Expression::Or(mut op) => {
5730 if let Expression::Paren(ref mut p) = op.left {
5731 if is_like_all_marker(p) {
5732 p.trailing_comments.clear();
5733 }
5734 }
5735 if let Expression::Paren(ref mut p) = op.right {
5736 if is_like_all_marker(p) {
5737 p.trailing_comments.clear();
5738 }
5739 }
5740 Ok(Expression::Or(op))
5741 }
5742 _ => Ok(e),
5743 }
5744 })?;
5745
5746 transform_recursive(result, &|e| {
5750 if let Expression::Paren(p) = &e {
5751 if is_like_all_marker(p) {
5752 let Expression::Paren(p) = e else {
5753 unreachable!()
5754 };
5755 return Ok(p.this);
5756 }
5757 }
5758 Ok(e)
5759 })
5760}
5761
5762pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
5770 use crate::expressions::Alias;
5771
5772 fn add_self_aliases_to_select(select: &mut Select) {
5773 let new_expressions: Vec<Expression> = select
5774 .expressions
5775 .iter()
5776 .map(|e| {
5777 match e {
5778 Expression::Column(col) => {
5780 let alias_name = col.name.clone();
5781 Expression::Alias(Box::new(Alias {
5782 this: e.clone(),
5783 alias: alias_name,
5784 column_aliases: Vec::new(),
5785 alias_explicit_as: false,
5786 alias_keyword: None,
5787 pre_alias_comments: Vec::new(),
5788 trailing_comments: Vec::new(),
5789 inferred_type: None,
5790 }))
5791 }
5792 _ => e.clone(),
5794 }
5795 })
5796 .collect();
5797 select.expressions = new_expressions;
5798 }
5799
5800 fn walk_and_qualify(expr: &mut Expression) {
5801 match expr {
5802 Expression::Select(ref mut select) => {
5803 if let Some(ref mut from) = select.from {
5805 for e in from.expressions.iter_mut() {
5806 qualify_subquery_expr(e);
5807 walk_and_qualify(e);
5808 }
5809 }
5810 for join in select.joins.iter_mut() {
5812 qualify_subquery_expr(&mut join.this);
5813 walk_and_qualify(&mut join.this);
5814 }
5815 for e in select.expressions.iter_mut() {
5817 walk_and_qualify(e);
5818 }
5819 if let Some(ref mut w) = select.where_clause {
5821 walk_and_qualify(&mut w.this);
5822 }
5823 }
5824 Expression::Subquery(ref mut subquery) => {
5825 walk_and_qualify(&mut subquery.this);
5826 }
5827 Expression::Union(ref mut u) => {
5828 walk_and_qualify(&mut u.left);
5829 walk_and_qualify(&mut u.right);
5830 }
5831 Expression::Intersect(ref mut i) => {
5832 walk_and_qualify(&mut i.left);
5833 walk_and_qualify(&mut i.right);
5834 }
5835 Expression::Except(ref mut e) => {
5836 walk_and_qualify(&mut e.left);
5837 walk_and_qualify(&mut e.right);
5838 }
5839 Expression::Cte(ref mut cte) => {
5840 walk_and_qualify(&mut cte.this);
5841 }
5842 _ => {}
5843 }
5844 }
5845
5846 fn qualify_subquery_expr(expr: &mut Expression) {
5847 match expr {
5848 Expression::Subquery(ref mut subquery) => {
5849 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
5851 if let Expression::Select(ref mut inner_select) = subquery.this {
5852 let has_star = inner_select
5854 .expressions
5855 .iter()
5856 .any(|e| matches!(e, Expression::Star(_)));
5857 if !has_star {
5858 add_self_aliases_to_select(inner_select);
5859 }
5860 }
5861 }
5862 walk_and_qualify(&mut subquery.this);
5864 }
5865 Expression::Alias(ref mut alias) => {
5866 qualify_subquery_expr(&mut alias.this);
5867 }
5868 _ => {}
5869 }
5870 }
5871
5872 let mut result = expr;
5873 walk_and_qualify(&mut result);
5874
5875 if let Expression::Select(ref mut select) = result {
5877 if let Some(ref mut with) = select.with {
5878 for cte in with.ctes.iter_mut() {
5879 if cte.columns.is_empty() {
5881 walk_and_qualify(&mut cte.this);
5883 }
5884 }
5885 }
5886 }
5887
5888 Ok(result)
5889}
5890
5891#[cfg(test)]
5892mod tests {
5893 use super::*;
5894 use crate::dialects::{Dialect, DialectType};
5895 use crate::expressions::Column;
5896
5897 fn gen(expr: &Expression) -> String {
5898 let dialect = Dialect::get(DialectType::Generic);
5899 dialect.generate(expr).unwrap()
5900 }
5901
5902 #[test]
5903 fn test_preprocess() {
5904 let expr = Expression::Boolean(BooleanLiteral { value: true });
5905 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
5906 assert!(
5907 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
5908 );
5909 }
5910
5911 #[test]
5912 fn test_preprocess_chain() {
5913 let expr = Expression::Boolean(BooleanLiteral { value: true });
5915 let transforms: Vec<fn(Expression) -> Result<Expression>> =
5917 vec![replace_bool_with_int, replace_int_with_bool];
5918 let result = preprocess(expr, &transforms).unwrap();
5919 if let Expression::Boolean(b) = result {
5922 assert!(b.value);
5923 } else {
5924 panic!("Expected boolean literal");
5925 }
5926 }
5927
5928 #[test]
5929 fn test_unnest_to_explode() {
5930 let unnest = Expression::Unnest(Box::new(UnnestFunc {
5931 this: Expression::boxed_column(Column {
5932 name: Identifier::new("arr".to_string()),
5933 table: None,
5934 join_mark: false,
5935 trailing_comments: vec![],
5936 span: None,
5937 inferred_type: None,
5938 }),
5939 expressions: Vec::new(),
5940 with_ordinality: false,
5941 alias: None,
5942 offset_alias: None,
5943 }));
5944
5945 let result = unnest_to_explode(unnest).unwrap();
5946 assert!(matches!(result, Expression::Explode(_)));
5947 }
5948
5949 #[test]
5950 fn test_explode_to_unnest() {
5951 let explode = Expression::Explode(Box::new(UnaryFunc {
5952 this: Expression::boxed_column(Column {
5953 name: Identifier::new("arr".to_string()),
5954 table: None,
5955 join_mark: false,
5956 trailing_comments: vec![],
5957 span: None,
5958 inferred_type: None,
5959 }),
5960 original_name: None,
5961 inferred_type: None,
5962 }));
5963
5964 let result = explode_to_unnest(explode).unwrap();
5965 assert!(matches!(result, Expression::Unnest(_)));
5966 }
5967
5968 #[test]
5969 fn test_replace_bool_with_int() {
5970 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
5971 let result = replace_bool_with_int(true_expr).unwrap();
5972 if let Expression::Literal(lit) = result {
5973 if let Literal::Number(n) = lit.as_ref() {
5974 assert_eq!(n, "1");
5975 }
5976 } else {
5977 panic!("Expected number literal");
5978 }
5979
5980 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
5981 let result = replace_bool_with_int(false_expr).unwrap();
5982 if let Expression::Literal(lit) = result {
5983 if let Literal::Number(n) = lit.as_ref() {
5984 assert_eq!(n, "0");
5985 }
5986 } else {
5987 panic!("Expected number literal");
5988 }
5989 }
5990
5991 #[test]
5992 fn test_replace_int_with_bool() {
5993 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
5994 let result = replace_int_with_bool(one_expr).unwrap();
5995 if let Expression::Boolean(b) = result {
5996 assert!(b.value);
5997 } else {
5998 panic!("Expected boolean true");
5999 }
6000
6001 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
6002 let result = replace_int_with_bool(zero_expr).unwrap();
6003 if let Expression::Boolean(b) = result {
6004 assert!(!b.value);
6005 } else {
6006 panic!("Expected boolean false");
6007 }
6008
6009 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
6011 let result = replace_int_with_bool(two_expr).unwrap();
6012 assert!(
6013 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6014 );
6015 }
6016
6017 #[test]
6018 fn test_strip_data_type_params() {
6019 let decimal = DataType::Decimal {
6021 precision: Some(10),
6022 scale: Some(2),
6023 };
6024 let stripped = strip_data_type_params(decimal);
6025 assert_eq!(
6026 stripped,
6027 DataType::Decimal {
6028 precision: None,
6029 scale: None
6030 }
6031 );
6032
6033 let varchar = DataType::VarChar {
6035 length: Some(255),
6036 parenthesized_length: false,
6037 };
6038 let stripped = strip_data_type_params(varchar);
6039 assert_eq!(
6040 stripped,
6041 DataType::VarChar {
6042 length: None,
6043 parenthesized_length: false
6044 }
6045 );
6046
6047 let char_type = DataType::Char { length: Some(10) };
6049 let stripped = strip_data_type_params(char_type);
6050 assert_eq!(stripped, DataType::Char { length: None });
6051
6052 let timestamp = DataType::Timestamp {
6054 precision: Some(6),
6055 timezone: true,
6056 };
6057 let stripped = strip_data_type_params(timestamp);
6058 assert_eq!(
6059 stripped,
6060 DataType::Timestamp {
6061 precision: None,
6062 timezone: true
6063 }
6064 );
6065
6066 let array = DataType::Array {
6068 element_type: Box::new(DataType::VarChar {
6069 length: Some(100),
6070 parenthesized_length: false,
6071 }),
6072 dimension: None,
6073 };
6074 let stripped = strip_data_type_params(array);
6075 assert_eq!(
6076 stripped,
6077 DataType::Array {
6078 element_type: Box::new(DataType::VarChar {
6079 length: None,
6080 parenthesized_length: false
6081 }),
6082 dimension: None,
6083 }
6084 );
6085
6086 let text = DataType::Text;
6088 let stripped = strip_data_type_params(text);
6089 assert_eq!(stripped, DataType::Text);
6090 }
6091
6092 #[test]
6093 fn test_remove_precision_parameterized_types_cast() {
6094 let cast_expr = Expression::Cast(Box::new(Cast {
6096 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6097 to: DataType::Decimal {
6098 precision: Some(10),
6099 scale: Some(2),
6100 },
6101 trailing_comments: vec![],
6102 double_colon_syntax: false,
6103 format: None,
6104 default: None,
6105 inferred_type: None,
6106 }));
6107
6108 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6109 if let Expression::Cast(cast) = result {
6110 assert_eq!(
6111 cast.to,
6112 DataType::Decimal {
6113 precision: None,
6114 scale: None
6115 }
6116 );
6117 } else {
6118 panic!("Expected Cast expression");
6119 }
6120 }
6121
6122 #[test]
6123 fn test_remove_precision_parameterized_types_varchar() {
6124 let cast_expr = Expression::Cast(Box::new(Cast {
6126 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
6127 to: DataType::VarChar {
6128 length: Some(10),
6129 parenthesized_length: false,
6130 },
6131 trailing_comments: vec![],
6132 double_colon_syntax: false,
6133 format: None,
6134 default: None,
6135 inferred_type: None,
6136 }));
6137
6138 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6139 if let Expression::Cast(cast) = result {
6140 assert_eq!(
6141 cast.to,
6142 DataType::VarChar {
6143 length: None,
6144 parenthesized_length: false
6145 }
6146 );
6147 } else {
6148 panic!("Expected Cast expression");
6149 }
6150 }
6151
6152 #[test]
6153 fn test_remove_precision_direct_cast() {
6154 let cast = Expression::Cast(Box::new(Cast {
6158 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6159 to: DataType::Decimal {
6160 precision: Some(10),
6161 scale: Some(2),
6162 },
6163 trailing_comments: vec![],
6164 double_colon_syntax: false,
6165 format: None,
6166 default: None,
6167 inferred_type: None,
6168 }));
6169
6170 let transformed = remove_precision_parameterized_types(cast).unwrap();
6171 let generated = gen(&transformed);
6172
6173 assert!(generated.contains("DECIMAL"));
6175 assert!(!generated.contains("(10"));
6176 }
6177
6178 #[test]
6179 fn test_epoch_cast_to_ts() {
6180 let cast_expr = Expression::Cast(Box::new(Cast {
6182 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
6183 to: DataType::Timestamp {
6184 precision: None,
6185 timezone: false,
6186 },
6187 trailing_comments: vec![],
6188 double_colon_syntax: false,
6189 format: None,
6190 default: None,
6191 inferred_type: None,
6192 }));
6193
6194 let result = epoch_cast_to_ts(cast_expr).unwrap();
6195 if let Expression::Cast(cast) = result {
6196 if let Expression::Literal(lit) = cast.this {
6197 if let Literal::String(s) = lit.as_ref() {
6198 assert_eq!(s, "1970-01-01 00:00:00");
6199 }
6200 } else {
6201 panic!("Expected string literal");
6202 }
6203 } else {
6204 panic!("Expected Cast expression");
6205 }
6206 }
6207
6208 #[test]
6209 fn test_epoch_cast_to_ts_preserves_non_epoch() {
6210 let cast_expr = Expression::Cast(Box::new(Cast {
6212 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
6213 to: DataType::Timestamp {
6214 precision: None,
6215 timezone: false,
6216 },
6217 trailing_comments: vec![],
6218 double_colon_syntax: false,
6219 format: None,
6220 default: None,
6221 inferred_type: None,
6222 }));
6223
6224 let result = epoch_cast_to_ts(cast_expr).unwrap();
6225 if let Expression::Cast(cast) = result {
6226 if let Expression::Literal(lit) = cast.this {
6227 if let Literal::String(s) = lit.as_ref() {
6228 assert_eq!(s, "2024-01-15");
6229 }
6230 } else {
6231 panic!("Expected string literal");
6232 }
6233 } else {
6234 panic!("Expected Cast expression");
6235 }
6236 }
6237
6238 #[test]
6239 fn test_unqualify_columns() {
6240 let col = Expression::boxed_column(Column {
6242 name: Identifier::new("id".to_string()),
6243 table: Some(Identifier::new("users".to_string())),
6244 join_mark: false,
6245 trailing_comments: vec![],
6246 span: None,
6247 inferred_type: None,
6248 });
6249
6250 let result = unqualify_columns(col).unwrap();
6251 if let Expression::Column(c) = result {
6252 assert!(c.table.is_none());
6253 assert_eq!(c.name.name, "id");
6254 } else {
6255 panic!("Expected Column expression");
6256 }
6257 }
6258
6259 #[test]
6260 fn test_is_temporal_type() {
6261 assert!(is_temporal_type(&DataType::Date));
6262 assert!(is_temporal_type(&DataType::Timestamp {
6263 precision: None,
6264 timezone: false
6265 }));
6266 assert!(is_temporal_type(&DataType::Time {
6267 precision: None,
6268 timezone: false
6269 }));
6270 assert!(!is_temporal_type(&DataType::Int {
6271 length: None,
6272 integer_spelling: false
6273 }));
6274 assert!(!is_temporal_type(&DataType::VarChar {
6275 length: None,
6276 parenthesized_length: false
6277 }));
6278 }
6279
6280 #[test]
6281 fn test_eliminate_semi_join_basic() {
6282 use crate::expressions::{Join, TableRef};
6283
6284 let select = Expression::Select(Box::new(Select {
6286 expressions: vec![Expression::boxed_column(Column {
6287 name: Identifier::new("a".to_string()),
6288 table: None,
6289 join_mark: false,
6290 trailing_comments: vec![],
6291 span: None,
6292 inferred_type: None,
6293 })],
6294 from: Some(From {
6295 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
6296 }),
6297 joins: vec![Join {
6298 this: Expression::Table(Box::new(TableRef::new("t2"))),
6299 kind: JoinKind::Semi,
6300 on: Some(Expression::Eq(Box::new(BinaryOp {
6301 left: Expression::boxed_column(Column {
6302 name: Identifier::new("x".to_string()),
6303 table: None,
6304 join_mark: false,
6305 trailing_comments: vec![],
6306 span: None,
6307 inferred_type: None,
6308 }),
6309 right: Expression::boxed_column(Column {
6310 name: Identifier::new("y".to_string()),
6311 table: None,
6312 join_mark: false,
6313 trailing_comments: vec![],
6314 span: None,
6315 inferred_type: None,
6316 }),
6317 left_comments: vec![],
6318 operator_comments: vec![],
6319 trailing_comments: vec![],
6320 inferred_type: None,
6321 }))),
6322 using: vec![],
6323 use_inner_keyword: false,
6324 use_outer_keyword: false,
6325 deferred_condition: false,
6326 join_hint: None,
6327 match_condition: None,
6328 pivots: Vec::new(),
6329 comments: Vec::new(),
6330 nesting_group: 0,
6331 directed: false,
6332 }],
6333 ..Select::new()
6334 }));
6335
6336 let result = eliminate_semi_and_anti_joins(select).unwrap();
6337 if let Expression::Select(s) = result {
6338 assert!(s.joins.is_empty());
6340 assert!(s.where_clause.is_some());
6342 } else {
6343 panic!("Expected Select expression");
6344 }
6345 }
6346
6347 #[test]
6348 fn test_no_ilike_sql() {
6349 use crate::expressions::LikeOp;
6350
6351 let ilike_expr = Expression::ILike(Box::new(LikeOp {
6353 left: Expression::boxed_column(Column {
6354 name: Identifier::new("name".to_string()),
6355 table: None,
6356 join_mark: false,
6357 trailing_comments: vec![],
6358 span: None,
6359 inferred_type: None,
6360 }),
6361 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
6362 escape: None,
6363 quantifier: None,
6364 inferred_type: None,
6365 }));
6366
6367 let result = no_ilike_sql(ilike_expr).unwrap();
6368 if let Expression::Like(like) = result {
6369 if let Expression::Function(f) = &like.left {
6371 assert_eq!(f.name, "LOWER");
6372 } else {
6373 panic!("Expected LOWER function on left");
6374 }
6375 if let Expression::Function(f) = &like.right {
6377 assert_eq!(f.name, "LOWER");
6378 } else {
6379 panic!("Expected LOWER function on right");
6380 }
6381 } else {
6382 panic!("Expected Like expression");
6383 }
6384 }
6385
6386 #[test]
6387 fn test_no_trycast_sql() {
6388 let trycast_expr = Expression::TryCast(Box::new(Cast {
6390 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6391 to: DataType::Int {
6392 length: None,
6393 integer_spelling: false,
6394 },
6395 trailing_comments: vec![],
6396 double_colon_syntax: false,
6397 format: None,
6398 default: None,
6399 inferred_type: None,
6400 }));
6401
6402 let result = no_trycast_sql(trycast_expr).unwrap();
6403 assert!(matches!(result, Expression::Cast(_)));
6404 }
6405
6406 #[test]
6407 fn test_no_safe_cast_sql() {
6408 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
6410 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6411 to: DataType::Int {
6412 length: None,
6413 integer_spelling: false,
6414 },
6415 trailing_comments: vec![],
6416 double_colon_syntax: false,
6417 format: None,
6418 default: None,
6419 inferred_type: None,
6420 }));
6421
6422 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
6423 assert!(matches!(result, Expression::Cast(_)));
6424 }
6425
6426 #[test]
6427 fn test_explode_to_unnest_presto() {
6428 let spark = Dialect::get(DialectType::Spark);
6429 let result = spark
6430 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
6431 .unwrap();
6432 assert_eq!(
6433 result[0],
6434 "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))"
6435 );
6436 }
6437
6438 #[test]
6439 fn test_explode_to_unnest_bigquery() {
6440 let spark = Dialect::get(DialectType::Spark);
6441 let result = spark
6442 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
6443 .unwrap();
6444 assert_eq!(
6445 result[0],
6446 "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))"
6447 );
6448 }
6449}