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(crate) fn normalize_grouping_sets_for_tsql(expr: Expression) -> Result<Expression> {
45 transform_recursive(expr, &|expr| {
46 let Expression::Select(mut select) = expr else {
47 return Ok(expr);
48 };
49
50 if let Some(group_by) = select.group_by.as_mut() {
51 group_by.expressions = std::mem::take(&mut group_by.expressions)
52 .into_iter()
53 .map(normalize_tsql_grouping_element)
54 .collect();
55 }
56
57 Ok(Expression::Select(select))
58 })
59}
60
61fn normalize_tsql_grouping_element(expression: Expression) -> Expression {
62 match expression {
63 Expression::Function(mut function)
64 if !function.quoted && function.name.eq_ignore_ascii_case("GROUPING SETS") =>
65 {
66 function.args = normalize_tsql_grouping_sets(std::mem::take(&mut function.args));
67 Expression::Function(function)
68 }
69 Expression::GroupingSets(mut grouping_sets) => {
70 grouping_sets.expressions =
71 normalize_tsql_grouping_sets(std::mem::take(&mut grouping_sets.expressions));
72 Expression::GroupingSets(grouping_sets)
73 }
74 Expression::Function(mut function)
75 if !function.quoted
76 && (function.name.eq_ignore_ascii_case("ROLLUP")
77 || function.name.eq_ignore_ascii_case("CUBE")) =>
78 {
79 function.args = std::mem::take(&mut function.args)
80 .into_iter()
81 .map(normalize_tsql_grouping_unit)
82 .collect();
83 Expression::Function(function)
84 }
85 Expression::Rollup(mut rollup) => {
86 rollup.expressions = std::mem::take(&mut rollup.expressions)
87 .into_iter()
88 .map(normalize_tsql_grouping_unit)
89 .collect();
90 Expression::Rollup(rollup)
91 }
92 Expression::Cube(mut cube) => {
93 cube.expressions = std::mem::take(&mut cube.expressions)
94 .into_iter()
95 .map(normalize_tsql_grouping_unit)
96 .collect();
97 Expression::Cube(cube)
98 }
99 other => other,
100 }
101}
102
103fn normalize_tsql_grouping_sets(expressions: Vec<Expression>) -> Vec<Expression> {
104 let mut normalized = Vec::new();
105
106 for expression in expressions {
107 match expression {
108 Expression::Function(mut function)
109 if !function.quoted && function.name.eq_ignore_ascii_case("GROUPING SETS") =>
110 {
111 normalized.extend(normalize_tsql_grouping_sets(std::mem::take(
112 &mut function.args,
113 )));
114 }
115 Expression::GroupingSets(mut grouping_sets) => {
116 normalized.extend(normalize_tsql_grouping_sets(std::mem::take(
117 &mut grouping_sets.expressions,
118 )));
119 }
120 other => normalized.push(normalize_tsql_grouping_unit(
121 normalize_tsql_grouping_element(other),
122 )),
123 }
124 }
125
126 normalized
127}
128
129fn normalize_tsql_grouping_unit(expression: Expression) -> Expression {
130 let Expression::Tuple(tuple) = expression else {
131 return expression;
132 };
133
134 let mut expressions = Vec::new();
135 for expression in tuple.expressions {
136 append_tsql_grouping_unit(expression, &mut expressions);
137 }
138
139 Expression::Tuple(Box::new(Tuple { expressions }))
140}
141
142fn append_tsql_grouping_unit(expression: Expression, expressions: &mut Vec<Expression>) {
143 match expression {
144 Expression::Tuple(tuple) => {
145 for expression in tuple.expressions {
146 append_tsql_grouping_unit(expression, expressions);
147 }
148 }
149 Expression::Paren(paren) => append_tsql_grouping_unit(paren.this, expressions),
150 other => {
151 if !expressions.contains(&other) {
152 expressions.push(other);
153 }
154 }
155 }
156}
157
158pub fn expand_distinct_grouping_sets_for_tsql(
161 expr: Expression,
162 target: DialectType,
163) -> Result<Expression> {
164 transform_recursive(expr, &|expr| {
165 let Expression::Select(mut select) = expr else {
166 return Ok(expr);
167 };
168
169 let Some(group_by) = select.group_by.as_mut() else {
170 return Ok(Expression::Select(select));
171 };
172 if group_by.all != Some(false) {
173 return Ok(Expression::Select(select));
174 }
175
176 let mut product = vec![Vec::new()];
177 let mut has_advanced_grouping = false;
178
179 for element in &group_by.expressions {
180 let alternatives = match expand_grouping_element(element, target)? {
181 Some(alternatives) => {
182 has_advanced_grouping = true;
183 alternatives
184 }
185 None => vec![vec![element.clone()]],
186 };
187
188 let expanded_len = product
189 .len()
190 .checked_mul(alternatives.len())
191 .filter(|len| *len <= MAX_TSQL_GROUPING_SETS)
192 .ok_or_else(|| grouping_set_expansion_error(target))?;
193 let mut next = Vec::with_capacity(expanded_len);
194
195 for left in &product {
196 for right in &alternatives {
197 let mut combined = left.clone();
198 for expression in right {
199 if !combined.contains(expression) {
200 combined.push(expression.clone());
201 }
202 }
203 next.push(combined);
204 }
205 }
206 product = next;
207 }
208
209 if !has_advanced_grouping {
210 return Ok(Expression::Select(select));
211 }
212
213 let mut distinct_sets = Vec::with_capacity(product.len());
214 for grouping_set in product {
215 if !distinct_sets.contains(&grouping_set) {
216 distinct_sets.push(grouping_set);
217 }
218 }
219
220 let sets = distinct_sets
221 .into_iter()
222 .map(|expressions| Expression::Tuple(Box::new(Tuple { expressions })))
223 .collect();
224 group_by.all = None;
225 group_by.expressions = vec![Expression::Function(Box::new(Function::new(
226 "GROUPING SETS".to_string(),
227 sets,
228 )))];
229
230 Ok(Expression::Select(select))
231 })
232}
233
234fn expand_grouping_element(
235 expression: &Expression,
236 target: DialectType,
237) -> Result<Option<Vec<Vec<Expression>>>> {
238 match expression {
239 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROLLUP") => {
240 Ok(Some(expand_rollup(&function.args)))
241 }
242 Expression::Function(function) if function.name.eq_ignore_ascii_case("CUBE") => {
243 Ok(Some(expand_cube(&function.args, target)?))
244 }
245 Expression::Function(function) if function.name.eq_ignore_ascii_case("GROUPING SETS") => {
246 Ok(Some(expand_explicit_grouping_sets(&function.args, target)?))
247 }
248 Expression::Rollup(rollup) => Ok(Some(expand_rollup(&rollup.expressions))),
249 Expression::Cube(cube) => Ok(Some(expand_cube(&cube.expressions, target)?)),
250 Expression::GroupingSets(grouping_sets) => Ok(Some(expand_explicit_grouping_sets(
251 &grouping_sets.expressions,
252 target,
253 )?)),
254 _ => Ok(None),
255 }
256}
257
258fn expand_rollup(elements: &[Expression]) -> Vec<Vec<Expression>> {
259 (0..=elements.len())
260 .rev()
261 .map(|end| flatten_grouping_units(&elements[..end]))
262 .collect()
263}
264
265fn expand_cube(elements: &[Expression], target: DialectType) -> Result<Vec<Vec<Expression>>> {
266 let set_count = 1usize
267 .checked_shl(elements.len() as u32)
268 .filter(|count| *count <= MAX_TSQL_GROUPING_SETS)
269 .ok_or_else(|| grouping_set_expansion_error(target))?;
270
271 Ok((0..set_count)
272 .rev()
273 .map(|mask| {
274 let selected = elements
275 .iter()
276 .enumerate()
277 .filter_map(|(index, element)| {
278 let bit = elements.len() - index - 1;
279 (mask & (1usize << bit) != 0).then_some(element)
280 })
281 .cloned()
282 .collect::<Vec<_>>();
283 flatten_grouping_units(&selected)
284 })
285 .collect())
286}
287
288fn expand_explicit_grouping_sets(
289 elements: &[Expression],
290 target: DialectType,
291) -> Result<Vec<Vec<Expression>>> {
292 let mut sets = Vec::new();
293 for element in elements {
294 if let Some(nested) = expand_grouping_element(element, target)? {
295 sets.extend(nested);
296 } else {
297 sets.push(flatten_grouping_unit(element));
298 }
299 if sets.len() > MAX_TSQL_GROUPING_SETS {
300 return Err(grouping_set_expansion_error(target));
301 }
302 }
303 Ok(sets)
304}
305
306fn flatten_grouping_units(elements: &[Expression]) -> Vec<Expression> {
307 elements.iter().flat_map(flatten_grouping_unit).collect()
308}
309
310fn flatten_grouping_unit(expression: &Expression) -> Vec<Expression> {
311 match expression {
312 Expression::Tuple(tuple) => tuple.expressions.clone(),
313 Expression::Paren(paren) => flatten_grouping_unit(&paren.this),
314 _ => vec![expression.clone()],
315 }
316}
317
318fn grouping_set_expansion_error(target: DialectType) -> Error {
319 Error::unsupported(
320 format!("GROUP BY DISTINCT expansion beyond {MAX_TSQL_GROUPING_SETS} grouping sets"),
321 target.to_string(),
322 )
323}
324
325pub fn grouped_percentiles_to_tsql_windows(expr: Expression) -> Result<Expression> {
336 transform_recursive(expr, &grouped_percentiles_to_tsql_windows_inner)
337}
338
339fn grouped_percentiles_to_tsql_windows_inner(expr: Expression) -> Result<Expression> {
340 let Expression::Select(select) = expr else {
341 return Ok(expr);
342 };
343
344 rewrite_grouped_percentile_select(*select)
345}
346
347fn rewrite_grouped_percentile_select(mut select: Select) -> Result<Expression> {
348 let Some(group_by) = &select.group_by else {
349 return Ok(Expression::Select(Box::new(select)));
350 };
351
352 if select.having.is_some()
353 || group_by.all.is_some()
354 || group_by.totals
355 || group_by.expressions.is_empty()
356 || group_by.expressions.iter().any(is_complex_grouping_expr)
357 {
358 return Ok(Expression::Select(Box::new(select)));
359 }
360
361 let partition_by = group_by.expressions.clone();
362 let original_expressions = select.expressions.clone();
363 let mut changed = false;
364 let mut rewritten_expressions = Vec::with_capacity(select.expressions.len());
365
366 for expression in &select.expressions {
367 if is_group_projection(expression, &partition_by) {
368 rewritten_expressions.push(expression.clone());
369 continue;
370 }
371
372 let Some(rewritten) = rewrite_grouped_percentile_projection(expression, &partition_by)
373 else {
374 return Ok(Expression::Select(Box::new(select)));
375 };
376
377 changed = true;
378 rewritten_expressions.push(rewritten);
379 }
380
381 if !changed {
382 return Ok(Expression::Select(Box::new(select)));
383 }
384
385 let all_grouping_keys_projected = partition_by.iter().all(|group_expr| {
386 original_expressions
387 .iter()
388 .any(|projection| is_projection_of_group_expr(projection, group_expr))
389 });
390
391 if all_grouping_keys_projected {
392 select.expressions = rewritten_expressions;
393 select.group_by = None;
394 select.distinct = true;
395 return Ok(Expression::Select(Box::new(select)));
396 }
397
398 rewrite_grouped_percentile_select_with_hidden_groups(
399 select,
400 original_expressions,
401 rewritten_expressions,
402 partition_by,
403 )
404}
405
406fn is_complex_grouping_expr(expr: &Expression) -> bool {
407 matches!(
408 expr,
409 Expression::Cube(_) | Expression::Rollup(_) | Expression::GroupingSets(_)
410 ) || matches!(expr, Expression::Function(f) if f.name.eq_ignore_ascii_case("GROUPING SETS"))
411}
412
413fn is_group_projection(expr: &Expression, group_by: &[Expression]) -> bool {
414 let inner = unalias_expression(expr);
415
416 group_by.iter().any(|group_expr| inner == group_expr)
417}
418
419fn is_projection_of_group_expr(projection: &Expression, group_expr: &Expression) -> bool {
420 unalias_expression(projection) == group_expr
421}
422
423fn unalias_expression(expr: &Expression) -> &Expression {
424 match expr {
425 Expression::Alias(alias) => &alias.this,
426 other => other,
427 }
428}
429
430fn rewrite_grouped_percentile_select_with_hidden_groups(
431 mut inner: Select,
432 original_expressions: Vec<Expression>,
433 rewritten_expressions: Vec<Expression>,
434 group_by: Vec<Expression>,
435) -> Result<Expression> {
436 let original_distinct = inner.distinct;
437
438 let mut used_column_names = original_expressions
439 .iter()
440 .filter_map(grouped_percentile_output_identifier)
441 .map(|identifier| identifier.name)
442 .collect::<Vec<_>>();
443 let projection_aliases = (0..rewritten_expressions.len())
444 .map(|index| {
445 Identifier::new(fresh_grouped_percentile_name(
446 &mut used_column_names,
447 &format!("_polyglot_projection_{index}"),
448 ))
449 })
450 .collect::<Vec<_>>();
451 let group_aliases = (0..group_by.len())
452 .map(|index| {
453 Identifier::new(fresh_grouped_percentile_name(
454 &mut used_column_names,
455 &format!("_polyglot_group_{index}"),
456 ))
457 })
458 .collect::<Vec<_>>();
459
460 let mut used_source_names = Vec::new();
461 if let Some(from) = &inner.from {
462 for source in &from.expressions {
463 collect_grouped_percentile_source_names(source, &mut used_source_names);
464 }
465 }
466 for join in &inner.joins {
467 collect_grouped_percentile_source_names(&join.this, &mut used_source_names);
468 }
469 let derived_alias = Identifier::new(fresh_grouped_percentile_name(
470 &mut used_source_names,
471 "_polyglot_grouped_percentile",
472 ));
473
474 let mut inner_expressions = rewritten_expressions
475 .into_iter()
476 .zip(&projection_aliases)
477 .map(|(expression, alias)| {
478 Expression::Alias(Box::new(Alias::new(
479 take_alias_expression(expression),
480 alias.clone(),
481 )))
482 })
483 .collect::<Vec<_>>();
484 inner_expressions.extend(group_by.iter().cloned().zip(&group_aliases).map(
485 |(expression, alias)| Expression::Alias(Box::new(Alias::new(expression, alias.clone()))),
486 ));
487
488 let outer_order_by = inner.order_by.take();
489 let outer_with = inner.with.take();
490 let outer_top = inner.top.take();
491 let outer_limit = inner.limit.take();
492 let outer_offset = inner.offset.take();
493 let outer_limit_by = inner.limit_by.take();
494 let outer_fetch = inner.fetch.take();
495 let outer_distribute_by = inner.distribute_by.take();
496 let outer_cluster_by = inner.cluster_by.take();
497 let outer_sort_by = inner.sort_by.take();
498 let outer_settings = inner.settings.take();
499 let outer_format = inner.format.take();
500 let outer_hint = inner.hint.take();
501 let outer_into = inner.into.take();
502 let outer_locks = std::mem::take(&mut inner.locks);
503 let outer_for_xml = std::mem::take(&mut inner.for_xml);
504 let outer_for_json = std::mem::take(&mut inner.for_json);
505 let outer_leading_comments = std::mem::take(&mut inner.leading_comments);
506 let outer_post_select_comments = std::mem::take(&mut inner.post_select_comments);
507 let outer_kind = inner.kind.take();
508 let outer_operation_modifiers = std::mem::take(&mut inner.operation_modifiers);
509 let outer_option = inner.option.take();
510 let outer_exclude = inner.exclude.take();
511
512 inner.expressions = inner_expressions;
513 inner.group_by = None;
514 inner.distinct = true;
515
516 let outer_expressions = original_expressions
517 .iter()
518 .zip(&projection_aliases)
519 .map(|(original, internal_alias)| {
520 let reference = grouped_percentile_derived_column(&derived_alias, internal_alias);
521 match original {
522 Expression::Alias(alias) => {
523 let mut outer_alias = alias.as_ref().clone();
524 outer_alias.this = reference;
525 Expression::Alias(Box::new(outer_alias))
526 }
527 _ => grouped_percentile_output_identifier(original)
528 .map_or(reference.clone(), |output_alias| {
529 Expression::Alias(Box::new(Alias::new(reference, output_alias)))
530 }),
531 }
532 })
533 .collect::<Vec<_>>();
534
535 let outer_order_by = outer_order_by
536 .map(|mut order_by| {
537 for ordered in &mut order_by.expressions {
538 ordered.this = rewrite_grouped_percentile_outer_reference(
539 std::mem::replace(
540 &mut ordered.this,
541 Expression::Null(crate::expressions::Null),
542 ),
543 &original_expressions,
544 &projection_aliases,
545 &group_by,
546 &group_aliases,
547 &derived_alias,
548 )?;
549 }
550 Ok(order_by)
551 })
552 .transpose()?;
553
554 let subquery = Subquery {
555 this: Expression::Select(Box::new(inner)),
556 alias: Some(derived_alias),
557 column_aliases: Vec::new(),
558 alias_explicit_as: true,
559 alias_keyword: None,
560 order_by: None,
561 limit: None,
562 offset: None,
563 distribute_by: None,
564 sort_by: None,
565 cluster_by: None,
566 lateral: false,
567 modifiers_inside: false,
568 trailing_comments: Vec::new(),
569 inferred_type: None,
570 };
571
572 let mut outer = Select::new();
573 outer.expressions = outer_expressions;
574 outer.from = Some(From {
575 expressions: vec![Expression::Subquery(Box::new(subquery))],
576 });
577 outer.distinct = original_distinct;
578 outer.with = outer_with;
579 outer.order_by = outer_order_by;
580 outer.top = outer_top;
581 outer.limit = outer_limit;
582 outer.offset = outer_offset;
583 outer.limit_by = outer_limit_by;
584 outer.fetch = outer_fetch;
585 outer.distribute_by = outer_distribute_by;
586 outer.cluster_by = outer_cluster_by;
587 outer.sort_by = outer_sort_by;
588 outer.settings = outer_settings;
589 outer.format = outer_format;
590 outer.hint = outer_hint;
591 outer.into = outer_into;
592 outer.locks = outer_locks;
593 outer.for_xml = outer_for_xml;
594 outer.for_json = outer_for_json;
595 outer.leading_comments = outer_leading_comments;
596 outer.post_select_comments = outer_post_select_comments;
597 outer.kind = outer_kind;
598 outer.operation_modifiers = outer_operation_modifiers;
599 outer.option = outer_option;
600 outer.exclude = outer_exclude;
601
602 Ok(Expression::Select(Box::new(outer)))
603}
604
605fn take_alias_expression(expression: Expression) -> Expression {
606 match expression {
607 Expression::Alias(alias) => alias.this,
608 other => other,
609 }
610}
611
612fn grouped_percentile_output_identifier(expression: &Expression) -> Option<Identifier> {
613 match expression {
614 Expression::Alias(alias) if !alias.alias.is_empty() => Some(alias.alias.clone()),
615 Expression::Column(column) => Some(column.name.clone()),
616 Expression::Identifier(identifier) => Some(identifier.clone()),
617 Expression::Function(function) => Some(if function.quoted {
618 Identifier::quoted(function.name.clone())
619 } else {
620 Identifier::new(function.name.to_ascii_lowercase())
621 }),
622 Expression::AggregateFunction(function) => {
623 Some(Identifier::new(function.name.to_ascii_lowercase()))
624 }
625 Expression::WithinGroup(within_group) => {
626 grouped_percentile_output_identifier(&within_group.this)
627 }
628 Expression::PercentileCont(_) => Some(Identifier::new("percentile_cont")),
629 Expression::PercentileDisc(_) => Some(Identifier::new("percentile_disc")),
630 _ => None,
631 }
632}
633
634fn fresh_grouped_percentile_name(used_names: &mut Vec<String>, base: &str) -> String {
635 let mut suffix = 1;
636 loop {
637 let candidate = if suffix == 1 {
638 base.to_string()
639 } else {
640 format!("{base}_{suffix}")
641 };
642 if !used_names
643 .iter()
644 .any(|name| name.eq_ignore_ascii_case(&candidate))
645 {
646 used_names.push(candidate.clone());
647 return candidate;
648 }
649 suffix += 1;
650 }
651}
652
653fn collect_grouped_percentile_source_names(expression: &Expression, names: &mut Vec<String>) {
654 match expression {
655 Expression::Alias(alias) if !alias.alias.is_empty() => names.push(alias.alias.name.clone()),
656 Expression::Subquery(subquery) => {
657 if let Some(alias) = &subquery.alias {
658 names.push(alias.name.clone());
659 }
660 }
661 Expression::Table(table) => {
662 names.push(table.alias.as_ref().unwrap_or(&table.name).name.clone())
663 }
664 _ => {}
665 }
666}
667
668fn grouped_percentile_derived_column(
669 derived_alias: &Identifier,
670 column_alias: &Identifier,
671) -> Expression {
672 Expression::qualified_column(derived_alias.name.clone(), column_alias.name.clone())
673}
674
675fn rewrite_grouped_percentile_outer_reference(
676 expression: Expression,
677 original_expressions: &[Expression],
678 projection_aliases: &[Identifier],
679 group_by: &[Expression],
680 group_aliases: &[Identifier],
681 derived_alias: &Identifier,
682) -> Result<Expression> {
683 transform_recursive(expression, &|node| {
684 if let Some((_, alias)) =
685 original_expressions
686 .iter()
687 .zip(projection_aliases)
688 .find(|(original, _)| {
689 unalias_expression(original) == &node
690 || grouped_percentile_output_identifier(original).is_some_and(
691 |identifier| expression_references_identifier(&node, &identifier),
692 )
693 })
694 {
695 return Ok(grouped_percentile_derived_column(derived_alias, alias));
696 }
697
698 if let Some((_, alias)) = group_by
699 .iter()
700 .zip(group_aliases)
701 .find(|(group_expr, _)| *group_expr == &node)
702 {
703 return Ok(grouped_percentile_derived_column(derived_alias, alias));
704 }
705
706 Ok(node)
707 })
708}
709
710fn expression_references_identifier(expression: &Expression, identifier: &Identifier) -> bool {
711 let referenced = match expression {
712 Expression::Column(column) if column.table.is_none() => Some(&column.name),
713 Expression::Identifier(referenced) => Some(referenced),
714 _ => None,
715 };
716
717 referenced.is_some_and(|referenced| {
718 if referenced.quoted || identifier.quoted {
719 referenced.name == identifier.name
720 } else {
721 referenced.name.eq_ignore_ascii_case(&identifier.name)
722 }
723 })
724}
725
726fn rewrite_grouped_percentile_projection(
727 expr: &Expression,
728 partition_by: &[Expression],
729) -> Option<Expression> {
730 match expr {
731 Expression::Alias(alias) => {
732 let rewritten = rewrite_grouped_percentile_expr(&alias.this, partition_by)?;
733 let mut alias = alias.as_ref().clone();
734 alias.this = rewritten;
735 Some(Expression::Alias(Box::new(alias)))
736 }
737 other => rewrite_grouped_percentile_expr(other, partition_by),
738 }
739}
740
741fn rewrite_grouped_percentile_expr(
742 expr: &Expression,
743 partition_by: &[Expression],
744) -> Option<Expression> {
745 let Expression::WithinGroup(within_group) = expr else {
746 return None;
747 };
748
749 if !is_percentile_ordered_set(&within_group.this) || within_group.order_by.len() != 1 {
750 return None;
751 }
752
753 let mut order_by = within_group.order_by.clone();
754 order_by[0].nulls_first = None;
758
759 Some(Expression::WindowFunction(Box::new(WindowFunction {
760 this: Expression::WithinGroup(Box::new(WithinGroup {
761 this: within_group.this.clone(),
762 order_by,
763 })),
764 over: Over {
765 window_name: None,
766 partition_by: partition_by.to_vec(),
767 order_by: Vec::new(),
768 frame: None,
769 alias: None,
770 },
771 keep: None,
772 inferred_type: None,
773 })))
774}
775
776fn is_percentile_ordered_set(expr: &Expression) -> bool {
777 match expr {
778 Expression::Function(function) => is_percentile_name(&function.name),
779 Expression::AggregateFunction(function) => is_percentile_name(&function.name),
780 Expression::PercentileCont(_) | Expression::PercentileDisc(_) => true,
781 _ => false,
782 }
783}
784
785fn is_percentile_name(name: &str) -> bool {
786 name.eq_ignore_ascii_case("PERCENTILE_CONT") || name.eq_ignore_ascii_case("PERCENTILE_DISC")
787}
788
789pub fn unnest_to_explode(expr: Expression) -> Result<Expression> {
793 match expr {
794 Expression::Unnest(unnest) => {
795 Ok(Expression::Explode(Box::new(UnaryFunc::new(unnest.this))))
796 }
797 _ => Ok(expr),
798 }
799}
800
801pub fn unnest_to_explode_select(expr: Expression) -> Result<Expression> {
811 transform_recursive(expr, &unnest_to_explode_select_inner)
812}
813
814fn make_udtf_expr(unnest: &UnnestFunc) -> Expression {
817 let has_multi_expr = !unnest.expressions.is_empty();
818 if has_multi_expr {
819 let mut all_args = vec![unnest.this.clone()];
821 all_args.extend(unnest.expressions.iter().cloned());
822 let arrays_zip =
823 Expression::Function(Box::new(Function::new("ARRAYS_ZIP".to_string(), all_args)));
824 Expression::Function(Box::new(Function::new(
825 "INLINE".to_string(),
826 vec![arrays_zip],
827 )))
828 } else {
829 Expression::Explode(Box::new(UnaryFunc::new(unnest.this.clone())))
831 }
832}
833
834fn unnest_to_explode_select_inner(expr: Expression) -> Result<Expression> {
835 let Expression::Select(mut select) = expr else {
836 return Ok(expr);
837 };
838
839 if let Some(ref mut from) = select.from {
841 if from.expressions.len() >= 1 {
842 let mut new_from_exprs = Vec::new();
843 let mut new_lateral_views = Vec::new();
844 let first_is_unnest = is_unnest_expr(&from.expressions[0]);
845
846 for (idx, from_item) in from.expressions.drain(..).enumerate() {
847 if idx == 0 && first_is_unnest {
848 let replaced = replace_from_unnest(from_item);
851 new_from_exprs.push(replaced);
852 } else if idx > 0 && is_unnest_expr(&from_item) {
853 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(from_item);
855 let udtf = make_udtf_expr(&unnest_func);
856 new_lateral_views.push(LateralView {
857 this: udtf,
858 table_alias: alias_name,
859 column_aliases,
860 outer: false,
861 });
862 } else {
863 new_from_exprs.push(from_item);
864 }
865 }
866
867 from.expressions = new_from_exprs;
868 select.lateral_views.extend(new_lateral_views);
870 }
871 }
872
873 let mut remaining_joins = Vec::new();
875 for join in select.joins.drain(..) {
876 if matches!(join.kind, JoinKind::Cross | JoinKind::Inner) {
877 let (is_unnest, is_lateral) = check_join_unnest(&join.this);
878 if is_unnest {
879 let (lateral_alias, lateral_col_aliases, join_expr) = if is_lateral {
881 if let Expression::Lateral(lat) = join.this {
882 let alias = lat.alias.map(|s| Identifier::new(&s));
884 let col_aliases: Vec<Identifier> = lat
885 .column_aliases
886 .iter()
887 .map(|s| Identifier::new(s))
888 .collect();
889 (alias, col_aliases, *lat.this)
890 } else {
891 (None, Vec::new(), join.this)
892 }
893 } else {
894 (None, Vec::new(), join.this)
895 };
896
897 let (alias_name, column_aliases, unnest_func) = extract_unnest_info(join_expr);
898
899 let final_alias = lateral_alias.or(alias_name);
901 let final_col_aliases = if !lateral_col_aliases.is_empty() {
902 lateral_col_aliases
903 } else {
904 column_aliases
905 };
906
907 let table_alias = final_alias.or_else(|| Some(Identifier::new("unnest")));
909 let col_aliases = if final_col_aliases.is_empty() {
910 vec![Identifier::new("unnest")]
911 } else {
912 final_col_aliases
913 };
914
915 let udtf = make_udtf_expr(&unnest_func);
916 select.lateral_views.push(LateralView {
917 this: udtf,
918 table_alias,
919 column_aliases: col_aliases,
920 outer: false,
921 });
922 } else {
923 remaining_joins.push(join);
924 }
925 } else {
926 remaining_joins.push(join);
927 }
928 }
929 select.joins = remaining_joins;
930
931 Ok(Expression::Select(select))
932}
933
934fn is_unnest_expr(expr: &Expression) -> bool {
936 match expr {
937 Expression::Unnest(_) => true,
938 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
939 _ => false,
940 }
941}
942
943fn check_join_unnest(expr: &Expression) -> (bool, bool) {
945 match expr {
946 Expression::Unnest(_) => (true, false),
947 Expression::Alias(a) => {
948 if matches!(a.this, Expression::Unnest(_)) {
949 (true, false)
950 } else {
951 (false, false)
952 }
953 }
954 Expression::Lateral(lat) => match &*lat.this {
955 Expression::Unnest(_) => (true, true),
956 Expression::Alias(a) => {
957 if matches!(a.this, Expression::Unnest(_)) {
958 (true, true)
959 } else {
960 (false, true)
961 }
962 }
963 _ => (false, true),
964 },
965 _ => (false, false),
966 }
967}
968
969fn replace_from_unnest(from_item: Expression) -> Expression {
971 match from_item {
972 Expression::Alias(mut a) => {
973 if let Expression::Unnest(unnest) = a.this {
974 a.this = make_udtf_expr(&unnest);
975 }
976 Expression::Alias(a)
977 }
978 Expression::Unnest(unnest) => make_udtf_expr(&unnest),
979 other => other,
980 }
981}
982
983fn extract_unnest_info(expr: Expression) -> (Option<Identifier>, Vec<Identifier>, UnnestFunc) {
985 match expr {
986 Expression::Alias(a) => {
987 if let Expression::Unnest(unnest) = a.this {
988 (Some(a.alias), a.column_aliases, *unnest)
989 } else {
990 (
992 Some(a.alias),
993 a.column_aliases,
994 UnnestFunc {
995 this: a.this,
996 expressions: Vec::new(),
997 with_ordinality: false,
998 alias: None,
999 offset_alias: None,
1000 inferred_type: None,
1001 },
1002 )
1003 }
1004 }
1005 Expression::Unnest(unnest) => {
1006 let alias = unnest.alias.clone();
1007 (alias, Vec::new(), *unnest)
1008 }
1009 _ => (
1010 None,
1011 Vec::new(),
1012 UnnestFunc {
1013 this: expr,
1014 expressions: Vec::new(),
1015 with_ordinality: false,
1016 alias: None,
1017 offset_alias: None,
1018 inferred_type: None,
1019 },
1020 ),
1021 }
1022}
1023
1024pub fn explode_to_unnest(expr: Expression) -> Result<Expression> {
1026 match expr {
1027 Expression::Explode(explode) => Ok(Expression::Unnest(Box::new(UnnestFunc {
1028 this: explode.this,
1029 expressions: Vec::new(),
1030 with_ordinality: false,
1031 alias: None,
1032 offset_alias: None,
1033 inferred_type: None,
1034 }))),
1035 _ => Ok(expr),
1036 }
1037}
1038
1039pub fn replace_bool_with_int(expr: Expression) -> Result<Expression> {
1043 match expr {
1044 Expression::Boolean(b) => {
1045 let value = if b.value { "1" } else { "0" };
1046 Ok(Expression::Literal(Box::new(Literal::Number(
1047 value.to_string(),
1048 ))))
1049 }
1050 _ => Ok(expr),
1051 }
1052}
1053
1054pub fn replace_int_with_bool(expr: Expression) -> Result<Expression> {
1058 match expr {
1059 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(n) if n == "1" || n == "0") =>
1060 {
1061 let Literal::Number(n) = lit.as_ref() else {
1062 unreachable!()
1063 };
1064 Ok(Expression::Boolean(BooleanLiteral { value: n == "1" }))
1065 }
1066 _ => Ok(expr),
1067 }
1068}
1069
1070pub fn remove_precision_parameterized_types(expr: Expression) -> Result<Expression> {
1075 Ok(strip_type_params_recursive(expr))
1076}
1077
1078fn strip_type_params_recursive(expr: Expression) -> Expression {
1080 match expr {
1081 Expression::Cast(mut cast) => {
1083 cast.to = strip_data_type_params(cast.to);
1084 cast.this = strip_type_params_recursive(cast.this);
1086 Expression::Cast(cast)
1087 }
1088 Expression::TryCast(mut try_cast) => {
1090 try_cast.to = strip_data_type_params(try_cast.to);
1091 try_cast.this = strip_type_params_recursive(try_cast.this);
1092 Expression::TryCast(try_cast)
1093 }
1094 Expression::SafeCast(mut safe_cast) => {
1096 safe_cast.to = strip_data_type_params(safe_cast.to);
1097 safe_cast.this = strip_type_params_recursive(safe_cast.this);
1098 Expression::SafeCast(safe_cast)
1099 }
1100 _ => expr,
1103 }
1104}
1105
1106fn strip_data_type_params(dt: DataType) -> DataType {
1108 match dt {
1109 DataType::Decimal { .. } => DataType::Decimal {
1111 precision: None,
1112 scale: None,
1113 },
1114 DataType::TinyInt { .. } => DataType::TinyInt { length: None },
1115 DataType::SmallInt { .. } => DataType::SmallInt { length: None },
1116 DataType::Int { .. } => DataType::Int {
1117 length: None,
1118 integer_spelling: false,
1119 },
1120 DataType::BigInt { .. } => DataType::BigInt { length: None },
1121
1122 DataType::Char { .. } => DataType::Char { length: None },
1124 DataType::VarChar { .. } => DataType::VarChar {
1125 length: None,
1126 parenthesized_length: false,
1127 },
1128
1129 DataType::Binary { .. } => DataType::Binary { length: None },
1131 DataType::VarBinary { .. } => DataType::VarBinary { length: None },
1132
1133 DataType::Bit { .. } => DataType::Bit { length: None },
1135 DataType::VarBit { .. } => DataType::VarBit { length: None },
1136
1137 DataType::Time { .. } => DataType::Time {
1139 precision: None,
1140 timezone: false,
1141 },
1142 DataType::Timestamp { timezone, .. } => DataType::Timestamp {
1143 precision: None,
1144 timezone,
1145 },
1146
1147 DataType::Array {
1149 element_type,
1150 dimension,
1151 } => DataType::Array {
1152 element_type: Box::new(strip_data_type_params(*element_type)),
1153 dimension,
1154 },
1155
1156 DataType::Map {
1158 key_type,
1159 value_type,
1160 } => DataType::Map {
1161 key_type: Box::new(strip_data_type_params(*key_type)),
1162 value_type: Box::new(strip_data_type_params(*value_type)),
1163 },
1164
1165 DataType::Struct { fields, nested } => DataType::Struct {
1167 fields: fields
1168 .into_iter()
1169 .map(|f| {
1170 StructField::with_options(
1171 f.name,
1172 strip_data_type_params(f.data_type),
1173 f.options,
1174 )
1175 })
1176 .collect(),
1177 nested,
1178 },
1179
1180 DataType::Vector { element_type, .. } => DataType::Vector {
1182 element_type: element_type.map(|et| Box::new(strip_data_type_params(*et))),
1183 dimension: None,
1184 },
1185
1186 DataType::Object { fields, modifier } => DataType::Object {
1188 fields: fields
1189 .into_iter()
1190 .map(|(name, ty, not_null)| (name, strip_data_type_params(ty), not_null))
1191 .collect(),
1192 modifier,
1193 },
1194
1195 other => other,
1197 }
1198}
1199
1200pub fn eliminate_qualify(expr: Expression) -> Result<Expression> {
1215 match expr {
1216 Expression::Select(mut select) => {
1217 if let Some(qualify) = select.qualify.take() {
1218 let qualify_filter = qualify.this;
1225 let window_alias_name = "_w".to_string();
1226 let window_alias_ident = Identifier::new(window_alias_name.clone());
1227
1228 let (window_expr, outer_where) =
1231 extract_window_from_condition(qualify_filter.clone(), &window_alias_ident);
1232
1233 if let Some(win_expr) = window_expr {
1234 let window_alias_expr =
1236 Expression::Alias(Box::new(crate::expressions::Alias {
1237 this: win_expr,
1238 alias: window_alias_ident.clone(),
1239 column_aliases: vec![],
1240 alias_explicit_as: false,
1241 alias_keyword: None,
1242 pre_alias_comments: vec![],
1243 trailing_comments: vec![],
1244 inferred_type: None,
1245 }));
1246
1247 let outer_exprs: Vec<Expression> = select
1251 .expressions
1252 .iter()
1253 .map(|expr| {
1254 if let Expression::Alias(a) = expr {
1255 Expression::Column(Box::new(crate::expressions::Column {
1257 name: a.alias.clone(),
1258 table: None,
1259 join_mark: false,
1260 trailing_comments: vec![],
1261 span: None,
1262 inferred_type: None,
1263 }))
1264 } else {
1265 expr.clone()
1266 }
1267 })
1268 .collect();
1269 select.expressions.push(window_alias_expr);
1270
1271 let inner_select = Expression::Select(select);
1273 let subquery = Subquery {
1274 this: inner_select,
1275 alias: Some(Identifier::new("_t".to_string())),
1276 column_aliases: vec![],
1277 alias_explicit_as: false,
1278 alias_keyword: None,
1279 order_by: None,
1280 limit: None,
1281 offset: None,
1282 distribute_by: None,
1283 sort_by: None,
1284 cluster_by: None,
1285 lateral: false,
1286 modifiers_inside: false,
1287 trailing_comments: vec![],
1288 inferred_type: None,
1289 };
1290
1291 let outer_select = Select {
1293 expressions: outer_exprs,
1294 from: Some(From {
1295 expressions: vec![Expression::Subquery(Box::new(subquery))],
1296 }),
1297 where_clause: Some(Where { this: outer_where }),
1298 ..Select::new()
1299 };
1300
1301 return Ok(Expression::Select(Box::new(outer_select)));
1302 } else {
1303 let qualify_alias = Expression::Alias(Box::new(crate::expressions::Alias {
1305 this: qualify_filter.clone(),
1306 alias: window_alias_ident.clone(),
1307 column_aliases: vec![],
1308 alias_explicit_as: false,
1309 alias_keyword: None,
1310 pre_alias_comments: vec![],
1311 trailing_comments: vec![],
1312 inferred_type: None,
1313 }));
1314
1315 let original_exprs = select.expressions.clone();
1316 select.expressions.push(qualify_alias);
1317
1318 let inner_select = Expression::Select(select);
1319 let subquery = Subquery {
1320 this: inner_select,
1321 alias: Some(Identifier::new("_t".to_string())),
1322 column_aliases: vec![],
1323 alias_explicit_as: false,
1324 alias_keyword: None,
1325 order_by: None,
1326 limit: None,
1327 offset: None,
1328 distribute_by: None,
1329 sort_by: None,
1330 cluster_by: None,
1331 lateral: false,
1332 modifiers_inside: false,
1333 trailing_comments: vec![],
1334 inferred_type: None,
1335 };
1336
1337 let outer_select = Select {
1338 expressions: original_exprs,
1339 from: Some(From {
1340 expressions: vec![Expression::Subquery(Box::new(subquery))],
1341 }),
1342 where_clause: Some(Where {
1343 this: Expression::Column(Box::new(crate::expressions::Column {
1344 name: window_alias_ident,
1345 table: None,
1346 join_mark: false,
1347 trailing_comments: vec![],
1348 span: None,
1349 inferred_type: None,
1350 })),
1351 }),
1352 ..Select::new()
1353 };
1354
1355 return Ok(Expression::Select(Box::new(outer_select)));
1356 }
1357 }
1358 Ok(Expression::Select(select))
1359 }
1360 other => Ok(other),
1361 }
1362}
1363
1364fn extract_window_from_condition(
1368 condition: Expression,
1369 alias: &Identifier,
1370) -> (Option<Expression>, Expression) {
1371 let alias_col = Expression::Column(Box::new(crate::expressions::Column {
1372 name: alias.clone(),
1373 table: None,
1374 join_mark: false,
1375 trailing_comments: vec![],
1376 span: None,
1377 inferred_type: None,
1378 }));
1379
1380 match condition {
1382 Expression::Eq(ref op) => {
1384 if is_window_expr(&op.left) {
1385 (
1386 Some(op.left.clone()),
1387 Expression::Eq(Box::new(BinaryOp {
1388 left: alias_col,
1389 right: op.right.clone(),
1390 ..(**op).clone()
1391 })),
1392 )
1393 } else if is_window_expr(&op.right) {
1394 (
1395 Some(op.right.clone()),
1396 Expression::Eq(Box::new(BinaryOp {
1397 left: op.left.clone(),
1398 right: alias_col,
1399 ..(**op).clone()
1400 })),
1401 )
1402 } else {
1403 (None, condition)
1404 }
1405 }
1406 Expression::Neq(ref op) => {
1407 if is_window_expr(&op.left) {
1408 (
1409 Some(op.left.clone()),
1410 Expression::Neq(Box::new(BinaryOp {
1411 left: alias_col,
1412 right: op.right.clone(),
1413 ..(**op).clone()
1414 })),
1415 )
1416 } else if is_window_expr(&op.right) {
1417 (
1418 Some(op.right.clone()),
1419 Expression::Neq(Box::new(BinaryOp {
1420 left: op.left.clone(),
1421 right: alias_col,
1422 ..(**op).clone()
1423 })),
1424 )
1425 } else {
1426 (None, condition)
1427 }
1428 }
1429 Expression::Lt(ref op) => {
1430 if is_window_expr(&op.left) {
1431 (
1432 Some(op.left.clone()),
1433 Expression::Lt(Box::new(BinaryOp {
1434 left: alias_col,
1435 right: op.right.clone(),
1436 ..(**op).clone()
1437 })),
1438 )
1439 } else if is_window_expr(&op.right) {
1440 (
1441 Some(op.right.clone()),
1442 Expression::Lt(Box::new(BinaryOp {
1443 left: op.left.clone(),
1444 right: alias_col,
1445 ..(**op).clone()
1446 })),
1447 )
1448 } else {
1449 (None, condition)
1450 }
1451 }
1452 Expression::Lte(ref op) => {
1453 if is_window_expr(&op.left) {
1454 (
1455 Some(op.left.clone()),
1456 Expression::Lte(Box::new(BinaryOp {
1457 left: alias_col,
1458 right: op.right.clone(),
1459 ..(**op).clone()
1460 })),
1461 )
1462 } else if is_window_expr(&op.right) {
1463 (
1464 Some(op.right.clone()),
1465 Expression::Lte(Box::new(BinaryOp {
1466 left: op.left.clone(),
1467 right: alias_col,
1468 ..(**op).clone()
1469 })),
1470 )
1471 } else {
1472 (None, condition)
1473 }
1474 }
1475 Expression::Gt(ref op) => {
1476 if is_window_expr(&op.left) {
1477 (
1478 Some(op.left.clone()),
1479 Expression::Gt(Box::new(BinaryOp {
1480 left: alias_col,
1481 right: op.right.clone(),
1482 ..(**op).clone()
1483 })),
1484 )
1485 } else if is_window_expr(&op.right) {
1486 (
1487 Some(op.right.clone()),
1488 Expression::Gt(Box::new(BinaryOp {
1489 left: op.left.clone(),
1490 right: alias_col,
1491 ..(**op).clone()
1492 })),
1493 )
1494 } else {
1495 (None, condition)
1496 }
1497 }
1498 Expression::Gte(ref op) => {
1499 if is_window_expr(&op.left) {
1500 (
1501 Some(op.left.clone()),
1502 Expression::Gte(Box::new(BinaryOp {
1503 left: alias_col,
1504 right: op.right.clone(),
1505 ..(**op).clone()
1506 })),
1507 )
1508 } else if is_window_expr(&op.right) {
1509 (
1510 Some(op.right.clone()),
1511 Expression::Gte(Box::new(BinaryOp {
1512 left: op.left.clone(),
1513 right: alias_col,
1514 ..(**op).clone()
1515 })),
1516 )
1517 } else {
1518 (None, condition)
1519 }
1520 }
1521 _ if is_window_expr(&condition) => (Some(condition), alias_col),
1523 _ => (None, condition),
1525 }
1526}
1527
1528fn is_window_expr(expr: &Expression) -> bool {
1530 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
1531}
1532
1533pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
1552 eliminate_distinct_on_for_dialect(expr, None, None)
1553}
1554
1555pub fn strip_cte_materialization(expr: Expression) -> Result<Expression> {
1558 transform_recursive(expr, &strip_cte_materialization_single)
1559}
1560
1561fn strip_cte_materialization_single(expr: Expression) -> Result<Expression> {
1562 Ok(match expr {
1563 Expression::Select(mut select) => {
1564 strip_with_cte_materialization(&mut select.with);
1565 Expression::Select(select)
1566 }
1567 Expression::Union(mut union) => {
1568 strip_with_cte_materialization(&mut union.with);
1569 Expression::Union(union)
1570 }
1571 Expression::Intersect(mut intersect) => {
1572 strip_with_cte_materialization(&mut intersect.with);
1573 Expression::Intersect(intersect)
1574 }
1575 Expression::Except(mut except) => {
1576 strip_with_cte_materialization(&mut except.with);
1577 Expression::Except(except)
1578 }
1579 Expression::Pivot(mut pivot) => {
1580 strip_with_cte_materialization(&mut pivot.with);
1581 Expression::Pivot(pivot)
1582 }
1583 Expression::Insert(mut insert) => {
1584 strip_with_cte_materialization(&mut insert.with);
1585 Expression::Insert(insert)
1586 }
1587 Expression::Update(mut update) => {
1588 strip_with_cte_materialization(&mut update.with);
1589 Expression::Update(update)
1590 }
1591 Expression::Delete(mut delete) => {
1592 strip_with_cte_materialization(&mut delete.with);
1593 Expression::Delete(delete)
1594 }
1595 Expression::CreateTable(mut create_table) => {
1596 strip_with_cte_materialization(&mut create_table.with_cte);
1597 Expression::CreateTable(create_table)
1598 }
1599 Expression::With(mut with) => {
1600 strip_cte_materialization_in_with(&mut with);
1601 Expression::With(with)
1602 }
1603 Expression::Cte(mut cte) => {
1604 cte.materialized = None;
1605 Expression::Cte(cte)
1606 }
1607 _ => expr,
1608 })
1609}
1610
1611fn strip_with_cte_materialization(with: &mut Option<With>) {
1612 if let Some(with) = with {
1613 strip_cte_materialization_in_with(with);
1614 }
1615}
1616
1617fn strip_cte_materialization_in_with(with: &mut With) {
1618 for cte in &mut with.ctes {
1619 cte.materialized = None;
1620 }
1621}
1622
1623#[derive(Clone, Copy)]
1624enum DistinctOnNullsMode {
1625 None,
1626 NullsFirst,
1627 CaseExpr,
1628}
1629
1630pub fn eliminate_distinct_on_for_dialect(
1635 expr: Expression,
1636 target: Option<DialectType>,
1637 source: Option<DialectType>,
1638) -> Result<Expression> {
1639 if matches!(
1641 target,
1642 Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)
1643 ) {
1644 return Ok(expr);
1645 }
1646
1647 let nulls_mode = match target {
1652 Some(DialectType::MySQL)
1653 | Some(DialectType::SingleStore)
1654 | Some(DialectType::TSQL)
1655 | Some(DialectType::Fabric) => DistinctOnNullsMode::CaseExpr,
1656 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => {
1657 DistinctOnNullsMode::None
1658 }
1659 Some(DialectType::StarRocks) => {
1660 if matches!(source, Some(DialectType::Redshift)) {
1661 DistinctOnNullsMode::CaseExpr
1662 } else {
1663 DistinctOnNullsMode::None
1664 }
1665 }
1666 _ => DistinctOnNullsMode::NullsFirst,
1668 };
1669
1670 transform_recursive(expr, &|expr| eliminate_distinct_on_select(expr, nulls_mode))
1671}
1672
1673fn eliminate_distinct_on_select(
1674 expr: Expression,
1675 nulls_mode: DistinctOnNullsMode,
1676) -> Result<Expression> {
1677 use crate::expressions::Case;
1678
1679 match expr {
1680 Expression::Select(mut select) => {
1681 if let Some(distinct_cols) = select.distinct_on.take() {
1682 if !distinct_cols.is_empty() {
1683 let row_number_alias = Identifier::new("_row_number".to_string());
1685
1686 let order_exprs = if let Some(ref order_by) = select.order_by {
1688 let mut exprs = order_by.expressions.clone();
1689 match nulls_mode {
1691 DistinctOnNullsMode::NullsFirst => {
1692 for ord in &mut exprs {
1693 if ord.desc && ord.nulls_first.is_none() {
1694 ord.nulls_first = Some(true);
1695 }
1696 }
1697 }
1698 DistinctOnNullsMode::CaseExpr => {
1699 let mut new_exprs = Vec::new();
1702 for ord in &exprs {
1703 if ord.desc && ord.nulls_first.is_none() {
1704 let null_check = Expression::Case(Box::new(Case {
1706 operand: None,
1707 whens: vec![(
1708 Expression::IsNull(Box::new(
1709 crate::expressions::IsNull {
1710 this: ord.this.clone(),
1711 not: false,
1712 postfix_form: false,
1713 },
1714 )),
1715 Expression::Literal(Box::new(Literal::Number(
1716 "1".to_string(),
1717 ))),
1718 )],
1719 else_: Some(Expression::Literal(Box::new(
1720 Literal::Number("0".to_string()),
1721 ))),
1722 comments: Vec::new(),
1723 inferred_type: None,
1724 }));
1725 new_exprs.push(crate::expressions::Ordered {
1726 this: null_check,
1727 desc: true,
1728 nulls_first: None,
1729 explicit_asc: false,
1730 with_fill: None,
1731 });
1732 }
1733 new_exprs.push(ord.clone());
1734 }
1735 exprs = new_exprs;
1736 }
1737 DistinctOnNullsMode::None => {}
1738 }
1739 exprs
1740 } else {
1741 distinct_cols
1742 .iter()
1743 .map(|e| crate::expressions::Ordered {
1744 this: e.clone(),
1745 desc: false,
1746 nulls_first: None,
1747 explicit_asc: false,
1748 with_fill: None,
1749 })
1750 .collect()
1751 };
1752
1753 let row_number_func =
1755 Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
1756 this: Expression::RowNumber(crate::expressions::RowNumber),
1757 over: Over {
1758 partition_by: distinct_cols,
1759 order_by: order_exprs,
1760 frame: None,
1761 window_name: None,
1762 alias: None,
1763 },
1764 keep: None,
1765 inferred_type: None,
1766 }));
1767
1768 let mut inner_aliased_exprs = Vec::new();
1772 let mut outer_select_exprs = Vec::new();
1773 for orig_expr in &select.expressions {
1774 match orig_expr {
1775 Expression::Alias(alias) => {
1776 inner_aliased_exprs.push(orig_expr.clone());
1778 outer_select_exprs.push(Expression::Column(Box::new(
1779 crate::expressions::Column {
1780 name: alias.alias.clone(),
1781 table: None,
1782 join_mark: false,
1783 trailing_comments: vec![],
1784 span: None,
1785 inferred_type: None,
1786 },
1787 )));
1788 }
1789 Expression::Column(col) => {
1790 inner_aliased_exprs.push(Expression::Alias(Box::new(
1792 crate::expressions::Alias {
1793 this: orig_expr.clone(),
1794 alias: col.name.clone(),
1795 column_aliases: vec![],
1796 alias_explicit_as: false,
1797 alias_keyword: None,
1798 pre_alias_comments: vec![],
1799 trailing_comments: vec![],
1800 inferred_type: None,
1801 },
1802 )));
1803 outer_select_exprs.push(Expression::Column(Box::new(
1804 crate::expressions::Column {
1805 name: col.name.clone(),
1806 table: None,
1807 join_mark: false,
1808 trailing_comments: vec![],
1809 span: None,
1810 inferred_type: None,
1811 },
1812 )));
1813 }
1814 _ => {
1815 inner_aliased_exprs.push(orig_expr.clone());
1817 outer_select_exprs.push(orig_expr.clone());
1818 }
1819 }
1820 }
1821
1822 let row_number_alias_expr =
1824 Expression::Alias(Box::new(crate::expressions::Alias {
1825 this: row_number_func,
1826 alias: row_number_alias.clone(),
1827 column_aliases: vec![],
1828 alias_explicit_as: false,
1829 alias_keyword: None,
1830 pre_alias_comments: vec![],
1831 trailing_comments: vec![],
1832 inferred_type: None,
1833 }));
1834 inner_aliased_exprs.push(row_number_alias_expr);
1835
1836 select.expressions = inner_aliased_exprs;
1838
1839 let _inner_order_by = select.order_by.take();
1841
1842 select.distinct = false;
1844
1845 let inner_select = Expression::Select(select);
1847 let subquery = Subquery {
1848 this: inner_select,
1849 alias: Some(Identifier::new("_t".to_string())),
1850 column_aliases: vec![],
1851 alias_explicit_as: false,
1852 alias_keyword: None,
1853 order_by: None,
1854 limit: None,
1855 offset: None,
1856 distribute_by: None,
1857 sort_by: None,
1858 cluster_by: None,
1859 lateral: false,
1860 modifiers_inside: false,
1861 trailing_comments: vec![],
1862 inferred_type: None,
1863 };
1864
1865 let outer_select = Select {
1868 expressions: outer_select_exprs,
1869 from: Some(From {
1870 expressions: vec![Expression::Subquery(Box::new(subquery))],
1871 }),
1872 where_clause: Some(Where {
1873 this: Expression::Eq(Box::new(BinaryOp {
1874 left: Expression::Column(Box::new(crate::expressions::Column {
1875 name: row_number_alias,
1876 table: None,
1877 join_mark: false,
1878 trailing_comments: vec![],
1879 span: None,
1880 inferred_type: None,
1881 })),
1882 right: Expression::Literal(Box::new(Literal::Number(
1883 "1".to_string(),
1884 ))),
1885 left_comments: vec![],
1886 operator_comments: vec![],
1887 trailing_comments: vec![],
1888 inferred_type: None,
1889 })),
1890 }),
1891 ..Select::new()
1892 };
1893
1894 return Ok(Expression::Select(Box::new(outer_select)));
1895 }
1896 }
1897 Ok(Expression::Select(select))
1898 }
1899 other => Ok(other),
1900 }
1901}
1902
1903pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
1911 match expr {
1912 Expression::Select(mut select) => {
1913 let mut new_joins = Vec::new();
1914 let mut extra_where_conditions = Vec::new();
1915
1916 for join in select.joins.drain(..) {
1917 match join.kind {
1918 JoinKind::Semi | JoinKind::LeftSemi => {
1919 if let Some(on_condition) = join.on {
1920 let subquery_select = Select {
1922 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1923 "1".to_string(),
1924 )))],
1925 from: Some(From {
1926 expressions: vec![join.this],
1927 }),
1928 where_clause: Some(Where { this: on_condition }),
1929 ..Select::new()
1930 };
1931
1932 let exists = Expression::Exists(Box::new(Exists {
1933 this: Expression::Subquery(Box::new(Subquery {
1934 this: Expression::Select(Box::new(subquery_select)),
1935 alias: None,
1936 column_aliases: vec![],
1937 alias_explicit_as: false,
1938 alias_keyword: None,
1939 order_by: None,
1940 limit: None,
1941 offset: None,
1942 distribute_by: None,
1943 sort_by: None,
1944 cluster_by: None,
1945 lateral: false,
1946 modifiers_inside: false,
1947 trailing_comments: vec![],
1948 inferred_type: None,
1949 })),
1950 not: false,
1951 }));
1952
1953 extra_where_conditions.push(exists);
1954 }
1955 }
1956 JoinKind::Anti | JoinKind::LeftAnti => {
1957 if let Some(on_condition) = join.on {
1958 let subquery_select = Select {
1960 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1961 "1".to_string(),
1962 )))],
1963 from: Some(From {
1964 expressions: vec![join.this],
1965 }),
1966 where_clause: Some(Where { this: on_condition }),
1967 ..Select::new()
1968 };
1969
1970 let not_exists = Expression::Exists(Box::new(Exists {
1972 this: Expression::Subquery(Box::new(Subquery {
1973 this: Expression::Select(Box::new(subquery_select)),
1974 alias: None,
1975 column_aliases: vec![],
1976 alias_explicit_as: false,
1977 alias_keyword: None,
1978 order_by: None,
1979 limit: None,
1980 offset: None,
1981 distribute_by: None,
1982 sort_by: None,
1983 cluster_by: None,
1984 lateral: false,
1985 modifiers_inside: false,
1986 trailing_comments: vec![],
1987 inferred_type: None,
1988 })),
1989 not: true,
1990 }));
1991
1992 extra_where_conditions.push(not_exists);
1993 }
1994 }
1995 _ => {
1996 new_joins.push(join);
1998 }
1999 }
2000 }
2001
2002 select.joins = new_joins;
2003
2004 if !extra_where_conditions.is_empty() {
2006 let combined = extra_where_conditions
2007 .into_iter()
2008 .reduce(|acc, cond| {
2009 Expression::And(Box::new(BinaryOp {
2010 left: acc,
2011 right: cond,
2012 left_comments: vec![],
2013 operator_comments: vec![],
2014 trailing_comments: vec![],
2015 inferred_type: None,
2016 }))
2017 })
2018 .unwrap();
2019
2020 select.where_clause = match select.where_clause {
2021 Some(Where { this: existing }) => Some(Where {
2022 this: Expression::And(Box::new(BinaryOp {
2023 left: existing,
2024 right: combined,
2025 left_comments: vec![],
2026 operator_comments: vec![],
2027 trailing_comments: vec![],
2028 inferred_type: None,
2029 })),
2030 }),
2031 None => Some(Where { this: combined }),
2032 };
2033 }
2034
2035 Ok(Expression::Select(select))
2036 }
2037 other => Ok(other),
2038 }
2039}
2040
2041pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
2059 match expr {
2060 Expression::Select(mut select) => {
2061 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
2063
2064 if let Some(idx) = full_outer_join_idx {
2065 let full_join_count = select
2067 .joins
2068 .iter()
2069 .filter(|j| j.kind == JoinKind::Full)
2070 .count();
2071 if full_join_count != 1 {
2072 return Ok(Expression::Select(select));
2073 }
2074
2075 let mut right_select = select.clone();
2077
2078 let full_join = &select.joins[idx];
2080 let join_condition = full_join.on.clone();
2081
2082 select.joins[idx].kind = JoinKind::Left;
2084
2085 right_select.joins[idx].kind = JoinKind::Right;
2087
2088 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
2090 if !from.expressions.is_empty() {
2091 let anti_subquery = Expression::Select(Box::new(Select {
2092 expressions: vec![Expression::Literal(Box::new(Literal::Number(
2093 "1".to_string(),
2094 )))],
2095 from: Some(from.clone()),
2096 where_clause: Some(Where {
2097 this: join_cond.clone(),
2098 }),
2099 ..Select::new()
2100 }));
2101
2102 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
2103 inferred_type: None,
2104 this: Expression::Exists(Box::new(Exists {
2105 this: Expression::Subquery(Box::new(Subquery {
2106 this: anti_subquery,
2107 alias: None,
2108 column_aliases: vec![],
2109 alias_explicit_as: false,
2110 alias_keyword: None,
2111 order_by: None,
2112 limit: None,
2113 offset: None,
2114 distribute_by: None,
2115 sort_by: None,
2116 cluster_by: None,
2117 lateral: false,
2118 modifiers_inside: false,
2119 trailing_comments: vec![],
2120 inferred_type: None,
2121 })),
2122 not: false,
2123 })),
2124 }));
2125
2126 right_select.where_clause = Some(Where {
2128 this: match right_select.where_clause {
2129 Some(w) => Expression::And(Box::new(BinaryOp {
2130 left: w.this,
2131 right: not_exists,
2132 left_comments: vec![],
2133 operator_comments: vec![],
2134 trailing_comments: vec![],
2135 inferred_type: None,
2136 })),
2137 None => not_exists,
2138 },
2139 });
2140 }
2141 }
2142
2143 right_select.with = None;
2145
2146 let order_by = select.order_by.take();
2148
2149 let union = crate::expressions::Union {
2151 left: Expression::Select(select),
2152 right: Expression::Select(right_select),
2153 all: true, distinct: false,
2155 with: None,
2156 order_by,
2157 limit: None,
2158 offset: None,
2159 distribute_by: None,
2160 sort_by: None,
2161 cluster_by: None,
2162 by_name: false,
2163 side: None,
2164 kind: None,
2165 corresponding: false,
2166 strict: false,
2167 on_columns: Vec::new(),
2168 };
2169
2170 return Ok(Expression::Union(Box::new(union)));
2171 }
2172
2173 Ok(Expression::Select(select))
2174 }
2175 other => Ok(other),
2176 }
2177}
2178
2179pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
2192 match expr {
2193 Expression::Select(mut select) => {
2194 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
2196 let mut has_recursive = false;
2197
2198 collect_nested_ctes(
2199 &Expression::Select(select.clone()),
2200 &mut collected_ctes,
2201 &mut has_recursive,
2202 true,
2203 );
2204
2205 let mut cte_body_collected: Vec<(String, Vec<crate::expressions::Cte>)> = Vec::new();
2208 if let Some(ref with) = select.with {
2209 for cte in &with.ctes {
2210 let mut body_ctes: Vec<crate::expressions::Cte> = Vec::new();
2211 collect_ctes_from_cte_body(&cte.this, &mut body_ctes, &mut has_recursive);
2212 if !body_ctes.is_empty() {
2213 cte_body_collected.push((cte.alias.name.clone(), body_ctes));
2214 }
2215 }
2216 }
2217
2218 let has_subquery_ctes = !collected_ctes.is_empty();
2219 let has_body_ctes = !cte_body_collected.is_empty();
2220
2221 if has_subquery_ctes || has_body_ctes {
2222 strip_nested_with_clauses(&mut select, true);
2224
2225 if has_body_ctes {
2227 if let Some(ref mut with) = select.with {
2228 for cte in with.ctes.iter_mut() {
2229 strip_with_from_cte_body(&mut cte.this);
2230 }
2231 }
2232 }
2233
2234 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
2235 ctes: Vec::new(),
2236 recursive: false,
2237 leading_comments: vec![],
2238 search: None,
2239 });
2240
2241 if has_recursive {
2242 top_with.recursive = true;
2243 }
2244
2245 if has_body_ctes {
2247 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2248 for mut cte in top_with.ctes.drain(..) {
2249 if let Some(pos) = cte_body_collected
2251 .iter()
2252 .position(|(name, _)| *name == cte.alias.name)
2253 {
2254 let (_, mut nested) = cte_body_collected.remove(pos);
2255 for nested_cte in nested.iter_mut() {
2257 strip_with_from_cte_body(&mut nested_cte.this);
2258 }
2259 new_ctes.extend(nested);
2260 }
2261 strip_with_from_cte_body(&mut cte.this);
2263 new_ctes.push(cte);
2264 }
2265 top_with.ctes = new_ctes;
2266 }
2267
2268 top_with.ctes.extend(collected_ctes);
2270 }
2271
2272 Ok(Expression::Select(select))
2273 }
2274 other => Ok(other),
2275 }
2276}
2277
2278fn collect_ctes_from_cte_body(
2280 expr: &Expression,
2281 collected: &mut Vec<crate::expressions::Cte>,
2282 has_recursive: &mut bool,
2283) {
2284 if let Expression::Select(select) = expr {
2285 if let Some(ref with) = select.with {
2286 if with.recursive {
2287 *has_recursive = true;
2288 }
2289 for cte in &with.ctes {
2290 collect_ctes_from_cte_body(&cte.this, collected, has_recursive);
2292 collected.push(cte.clone());
2294 }
2295 }
2296 }
2297}
2298
2299fn strip_with_from_cte_body(expr: &mut Expression) {
2301 if let Expression::Select(ref mut select) = expr {
2302 select.with = None;
2303 }
2304}
2305
2306fn strip_nested_with_clauses(select: &mut Select, _is_top_level: bool) {
2308 if let Some(ref mut from) = select.from {
2310 for expr in from.expressions.iter_mut() {
2311 strip_with_from_expr(expr);
2312 }
2313 }
2314 for join in select.joins.iter_mut() {
2316 strip_with_from_expr(&mut join.this);
2317 }
2318 for expr in select.expressions.iter_mut() {
2320 strip_with_from_expr(expr);
2321 }
2322 if let Some(ref mut w) = select.where_clause {
2324 strip_with_from_expr(&mut w.this);
2325 }
2326}
2327
2328fn strip_with_from_expr(expr: &mut Expression) {
2329 match expr {
2330 Expression::Subquery(ref mut subquery) => {
2331 strip_with_from_inner_query(&mut subquery.this);
2332 }
2333 Expression::Alias(ref mut alias) => {
2334 strip_with_from_expr(&mut alias.this);
2335 }
2336 Expression::Select(ref mut select) => {
2337 select.with = None;
2339 strip_nested_with_clauses(select, false);
2341 }
2342 _ => {}
2343 }
2344}
2345
2346fn strip_with_from_inner_query(expr: &mut Expression) {
2347 if let Expression::Select(ref mut select) = expr {
2348 select.with = None;
2349 strip_nested_with_clauses(select, false);
2350 }
2351}
2352
2353fn collect_nested_ctes(
2355 expr: &Expression,
2356 collected: &mut Vec<crate::expressions::Cte>,
2357 has_recursive: &mut bool,
2358 is_top_level: bool,
2359) {
2360 match expr {
2361 Expression::Select(select) => {
2362 if !is_top_level {
2364 if let Some(ref with) = select.with {
2365 if with.recursive {
2366 *has_recursive = true;
2367 }
2368 collected.extend(with.ctes.clone());
2369 }
2370 }
2371
2372 if let Some(ref from) = select.from {
2374 for expr in &from.expressions {
2375 collect_nested_ctes(expr, collected, has_recursive, false);
2376 }
2377 }
2378
2379 for join in &select.joins {
2381 collect_nested_ctes(&join.this, collected, has_recursive, false);
2382 }
2383
2384 for sel_expr in &select.expressions {
2386 collect_nested_ctes(sel_expr, collected, has_recursive, false);
2387 }
2388
2389 if let Some(ref where_clause) = select.where_clause {
2391 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
2392 }
2393 }
2394 Expression::Subquery(subquery) => {
2395 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
2397 }
2398 Expression::Alias(alias) => {
2399 collect_nested_ctes(&alias.this, collected, has_recursive, false);
2400 }
2401 _ => {}
2403 }
2404}
2405
2406pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
2422 match expr {
2423 Expression::Select(mut select) => {
2424 if let Some(named_windows) = select.windows.take() {
2425 let window_map: std::collections::HashMap<String, &Over> = named_windows
2427 .iter()
2428 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
2429 .collect();
2430
2431 select.expressions = select
2433 .expressions
2434 .into_iter()
2435 .map(|e| inline_window_refs(e, &window_map))
2436 .collect();
2437 }
2438 Ok(Expression::Select(select))
2439 }
2440 other => Ok(other),
2441 }
2442}
2443
2444fn inline_window_refs(
2446 expr: Expression,
2447 window_map: &std::collections::HashMap<String, &Over>,
2448) -> Expression {
2449 match expr {
2450 Expression::WindowFunction(mut wf) => {
2451 if let Some(ref name) = wf.over.window_name {
2453 let key = name.name.to_lowercase();
2454 if let Some(named_spec) = window_map.get(&key) {
2455 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
2457 wf.over.partition_by = named_spec.partition_by.clone();
2458 }
2459 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
2460 wf.over.order_by = named_spec.order_by.clone();
2461 }
2462 if wf.over.frame.is_none() && named_spec.frame.is_some() {
2463 wf.over.frame = named_spec.frame.clone();
2464 }
2465 wf.over.window_name = None;
2467 }
2468 }
2469 Expression::WindowFunction(wf)
2470 }
2471 Expression::Alias(mut alias) => {
2472 alias.this = inline_window_refs(alias.this, window_map);
2474 Expression::Alias(alias)
2475 }
2476 other => other,
2479 }
2480}
2481
2482pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
2496 match expr {
2497 Expression::Select(mut select) => {
2498 let has_join_marks = select
2500 .where_clause
2501 .as_ref()
2502 .map_or(false, |w| contains_join_mark(&w.this));
2503
2504 if !has_join_marks {
2505 return Ok(Expression::Select(select));
2506 }
2507
2508 let from_tables: Vec<String> = select
2510 .from
2511 .as_ref()
2512 .map(|f| {
2513 f.expressions
2514 .iter()
2515 .filter_map(|e| get_table_name(e))
2516 .collect()
2517 })
2518 .unwrap_or_default();
2519
2520 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
2522 std::collections::HashMap::new();
2523 let mut remaining_conditions: Vec<Expression> = Vec::new();
2524
2525 if let Some(ref where_clause) = select.where_clause {
2526 extract_join_mark_conditions(
2527 &where_clause.this,
2528 &mut join_conditions,
2529 &mut remaining_conditions,
2530 );
2531 }
2532
2533 let mut new_joins = select.joins.clone();
2535 for (table_name, conditions) in join_conditions {
2536 let table_in_from = from_tables.contains(&table_name);
2538
2539 if table_in_from && !conditions.is_empty() {
2540 let combined_condition = conditions.into_iter().reduce(|a, b| {
2542 Expression::And(Box::new(BinaryOp {
2543 left: a,
2544 right: b,
2545 left_comments: vec![],
2546 operator_comments: vec![],
2547 trailing_comments: vec![],
2548 inferred_type: None,
2549 }))
2550 });
2551
2552 if let Some(ref mut from) = select.from {
2554 if let Some(pos) = from
2555 .expressions
2556 .iter()
2557 .position(|e| get_table_name(e).map_or(false, |n| n == table_name))
2558 {
2559 if from.expressions.len() > 1 {
2560 let join_table = from.expressions.remove(pos);
2561 new_joins.push(crate::expressions::Join {
2562 this: join_table,
2563 kind: JoinKind::Left,
2564 on: combined_condition,
2565 using: vec![],
2566 use_inner_keyword: false,
2567 use_outer_keyword: true,
2568 deferred_condition: false,
2569 join_hint: None,
2570 match_condition: None,
2571 pivots: Vec::new(),
2572 comments: Vec::new(),
2573 nesting_group: 0,
2574 directed: false,
2575 });
2576 }
2577 }
2578 }
2579 }
2580 }
2581
2582 select.joins = new_joins;
2583
2584 if remaining_conditions.is_empty() {
2586 select.where_clause = None;
2587 } else {
2588 let combined = remaining_conditions.into_iter().reduce(|a, b| {
2589 Expression::And(Box::new(BinaryOp {
2590 left: a,
2591 right: b,
2592 left_comments: vec![],
2593 operator_comments: vec![],
2594 trailing_comments: vec![],
2595 inferred_type: None,
2596 }))
2597 });
2598 select.where_clause = combined.map(|c| Where { this: c });
2599 }
2600
2601 clear_join_marks(&mut Expression::Select(select.clone()));
2603
2604 Ok(Expression::Select(select))
2605 }
2606 other => Ok(other),
2607 }
2608}
2609
2610fn contains_join_mark(expr: &Expression) -> bool {
2612 match expr {
2613 Expression::Column(col) => col.join_mark,
2614 Expression::And(op) | Expression::Or(op) => {
2615 contains_join_mark(&op.left) || contains_join_mark(&op.right)
2616 }
2617 Expression::Eq(op)
2618 | Expression::Neq(op)
2619 | Expression::Lt(op)
2620 | Expression::Lte(op)
2621 | Expression::Gt(op)
2622 | Expression::Gte(op) => contains_join_mark(&op.left) || contains_join_mark(&op.right),
2623 Expression::Not(op) => contains_join_mark(&op.this),
2624 _ => false,
2625 }
2626}
2627
2628fn get_table_name(expr: &Expression) -> Option<String> {
2630 match expr {
2631 Expression::Table(t) => Some(t.name.name.clone()),
2632 Expression::Alias(a) => Some(a.alias.name.clone()),
2633 _ => None,
2634 }
2635}
2636
2637fn extract_join_mark_conditions(
2639 expr: &Expression,
2640 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
2641 remaining: &mut Vec<Expression>,
2642) {
2643 match expr {
2644 Expression::And(op) => {
2645 extract_join_mark_conditions(&op.left, join_conditions, remaining);
2646 extract_join_mark_conditions(&op.right, join_conditions, remaining);
2647 }
2648 _ => {
2649 if let Some(table) = get_join_mark_table(expr) {
2650 join_conditions
2651 .entry(table)
2652 .or_insert_with(Vec::new)
2653 .push(expr.clone());
2654 } else {
2655 remaining.push(expr.clone());
2656 }
2657 }
2658 }
2659}
2660
2661fn get_join_mark_table(expr: &Expression) -> Option<String> {
2663 match expr {
2664 Expression::Eq(op)
2665 | Expression::Neq(op)
2666 | Expression::Lt(op)
2667 | Expression::Lte(op)
2668 | Expression::Gt(op)
2669 | Expression::Gte(op) => {
2670 if let Expression::Column(col) = &op.left {
2672 if col.join_mark {
2673 return col.table.as_ref().map(|t| t.name.clone());
2674 }
2675 }
2676 if let Expression::Column(col) = &op.right {
2677 if col.join_mark {
2678 return col.table.as_ref().map(|t| t.name.clone());
2679 }
2680 }
2681 None
2682 }
2683 _ => None,
2684 }
2685}
2686
2687fn clear_join_marks(expr: &mut Expression) {
2689 match expr {
2690 Expression::Column(col) => col.join_mark = false,
2691 Expression::Select(select) => {
2692 if let Some(ref mut w) = select.where_clause {
2693 clear_join_marks(&mut w.this);
2694 }
2695 for sel_expr in &mut select.expressions {
2696 clear_join_marks(sel_expr);
2697 }
2698 }
2699 Expression::And(op) | Expression::Or(op) => {
2700 clear_join_marks(&mut op.left);
2701 clear_join_marks(&mut op.right);
2702 }
2703 Expression::Eq(op)
2704 | Expression::Neq(op)
2705 | Expression::Lt(op)
2706 | Expression::Lte(op)
2707 | Expression::Gt(op)
2708 | Expression::Gte(op) => {
2709 clear_join_marks(&mut op.left);
2710 clear_join_marks(&mut op.right);
2711 }
2712 _ => {}
2713 }
2714}
2715
2716pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
2723 match expr {
2724 Expression::Select(mut select) => {
2725 if let Some(ref mut with) = select.with {
2726 if with.recursive {
2727 let mut counter = 0;
2728 for cte in &mut with.ctes {
2729 if cte.columns.is_empty() {
2730 if let Expression::Select(ref cte_select) = cte.this {
2732 let names: Vec<Identifier> = cte_select
2733 .expressions
2734 .iter()
2735 .map(|e| match e {
2736 Expression::Alias(a) => a.alias.clone(),
2737 Expression::Column(c) => c.name.clone(),
2738 _ => {
2739 counter += 1;
2740 Identifier::new(format!("_c_{}", counter))
2741 }
2742 })
2743 .collect();
2744 cte.columns = names;
2745 }
2746 }
2747 }
2748 }
2749 }
2750 Ok(Expression::Select(select))
2751 }
2752 other => Ok(other),
2753 }
2754}
2755
2756pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
2763 match expr {
2764 Expression::Cast(mut cast) => {
2765 if let Expression::Literal(ref lit) = cast.this {
2766 if let Literal::String(ref s) = lit.as_ref() {
2767 if s.to_lowercase() == "epoch" {
2768 if is_temporal_type(&cast.to) {
2769 cast.this = Expression::Literal(Box::new(Literal::String(
2770 "1970-01-01 00:00:00".to_string(),
2771 )));
2772 }
2773 }
2774 }
2775 }
2776 Ok(Expression::Cast(cast))
2777 }
2778 Expression::TryCast(mut try_cast) => {
2779 if let Expression::Literal(ref lit) = try_cast.this {
2780 if let Literal::String(ref s) = lit.as_ref() {
2781 if s.to_lowercase() == "epoch" {
2782 if is_temporal_type(&try_cast.to) {
2783 try_cast.this = Expression::Literal(Box::new(Literal::String(
2784 "1970-01-01 00:00:00".to_string(),
2785 )));
2786 }
2787 }
2788 }
2789 }
2790 Ok(Expression::TryCast(try_cast))
2791 }
2792 other => Ok(other),
2793 }
2794}
2795
2796fn is_temporal_type(dt: &DataType) -> bool {
2798 matches!(
2799 dt,
2800 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
2801 )
2802}
2803
2804pub fn ensure_bools(expr: Expression) -> Result<Expression> {
2829 let expr = ensure_bools_in_value_context(expr);
2830
2831 Ok(match expr {
2832 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => ensure_bool_condition(expr),
2834 other => other,
2835 })
2836}
2837
2838fn ensure_bools_in_value_context(expr: Expression) -> Expression {
2842 match expr {
2843 Expression::Case(mut case) => {
2844 let is_simple_case = case.operand.is_some();
2845 if let Some(operand) = case.operand.take() {
2846 case.operand = Some(ensure_bools_in_value_context(operand));
2847 }
2848 case.whens = case
2849 .whens
2850 .into_iter()
2851 .map(|(condition, result)| {
2852 let new_condition = if is_simple_case {
2853 ensure_bools_in_value_context(condition)
2854 } else {
2855 ensure_bool_condition(ensure_bools_in_value_context(condition))
2856 };
2857 let new_result = ensure_bools_in_value_context(result);
2858 (new_condition, new_result)
2859 })
2860 .collect();
2861 if let Some(else_expr) = case.else_ {
2862 case.else_ = Some(ensure_bools_in_value_context(else_expr));
2863 }
2864 Expression::Case(Box::new(*case))
2865 }
2866 Expression::Select(select) => Expression::Select(Box::new(ensure_bools_in_select(*select))),
2867 Expression::Subquery(mut subquery) => {
2868 subquery.this = ensure_bools_in_value_context(subquery.this);
2869 Expression::Subquery(subquery)
2870 }
2871 Expression::JoinedTable(mut joined_table) => {
2872 joined_table.left = ensure_bools_in_value_context(joined_table.left);
2873 joined_table.joins = joined_table
2874 .joins
2875 .into_iter()
2876 .map(ensure_bools_in_join)
2877 .collect();
2878 joined_table.lateral_views = joined_table
2879 .lateral_views
2880 .into_iter()
2881 .map(|mut lateral_view| {
2882 lateral_view.this = ensure_bools_in_value_context(lateral_view.this);
2883 lateral_view
2884 })
2885 .collect();
2886 Expression::JoinedTable(joined_table)
2887 }
2888 Expression::Union(mut union) => {
2889 let left = std::mem::replace(&mut union.left, Expression::null());
2890 let right = std::mem::replace(&mut union.right, Expression::null());
2891 union.left = ensure_bools_in_value_context(left);
2892 union.right = ensure_bools_in_value_context(right);
2893 if let Some(with) = union.with.take() {
2894 union.with = Some(ensure_bools_in_with(with));
2895 }
2896 Expression::Union(union)
2897 }
2898 Expression::Intersect(mut intersect) => {
2899 let left = std::mem::replace(&mut intersect.left, Expression::null());
2900 let right = std::mem::replace(&mut intersect.right, Expression::null());
2901 intersect.left = ensure_bools_in_value_context(left);
2902 intersect.right = ensure_bools_in_value_context(right);
2903 if let Some(with) = intersect.with.take() {
2904 intersect.with = Some(ensure_bools_in_with(with));
2905 }
2906 Expression::Intersect(intersect)
2907 }
2908 Expression::Except(mut except) => {
2909 let left = std::mem::replace(&mut except.left, Expression::null());
2910 let right = std::mem::replace(&mut except.right, Expression::null());
2911 except.left = ensure_bools_in_value_context(left);
2912 except.right = ensure_bools_in_value_context(right);
2913 if let Some(with) = except.with.take() {
2914 except.with = Some(ensure_bools_in_with(with));
2915 }
2916 Expression::Except(except)
2917 }
2918 Expression::Alias(mut alias) => {
2919 alias.this = ensure_bools_in_value_context(alias.this);
2920 Expression::Alias(alias)
2921 }
2922 Expression::Paren(mut paren) => {
2923 paren.this = ensure_bools_in_value_context(paren.this);
2924 Expression::Paren(paren)
2925 }
2926 other => other,
2927 }
2928}
2929
2930fn ensure_bools_in_select(mut select: Select) -> Select {
2931 select.expressions = select
2932 .expressions
2933 .into_iter()
2934 .map(ensure_bools_in_value_context)
2935 .collect();
2936
2937 if let Some(from) = select.from.take() {
2938 select.from = Some(crate::expressions::From {
2939 expressions: from
2940 .expressions
2941 .into_iter()
2942 .map(ensure_bools_in_value_context)
2943 .collect(),
2944 });
2945 }
2946
2947 select.joins = select.joins.into_iter().map(ensure_bools_in_join).collect();
2948
2949 if let Some(mut where_clause) = select.where_clause.take() {
2950 where_clause.this = ensure_bool_condition(ensure_bools_in_value_context(where_clause.this));
2951 select.where_clause = Some(where_clause);
2952 }
2953
2954 if let Some(mut having) = select.having.take() {
2955 having.this = ensure_bool_condition(ensure_bools_in_value_context(having.this));
2956 select.having = Some(having);
2957 }
2958
2959 if let Some(with) = select.with.take() {
2960 select.with = Some(ensure_bools_in_with(with));
2961 }
2962
2963 select
2964}
2965
2966fn ensure_bools_in_join(mut join: Join) -> Join {
2967 join.this = ensure_bools_in_value_context(join.this);
2968
2969 if let Some(on) = join.on.take() {
2970 join.on = Some(ensure_bool_condition(ensure_bools_in_value_context(on)));
2971 }
2972
2973 if let Some(match_condition) = join.match_condition.take() {
2974 join.match_condition = Some(ensure_bool_condition(ensure_bools_in_value_context(
2975 match_condition,
2976 )));
2977 }
2978
2979 join.pivots = join
2980 .pivots
2981 .into_iter()
2982 .map(ensure_bools_in_value_context)
2983 .collect();
2984
2985 join
2986}
2987
2988fn ensure_bools_in_with(mut with: With) -> With {
2989 with.ctes = with
2990 .ctes
2991 .into_iter()
2992 .map(|mut cte| {
2993 cte.this = ensure_bools_in_value_context(cte.this);
2994 cte
2995 })
2996 .collect();
2997 with
2998}
2999
3000fn is_boolean_expression(expr: &Expression) -> bool {
3003 matches!(
3004 expr,
3005 Expression::Eq(_)
3006 | Expression::Neq(_)
3007 | Expression::Lt(_)
3008 | Expression::Lte(_)
3009 | Expression::Gt(_)
3010 | Expression::Gte(_)
3011 | Expression::Is(_)
3012 | Expression::IsNull(_)
3013 | Expression::IsTrue(_)
3014 | Expression::IsFalse(_)
3015 | Expression::Like(_)
3016 | Expression::ILike(_)
3017 | Expression::StartsWith(_)
3018 | Expression::SimilarTo(_)
3019 | Expression::Glob(_)
3020 | Expression::RegexpLike(_)
3021 | Expression::In(_)
3022 | Expression::Between(_)
3023 | Expression::Exists(_)
3024 | Expression::And(_)
3025 | Expression::Or(_)
3026 | Expression::Not(_)
3027 | Expression::Any(_)
3028 | Expression::All(_)
3029 | Expression::NullSafeEq(_)
3030 | Expression::NullSafeNeq(_)
3031 | Expression::EqualNull(_)
3032 )
3033}
3034
3035fn wrap_neq_zero(expr: Expression) -> Expression {
3037 Expression::Neq(Box::new(BinaryOp {
3038 left: expr,
3039 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
3040 left_comments: vec![],
3041 operator_comments: vec![],
3042 trailing_comments: vec![],
3043 inferred_type: None,
3044 }))
3045}
3046
3047pub(crate) fn ensure_bool_condition(expr: Expression) -> Expression {
3053 match expr {
3054 Expression::And(op) => {
3056 let new_op = BinaryOp {
3057 left: ensure_bool_condition(op.left.clone()),
3058 right: ensure_bool_condition(op.right.clone()),
3059 left_comments: op.left_comments.clone(),
3060 operator_comments: op.operator_comments.clone(),
3061 trailing_comments: op.trailing_comments.clone(),
3062 inferred_type: None,
3063 };
3064 Expression::And(Box::new(new_op))
3065 }
3066 Expression::Or(op) => {
3067 let new_op = BinaryOp {
3068 left: ensure_bool_condition(op.left.clone()),
3069 right: ensure_bool_condition(op.right.clone()),
3070 left_comments: op.left_comments.clone(),
3071 operator_comments: op.operator_comments.clone(),
3072 trailing_comments: op.trailing_comments.clone(),
3073 inferred_type: None,
3074 };
3075 Expression::Or(Box::new(new_op))
3076 }
3077 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
3079 this: ensure_bool_condition(op.this.clone()),
3080 inferred_type: None,
3081 })),
3082 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
3084 this: ensure_bool_condition(paren.this.clone()),
3085 trailing_comments: paren.trailing_comments.clone(),
3086 })),
3087 Expression::Boolean(BooleanLiteral { value: true }) => {
3089 Expression::Paren(Box::new(crate::expressions::Paren {
3090 this: Expression::Eq(Box::new(BinaryOp {
3091 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3092 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3093 left_comments: vec![],
3094 operator_comments: vec![],
3095 trailing_comments: vec![],
3096 inferred_type: None,
3097 })),
3098 trailing_comments: vec![],
3099 }))
3100 }
3101 Expression::Boolean(BooleanLiteral { value: false }) => {
3102 Expression::Paren(Box::new(crate::expressions::Paren {
3103 this: Expression::Eq(Box::new(BinaryOp {
3104 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3105 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
3106 left_comments: vec![],
3107 operator_comments: vec![],
3108 trailing_comments: vec![],
3109 inferred_type: None,
3110 })),
3111 trailing_comments: vec![],
3112 }))
3113 }
3114 ref e if is_boolean_expression(e) => expr,
3116 _ => wrap_neq_zero(expr),
3119 }
3120}
3121
3122pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
3128 Ok(unqualify_columns_recursive(expr))
3129}
3130
3131fn unqualify_columns_recursive(expr: Expression) -> Expression {
3133 match expr {
3134 Expression::Column(mut col) => {
3135 col.table = None;
3136 Expression::Column(col)
3137 }
3138 Expression::Select(mut select) => {
3139 select.expressions = select
3140 .expressions
3141 .into_iter()
3142 .map(unqualify_columns_recursive)
3143 .collect();
3144 if let Some(ref mut where_clause) = select.where_clause {
3145 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
3146 }
3147 if let Some(ref mut having) = select.having {
3148 having.this = unqualify_columns_recursive(having.this.clone());
3149 }
3150 if let Some(ref mut group_by) = select.group_by {
3151 group_by.expressions = group_by
3152 .expressions
3153 .iter()
3154 .cloned()
3155 .map(unqualify_columns_recursive)
3156 .collect();
3157 }
3158 if let Some(ref mut order_by) = select.order_by {
3159 order_by.expressions = order_by
3160 .expressions
3161 .iter()
3162 .map(|o| crate::expressions::Ordered {
3163 this: unqualify_columns_recursive(o.this.clone()),
3164 desc: o.desc,
3165 nulls_first: o.nulls_first,
3166 explicit_asc: o.explicit_asc,
3167 with_fill: o.with_fill.clone(),
3168 })
3169 .collect();
3170 }
3171 for join in &mut select.joins {
3172 if let Some(ref mut on) = join.on {
3173 *on = unqualify_columns_recursive(on.clone());
3174 }
3175 }
3176 Expression::Select(select)
3177 }
3178 Expression::Alias(mut alias) => {
3179 alias.this = unqualify_columns_recursive(alias.this);
3180 Expression::Alias(alias)
3181 }
3182 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
3184 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
3185 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
3186 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
3187 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
3188 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
3189 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
3190 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
3191 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
3192 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
3193 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
3194 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
3195 Expression::Function(mut func) => {
3197 func.args = func
3198 .args
3199 .into_iter()
3200 .map(unqualify_columns_recursive)
3201 .collect();
3202 Expression::Function(func)
3203 }
3204 Expression::AggregateFunction(mut func) => {
3205 func.args = func
3206 .args
3207 .into_iter()
3208 .map(unqualify_columns_recursive)
3209 .collect();
3210 Expression::AggregateFunction(func)
3211 }
3212 Expression::Case(mut case) => {
3213 case.whens = case
3214 .whens
3215 .into_iter()
3216 .map(|(cond, result)| {
3217 (
3218 unqualify_columns_recursive(cond),
3219 unqualify_columns_recursive(result),
3220 )
3221 })
3222 .collect();
3223 if let Some(else_expr) = case.else_ {
3224 case.else_ = Some(unqualify_columns_recursive(else_expr));
3225 }
3226 Expression::Case(case)
3227 }
3228 other => other,
3230 }
3231}
3232
3233fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
3235 op.left = unqualify_columns_recursive(op.left);
3236 op.right = unqualify_columns_recursive(op.right);
3237 op
3238}
3239
3240pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
3260 match expr {
3261 Expression::Select(mut select) => {
3262 let mut cte_count = 0;
3263 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
3264
3265 if let Some(ref mut with) = select.with {
3267 for cte in &mut with.ctes {
3268 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
3269 }
3270 }
3271
3272 if let Some(ref mut from) = select.from {
3274 for table_expr in &mut from.expressions {
3275 if let Some((cte, replacement)) =
3276 try_convert_generate_date_array(table_expr, &mut cte_count)
3277 {
3278 new_ctes.push(cte);
3279 *table_expr = replacement;
3280 }
3281 }
3282 }
3283
3284 for join in &mut select.joins {
3286 if let Some((cte, replacement)) =
3287 try_convert_generate_date_array(&join.this, &mut cte_count)
3288 {
3289 new_ctes.push(cte);
3290 join.this = replacement;
3291 }
3292 }
3293
3294 if !new_ctes.is_empty() {
3296 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
3297 ctes: Vec::new(),
3298 recursive: true, leading_comments: vec![],
3300 search: None,
3301 });
3302 with_clause.recursive = true;
3303
3304 let mut all_ctes = new_ctes;
3306 all_ctes.append(&mut with_clause.ctes);
3307 with_clause.ctes = all_ctes;
3308 }
3309
3310 Ok(Expression::Select(select))
3311 }
3312 other => Ok(other),
3313 }
3314}
3315
3316fn process_expression_for_gda(
3319 expr: &mut Expression,
3320 cte_count: &mut usize,
3321 new_ctes: &mut Vec<crate::expressions::Cte>,
3322) {
3323 match expr {
3324 Expression::Select(ref mut select) => {
3325 if let Some(ref mut from) = select.from {
3327 for table_expr in &mut from.expressions {
3328 if let Some((cte, replacement)) =
3329 try_convert_generate_date_array(table_expr, cte_count)
3330 {
3331 new_ctes.push(cte);
3332 *table_expr = replacement;
3333 }
3334 }
3335 }
3336 for join in &mut select.joins {
3338 if let Some((cte, replacement)) =
3339 try_convert_generate_date_array(&join.this, cte_count)
3340 {
3341 new_ctes.push(cte);
3342 join.this = replacement;
3343 }
3344 }
3345 }
3346 Expression::Union(ref mut u) => {
3347 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
3348 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
3349 }
3350 Expression::Subquery(ref mut sq) => {
3351 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
3352 }
3353 _ => {}
3354 }
3355}
3356
3357fn try_convert_generate_date_array(
3360 expr: &Expression,
3361 cte_count: &mut usize,
3362) -> Option<(crate::expressions::Cte, Expression)> {
3363 try_convert_generate_date_array_with_name(expr, cte_count, None)
3364}
3365
3366fn try_convert_generate_date_array_with_name(
3367 expr: &Expression,
3368 cte_count: &mut usize,
3369 column_name_override: Option<&str>,
3370) -> Option<(crate::expressions::Cte, Expression)> {
3371 fn extract_gda_args(
3373 inner: &Expression,
3374 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
3375 match inner {
3376 Expression::GenerateDateArray(gda) => {
3377 let start = gda.start.as_ref()?;
3378 let end = gda.end.as_ref()?;
3379 let step = gda.step.as_deref();
3380 Some((start, end, step))
3381 }
3382 Expression::GenerateSeries(gs) => {
3383 let start = gs.start.as_deref()?;
3384 let end = gs.end.as_deref()?;
3385 let step = gs.step.as_deref();
3386 Some((start, end, step))
3387 }
3388 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
3389 if f.args.len() >= 2 {
3390 let start = &f.args[0];
3391 let end = &f.args[1];
3392 let step = f.args.get(2);
3393 Some((start, end, step))
3394 } else {
3395 None
3396 }
3397 }
3398 _ => None,
3399 }
3400 }
3401
3402 if let Expression::Unnest(unnest) = expr {
3404 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
3405 let start = start;
3406 let end = end;
3407 let step: Option<&Expression> = step_opt;
3408
3409 let cte_name = if *cte_count == 0 {
3411 "_generated_dates".to_string()
3412 } else {
3413 format!("_generated_dates_{}", cte_count)
3414 };
3415 *cte_count += 1;
3416
3417 let column_name =
3418 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
3419
3420 let cast_to_date = |expr: &Expression| -> Expression {
3422 match expr {
3423 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
3424 if let Expression::Literal(lit) = expr {
3426 if let Literal::Date(d) = lit.as_ref() {
3427 Expression::Cast(Box::new(Cast {
3428 this: Expression::Literal(Box::new(Literal::String(d.clone()))),
3429 to: DataType::Date,
3430 trailing_comments: vec![],
3431 double_colon_syntax: false,
3432 format: None,
3433 default: None,
3434 inferred_type: None,
3435 }))
3436 } else {
3437 expr.clone()
3438 }
3439 } else {
3440 unreachable!()
3441 }
3442 }
3443 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
3444 _ => Expression::Cast(Box::new(Cast {
3445 this: expr.clone(),
3446 to: DataType::Date,
3447 trailing_comments: vec![],
3448 double_colon_syntax: false,
3449 format: None,
3450 default: None,
3451 inferred_type: None,
3452 })),
3453 }
3454 };
3455
3456 let base_select = Select {
3458 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
3459 this: cast_to_date(start),
3460 alias: column_name.clone(),
3461 column_aliases: vec![],
3462 alias_explicit_as: false,
3463 alias_keyword: None,
3464 pre_alias_comments: vec![],
3465 trailing_comments: vec![],
3466 inferred_type: None,
3467 }))],
3468 ..Select::new()
3469 };
3470
3471 let normalize_interval = |expr: &Expression| -> Expression {
3473 if let Expression::Interval(ref iv) = expr {
3474 let mut iv_clone = iv.as_ref().clone();
3475 if let Some(Expression::Literal(ref lit)) = iv_clone.this {
3476 if let Literal::String(ref s) = lit.as_ref() {
3477 if s.parse::<f64>().is_ok() {
3479 iv_clone.this =
3480 Some(Expression::Literal(Box::new(Literal::Number(s.clone()))));
3481 }
3482 }
3483 }
3484 Expression::Interval(Box::new(iv_clone))
3485 } else {
3486 expr.clone()
3487 }
3488 };
3489
3490 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
3493 Expression::Interval(Box::new(crate::expressions::Interval {
3494 this: Some(Expression::Literal(Box::new(Literal::Number(
3495 "1".to_string(),
3496 )))),
3497 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
3498 unit: crate::expressions::IntervalUnit::Day,
3499 use_plural: false,
3500 }),
3501 }))
3502 });
3503
3504 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
3506
3507 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
3508 this: Expression::Column(Box::new(crate::expressions::Column {
3509 name: column_name.clone(),
3510 table: None,
3511 join_mark: false,
3512 trailing_comments: vec![],
3513 span: None,
3514 inferred_type: None,
3515 })),
3516 interval: add_count,
3517 unit: add_unit,
3518 }));
3519
3520 let cast_date_add = Expression::Cast(Box::new(Cast {
3521 this: date_add_expr.clone(),
3522 to: DataType::Date,
3523 trailing_comments: vec![],
3524 double_colon_syntax: false,
3525 format: None,
3526 default: None,
3527 inferred_type: None,
3528 }));
3529
3530 let recursive_select = Select {
3531 expressions: vec![cast_date_add.clone()],
3532 from: Some(From {
3533 expressions: vec![Expression::Table(Box::new(
3534 crate::expressions::TableRef::new(&cte_name),
3535 ))],
3536 }),
3537 where_clause: Some(Where {
3538 this: Expression::Lte(Box::new(BinaryOp {
3539 left: cast_date_add,
3540 right: cast_to_date(end),
3541 left_comments: vec![],
3542 operator_comments: vec![],
3543 trailing_comments: vec![],
3544 inferred_type: None,
3545 })),
3546 }),
3547 ..Select::new()
3548 };
3549
3550 let union = crate::expressions::Union {
3552 left: Expression::Select(Box::new(base_select)),
3553 right: Expression::Select(Box::new(recursive_select)),
3554 all: true, distinct: false,
3556 with: None,
3557 order_by: None,
3558 limit: None,
3559 offset: None,
3560 distribute_by: None,
3561 sort_by: None,
3562 cluster_by: None,
3563 by_name: false,
3564 side: None,
3565 kind: None,
3566 corresponding: false,
3567 strict: false,
3568 on_columns: Vec::new(),
3569 };
3570
3571 let cte = crate::expressions::Cte {
3573 this: Expression::Union(Box::new(union)),
3574 alias: Identifier::new(cte_name.clone()),
3575 columns: vec![column_name.clone()],
3576 materialized: None,
3577 key_expressions: Vec::new(),
3578 alias_first: true,
3579 comments: Vec::new(),
3580 };
3581
3582 let replacement_select = Select {
3584 expressions: vec![Expression::Column(Box::new(crate::expressions::Column {
3585 name: column_name,
3586 table: None,
3587 join_mark: false,
3588 trailing_comments: vec![],
3589 span: None,
3590 inferred_type: None,
3591 }))],
3592 from: Some(From {
3593 expressions: vec![Expression::Table(Box::new(
3594 crate::expressions::TableRef::new(&cte_name),
3595 ))],
3596 }),
3597 ..Select::new()
3598 };
3599
3600 let replacement = Expression::Subquery(Box::new(Subquery {
3601 this: Expression::Select(Box::new(replacement_select)),
3602 alias: Some(Identifier::new(cte_name)),
3603 column_aliases: vec![],
3604 alias_explicit_as: false,
3605 alias_keyword: None,
3606 order_by: None,
3607 limit: None,
3608 offset: None,
3609 distribute_by: None,
3610 sort_by: None,
3611 cluster_by: None,
3612 lateral: false,
3613 modifiers_inside: false,
3614 trailing_comments: vec![],
3615 inferred_type: None,
3616 }));
3617
3618 return Some((cte, replacement));
3619 }
3620 }
3621
3622 if let Expression::Alias(alias) = expr {
3624 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
3626 if let Some((cte, replacement)) =
3627 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
3628 {
3629 if col_name.is_some() {
3632 return Some((cte, replacement));
3633 }
3634 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
3635 this: replacement,
3636 alias: alias.alias.clone(),
3637 column_aliases: alias.column_aliases.clone(),
3638 alias_explicit_as: false,
3639 alias_keyword: None,
3640 pre_alias_comments: alias.pre_alias_comments.clone(),
3641 trailing_comments: alias.trailing_comments.clone(),
3642 inferred_type: None,
3643 }));
3644 return Some((cte, new_alias));
3645 }
3646 }
3647
3648 None
3649}
3650
3651fn extract_interval_unit_and_count(
3656 expr: &Expression,
3657) -> (crate::expressions::IntervalUnit, Expression) {
3658 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
3659
3660 if let Expression::Interval(ref iv) = expr {
3661 if let Some(ref unit_spec) = iv.unit {
3663 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
3664 let count = match &iv.this {
3665 Some(e) => e.clone(),
3666 None => Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3667 };
3668 return (unit.clone(), count);
3669 }
3670 }
3671
3672 if let Some(ref val_expr) = iv.this {
3674 match val_expr {
3675 Expression::Literal(lit)
3676 if matches!(lit.as_ref(), Literal::String(_) | Literal::Number(_)) =>
3677 {
3678 let s = match lit.as_ref() {
3679 Literal::String(s) | Literal::Number(s) => s,
3680 _ => unreachable!(),
3681 };
3682 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
3684 if parts.len() == 2 {
3685 let count_str = parts[0].trim();
3686 let unit_str = parts[1].trim().to_uppercase();
3687 let unit = match unit_str.as_str() {
3688 "YEAR" | "YEARS" => IntervalUnit::Year,
3689 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
3690 "MONTH" | "MONTHS" => IntervalUnit::Month,
3691 "WEEK" | "WEEKS" => IntervalUnit::Week,
3692 "DAY" | "DAYS" => IntervalUnit::Day,
3693 "HOUR" | "HOURS" => IntervalUnit::Hour,
3694 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
3695 "SECOND" | "SECONDS" => IntervalUnit::Second,
3696 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
3697 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
3698 _ => IntervalUnit::Day,
3699 };
3700 return (
3701 unit,
3702 Expression::Literal(Box::new(Literal::Number(count_str.to_string()))),
3703 );
3704 }
3705 if s.parse::<f64>().is_ok() {
3707 return (
3708 IntervalUnit::Day,
3709 Expression::Literal(Box::new(Literal::Number(s.clone()))),
3710 );
3711 }
3712 }
3713 _ => {}
3714 }
3715 }
3716
3717 (
3719 IntervalUnit::Day,
3720 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3721 )
3722 } else {
3723 (
3724 IntervalUnit::Day,
3725 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3726 )
3727 }
3728}
3729
3730pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
3743 match expr {
3744 Expression::ILike(ilike) => {
3745 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
3747 name: "LOWER".to_string(),
3748 args: vec![ilike.left],
3749 distinct: false,
3750 trailing_comments: vec![],
3751 use_bracket_syntax: false,
3752 no_parens: false,
3753 quoted: false,
3754 span: None,
3755 inferred_type: None,
3756 }));
3757
3758 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
3759 name: "LOWER".to_string(),
3760 args: vec![ilike.right],
3761 distinct: false,
3762 trailing_comments: vec![],
3763 use_bracket_syntax: false,
3764 no_parens: false,
3765 quoted: false,
3766 span: None,
3767 inferred_type: None,
3768 }));
3769
3770 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
3771 left: lower_left,
3772 right: lower_right,
3773 escape: ilike.escape,
3774 quantifier: ilike.quantifier,
3775 inferred_type: None,
3776 })))
3777 }
3778 other => Ok(other),
3779 }
3780}
3781
3782pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
3790 match expr {
3791 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
3792 other => Ok(other),
3793 }
3794}
3795
3796pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
3801 match expr {
3802 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
3803 other => Ok(other),
3804 }
3805}
3806
3807pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
3814 Ok(expr)
3816}
3817
3818pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
3832 match expr {
3835 Expression::Table(ref table) => {
3836 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
3839 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3841 this: expr.clone(),
3842 expressions: Vec::new(),
3843 with_ordinality: false,
3844 alias: None,
3845 offset_alias: None,
3846 inferred_type: None,
3847 }));
3848
3849 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
3851 this: unnest,
3852 alias: Identifier::new("_u".to_string()),
3853 column_aliases: vec![],
3854 alias_explicit_as: false,
3855 alias_keyword: None,
3856 pre_alias_comments: vec![],
3857 trailing_comments: vec![],
3858 inferred_type: None,
3859 })));
3860 }
3861 Ok(expr)
3862 }
3863 Expression::GenerateSeries(gs) => {
3864 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3866 this: Expression::GenerateSeries(gs),
3867 expressions: Vec::new(),
3868 with_ordinality: false,
3869 alias: None,
3870 offset_alias: None,
3871 inferred_type: None,
3872 }));
3873 Ok(unnest)
3874 }
3875 other => Ok(other),
3876 }
3877}
3878
3879pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
3890 use crate::dialects::transform_recursive;
3891 transform_recursive(expr, &unwrap_unnest_generate_series_single)
3892}
3893
3894fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
3895 use crate::expressions::*;
3896 match expr {
3898 Expression::Select(mut select) => {
3899 if let Some(ref mut from) = select.from {
3901 for table_expr in &mut from.expressions {
3902 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
3903 *table_expr = replacement;
3904 }
3905 }
3906 }
3907 for join in &mut select.joins {
3909 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
3910 join.this = replacement;
3911 }
3912 }
3913 Ok(Expression::Select(select))
3914 }
3915 other => Ok(other),
3916 }
3917}
3918
3919fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
3922 use crate::expressions::*;
3923
3924 let gen_series = match expr {
3926 Expression::Unnest(unnest) => {
3927 if let Expression::GenerateSeries(ref gs) = unnest.this {
3928 Some(gs.as_ref().clone())
3929 } else {
3930 None
3931 }
3932 }
3933 Expression::Alias(alias) => {
3934 if let Expression::Unnest(ref unnest) = alias.this {
3935 if let Expression::GenerateSeries(ref gs) = unnest.this {
3936 Some(gs.as_ref().clone())
3937 } else {
3938 None
3939 }
3940 } else {
3941 None
3942 }
3943 }
3944 _ => None,
3945 };
3946
3947 let gs = gen_series?;
3948
3949 let value_col = Expression::boxed_column(Column {
3951 name: Identifier::new("value".to_string()),
3952 table: None,
3953 join_mark: false,
3954 trailing_comments: vec![],
3955 span: None,
3956 inferred_type: None,
3957 });
3958
3959 let cast_value = Expression::Cast(Box::new(Cast {
3960 this: value_col,
3961 to: DataType::Date,
3962 trailing_comments: vec![],
3963 double_colon_syntax: false,
3964 format: None,
3965 default: None,
3966 inferred_type: None,
3967 }));
3968
3969 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
3970
3971 let gen_series_aliased = Expression::Alias(Box::new(Alias {
3973 this: gen_series_expr,
3974 alias: Identifier::new("_t".to_string()),
3975 column_aliases: vec![Identifier::new("value".to_string())],
3976 alias_explicit_as: false,
3977 alias_keyword: None,
3978 pre_alias_comments: vec![],
3979 trailing_comments: vec![],
3980 inferred_type: None,
3981 }));
3982
3983 let mut inner_select = Select::new();
3984 inner_select.expressions = vec![cast_value];
3985 inner_select.from = Some(From {
3986 expressions: vec![gen_series_aliased],
3987 });
3988
3989 let inner_select_expr = Expression::Select(Box::new(inner_select));
3990
3991 let subquery = Expression::Subquery(Box::new(Subquery {
3992 this: inner_select_expr,
3993 alias: None,
3994 column_aliases: vec![],
3995 alias_explicit_as: false,
3996 alias_keyword: None,
3997 order_by: None,
3998 limit: None,
3999 offset: None,
4000 distribute_by: None,
4001 sort_by: None,
4002 cluster_by: None,
4003 lateral: false,
4004 modifiers_inside: false,
4005 trailing_comments: vec![],
4006 inferred_type: None,
4007 }));
4008
4009 Some(Expression::Alias(Box::new(Alias {
4011 this: subquery,
4012 alias: Identifier::new("_unnested_generate_series".to_string()),
4013 column_aliases: vec![],
4014 alias_explicit_as: false,
4015 alias_keyword: None,
4016 pre_alias_comments: vec![],
4017 trailing_comments: vec![],
4018 inferred_type: None,
4019 })))
4020}
4021
4022pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
4030 match expr {
4031 Expression::Delete(mut delete) => {
4032 if let Some(ref mut where_clause) = delete.where_clause {
4034 where_clause.this = expand_between_recursive(where_clause.this.clone());
4035 }
4036 Ok(Expression::Delete(delete))
4037 }
4038 other => Ok(other),
4039 }
4040}
4041
4042fn expand_between_recursive(expr: Expression) -> Expression {
4044 match expr {
4045 Expression::Between(between) => {
4048 let this = expand_between_recursive(between.this.clone());
4049 let low = expand_between_recursive(between.low);
4050 let high = expand_between_recursive(between.high);
4051
4052 if between.not {
4053 Expression::Or(Box::new(BinaryOp::new(
4055 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
4056 Expression::Gt(Box::new(BinaryOp::new(this, high))),
4057 )))
4058 } else {
4059 Expression::And(Box::new(BinaryOp::new(
4061 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
4062 Expression::Lte(Box::new(BinaryOp::new(this, high))),
4063 )))
4064 }
4065 }
4066
4067 Expression::And(mut op) => {
4069 op.left = expand_between_recursive(op.left);
4070 op.right = expand_between_recursive(op.right);
4071 Expression::And(op)
4072 }
4073 Expression::Or(mut op) => {
4074 op.left = expand_between_recursive(op.left);
4075 op.right = expand_between_recursive(op.right);
4076 Expression::Or(op)
4077 }
4078 Expression::Not(mut op) => {
4079 op.this = expand_between_recursive(op.this);
4080 Expression::Not(op)
4081 }
4082
4083 Expression::Paren(mut paren) => {
4085 paren.this = expand_between_recursive(paren.this);
4086 Expression::Paren(paren)
4087 }
4088
4089 other => other,
4091 }
4092}
4093
4094pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
4103 match expr {
4104 Expression::Select(mut select) => {
4105 if let Some(ref mut with) = select.with {
4106 for cte in &mut with.ctes {
4107 if !cte.columns.is_empty() {
4108 let is_star = matches!(&cte.this, Expression::Select(s) if
4110 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
4111
4112 if is_star {
4113 cte.columns.clear();
4115 continue;
4116 }
4117
4118 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
4120
4121 if let Expression::Select(ref mut inner_select) = cte.this {
4123 let new_exprs: Vec<Expression> = inner_select
4124 .expressions
4125 .drain(..)
4126 .zip(
4127 column_names
4128 .into_iter()
4129 .chain(std::iter::repeat_with(|| Identifier::new(""))),
4130 )
4131 .map(|(expr, col_name)| {
4132 if col_name.name.is_empty() {
4133 return expr;
4134 }
4135 match expr {
4137 Expression::Alias(mut a) => {
4138 a.alias = col_name;
4139 Expression::Alias(a)
4140 }
4141 other => {
4142 Expression::Alias(Box::new(crate::expressions::Alias {
4143 this: other,
4144 alias: col_name,
4145 column_aliases: Vec::new(),
4146 alias_explicit_as: false,
4147 alias_keyword: None,
4148 pre_alias_comments: Vec::new(),
4149 trailing_comments: Vec::new(),
4150 inferred_type: None,
4151 }))
4152 }
4153 }
4154 })
4155 .collect();
4156 inner_select.expressions = new_exprs;
4157 }
4158 }
4159 }
4160 }
4161 Ok(Expression::Select(select))
4162 }
4163 other => Ok(other),
4164 }
4165}
4166
4167pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
4171 match expr {
4172 Expression::Select(mut select) => {
4173 if let Some(ref mut from) = select.from {
4174 for from_item in from.expressions.iter_mut() {
4175 simplify_paren_values_in_from(from_item);
4176 }
4177 }
4178 Ok(Expression::Select(select))
4179 }
4180 other => Ok(other),
4181 }
4182}
4183
4184fn simplify_paren_values_in_from(expr: &mut Expression) {
4185 let replacement = match expr {
4187 Expression::Subquery(ref subquery) => {
4189 if let Expression::Paren(ref paren) = subquery.this {
4190 if matches!(&paren.this, Expression::Values(_)) {
4191 let mut new_sub = subquery.as_ref().clone();
4192 new_sub.this = paren.this.clone();
4193 Some(Expression::Subquery(Box::new(new_sub)))
4194 } else {
4195 None
4196 }
4197 } else {
4198 None
4199 }
4200 }
4201 Expression::Paren(ref outer_paren) => {
4204 if let Expression::Subquery(ref subquery) = outer_paren.this {
4205 if matches!(&subquery.this, Expression::Values(_)) {
4207 Some(outer_paren.this.clone())
4208 }
4209 else if let Expression::Paren(ref paren) = subquery.this {
4211 if matches!(&paren.this, Expression::Values(_)) {
4212 let mut new_sub = subquery.as_ref().clone();
4213 new_sub.this = paren.this.clone();
4214 Some(Expression::Subquery(Box::new(new_sub)))
4215 } else {
4216 None
4217 }
4218 } else {
4219 None
4220 }
4221 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
4222 if matches!(&inner_paren.this, Expression::Values(_)) {
4223 Some(outer_paren.this.clone())
4224 } else {
4225 None
4226 }
4227 } else {
4228 None
4229 }
4230 }
4231 _ => None,
4232 };
4233 if let Some(new_expr) = replacement {
4234 *expr = new_expr;
4235 }
4236}
4237
4238pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
4242 match expr {
4243 Expression::Select(mut select) => {
4244 if let Some(ref mut from) = select.from {
4246 let mut counter = 0usize;
4247 for from_item in from.expressions.iter_mut() {
4248 add_auto_alias_to_from_item(from_item, &mut counter);
4249 }
4250 }
4251 Ok(Expression::Select(select))
4252 }
4253 other => Ok(other),
4254 }
4255}
4256
4257fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
4258 use crate::expressions::Identifier;
4259
4260 match expr {
4261 Expression::Alias(ref mut alias) => {
4262 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
4264 alias.alias = Identifier::new(format!("_t{}", counter));
4265 *counter += 1;
4266 }
4267 }
4268 _ => {}
4269 }
4270}
4271
4272pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
4282 use crate::dialects::transform_recursive;
4283 transform_recursive(expr, &propagate_struct_names_in_expr)
4284}
4285
4286fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
4287 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
4288
4289 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
4291 if elements.len() <= 1 {
4292 return None;
4293 }
4294 if let Some(Expression::Function(ref first_struct)) = elements.first() {
4296 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
4297 let field_names: Vec<Option<String>> = first_struct
4299 .args
4300 .iter()
4301 .map(|arg| {
4302 if let Expression::Alias(a) = arg {
4303 Some(a.alias.name.clone())
4304 } else {
4305 None
4306 }
4307 })
4308 .collect();
4309
4310 if field_names.iter().any(|n| n.is_some()) {
4312 let mut new_elements = Vec::with_capacity(elements.len());
4313 new_elements.push(elements[0].clone());
4314
4315 for elem in &elements[1..] {
4316 if let Expression::Function(ref s) = elem {
4317 if s.name.eq_ignore_ascii_case("STRUCT")
4318 && s.args.len() == field_names.len()
4319 {
4320 let all_unnamed =
4322 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
4323 if all_unnamed {
4324 let new_args: Vec<Expression> = s
4326 .args
4327 .iter()
4328 .zip(field_names.iter())
4329 .map(|(val, name)| {
4330 if let Some(n) = name {
4331 Expression::Alias(Box::new(Alias::new(
4332 val.clone(),
4333 Identifier::new(n.clone()),
4334 )))
4335 } else {
4336 val.clone()
4337 }
4338 })
4339 .collect();
4340 new_elements.push(Expression::Function(Box::new(
4341 Function::new("STRUCT".to_string(), new_args),
4342 )));
4343 continue;
4344 }
4345 }
4346 }
4347 new_elements.push(elem.clone());
4348 }
4349
4350 return Some(new_elements);
4351 }
4352 }
4353 }
4354 None
4355 }
4356
4357 if let Expression::Array(ref arr) = expr {
4359 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
4360 return Ok(Expression::Array(Box::new(crate::expressions::Array {
4361 expressions: new_elements,
4362 })));
4363 }
4364 }
4365
4366 if let Expression::ArrayFunc(ref arr) = expr {
4368 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
4369 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
4370 expressions: new_elements,
4371 bracket_notation: arr.bracket_notation,
4372 use_list_keyword: arr.use_list_keyword,
4373 })));
4374 }
4375 }
4376
4377 Ok(expr)
4378}
4379
4380pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
4383 use crate::dialects::transform_recursive;
4384 transform_recursive(expr, &unnest_alias_transform_single_select)
4385}
4386
4387pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
4390 use crate::dialects::transform_recursive;
4391 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
4392}
4393
4394fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
4395 if let Expression::Select(mut select) = expr {
4396 if let Some(ref mut from) = select.from {
4397 if from.expressions.len() > 1 {
4398 let mut new_from_exprs = Vec::new();
4399 let mut new_cross_joins = Vec::new();
4400
4401 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4402 if idx == 0 {
4403 new_from_exprs.push(from_item);
4404 } else {
4405 let is_unnest = match &from_item {
4406 Expression::Unnest(_) => true,
4407 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4408 _ => false,
4409 };
4410
4411 if is_unnest {
4412 new_cross_joins.push(crate::expressions::Join {
4413 this: from_item,
4414 on: None,
4415 using: Vec::new(),
4416 kind: JoinKind::Cross,
4417 use_inner_keyword: false,
4418 use_outer_keyword: false,
4419 deferred_condition: false,
4420 join_hint: None,
4421 match_condition: None,
4422 pivots: Vec::new(),
4423 comments: Vec::new(),
4424 nesting_group: 0,
4425 directed: false,
4426 });
4427 } else {
4428 new_from_exprs.push(from_item);
4429 }
4430 }
4431 }
4432
4433 from.expressions = new_from_exprs;
4434 new_cross_joins.append(&mut select.joins);
4435 select.joins = new_cross_joins;
4436 }
4437 }
4438
4439 Ok(Expression::Select(select))
4440 } else {
4441 Ok(expr)
4442 }
4443}
4444
4445pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
4449 use crate::dialects::transform_recursive;
4450 transform_recursive(expr, &wrap_unnest_join_aliases_single)
4451}
4452
4453fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
4454 if let Expression::Select(mut select) = expr {
4455 for join in &mut select.joins {
4457 wrap_unnest_alias_in_join_item(&mut join.this);
4458 }
4459 Ok(Expression::Select(select))
4460 } else {
4461 Ok(expr)
4462 }
4463}
4464
4465fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
4467 use crate::expressions::Identifier;
4468 if let Expression::Alias(alias) = expr {
4469 let is_unnest = match &alias.this {
4471 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
4472 _ => false,
4473 };
4474
4475 if is_unnest && alias.column_aliases.is_empty() {
4476 let original_alias_name = alias.alias.name.clone();
4478 alias.alias = Identifier {
4479 name: "_u".to_string(),
4480 quoted: false,
4481 trailing_comments: Vec::new(),
4482 span: None,
4483 };
4484 alias.column_aliases = vec![Identifier {
4485 name: original_alias_name,
4486 quoted: false,
4487 trailing_comments: Vec::new(),
4488 span: None,
4489 }];
4490 }
4491 }
4492}
4493
4494fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
4495 if let Expression::Select(mut select) = expr {
4496 let mut counter = 0usize;
4497
4498 if let Some(ref mut from) = select.from {
4500 for from_item in from.expressions.iter_mut() {
4502 convert_unnest_alias_in_from(from_item, &mut counter);
4503 }
4504
4505 if from.expressions.len() > 1 {
4507 let mut new_from_exprs = Vec::new();
4508 let mut new_cross_joins = Vec::new();
4509
4510 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4511 if idx == 0 {
4512 new_from_exprs.push(from_item);
4514 } else {
4515 let is_unnest = match &from_item {
4517 Expression::Unnest(_) => true,
4518 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4519 _ => false,
4520 };
4521
4522 if is_unnest {
4523 new_cross_joins.push(crate::expressions::Join {
4525 this: from_item,
4526 on: None,
4527 using: Vec::new(),
4528 kind: JoinKind::Cross,
4529 use_inner_keyword: false,
4530 use_outer_keyword: false,
4531 deferred_condition: false,
4532 join_hint: None,
4533 match_condition: None,
4534 pivots: Vec::new(),
4535 comments: Vec::new(),
4536 nesting_group: 0,
4537 directed: false,
4538 });
4539 } else {
4540 new_from_exprs.push(from_item);
4542 }
4543 }
4544 }
4545
4546 from.expressions = new_from_exprs;
4547 new_cross_joins.append(&mut select.joins);
4549 select.joins = new_cross_joins;
4550 }
4551 }
4552
4553 for join in select.joins.iter_mut() {
4555 convert_unnest_alias_in_from(&mut join.this, &mut counter);
4556 }
4557
4558 Ok(Expression::Select(select))
4559 } else {
4560 Ok(expr)
4561 }
4562}
4563
4564fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
4565 use crate::expressions::Identifier;
4566
4567 if let Expression::Alias(ref mut alias) = expr {
4568 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
4570 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
4571
4572 if is_unnest && alias.column_aliases.is_empty() {
4573 let col_alias = alias.alias.clone();
4575 alias.column_aliases = vec![col_alias];
4576 alias.alias = Identifier::new(format!("_t{}", counter));
4577 *counter += 1;
4578 }
4579 }
4580}
4581
4582pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
4589 use crate::expressions::{Alias, Function};
4590
4591 match expr {
4592 Expression::Select(mut select) => {
4593 let mut new_expressions = Vec::new();
4595 let mut changed = false;
4596
4597 for sel_expr in select.expressions.drain(..) {
4598 if let Expression::Alias(ref alias_box) = sel_expr {
4600 if let Expression::Function(ref func) = alias_box.this {
4601 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4602 let arg = func.args[0].clone();
4603 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4605 (
4606 alias_box.column_aliases[0].name.clone(),
4607 alias_box.column_aliases[1].name.clone(),
4608 )
4609 } else if !alias_box.alias.is_empty() {
4610 ("pos".to_string(), alias_box.alias.name.clone())
4612 } else {
4613 ("pos".to_string(), "col".to_string())
4614 };
4615
4616 let gen_subscripts = Expression::Function(Box::new(Function::new(
4618 "GENERATE_SUBSCRIPTS".to_string(),
4619 vec![
4620 arg.clone(),
4621 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4622 ],
4623 )));
4624 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4625 gen_subscripts,
4626 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4627 )));
4628 let pos_alias = Expression::Alias(Box::new(Alias {
4629 this: sub_one,
4630 alias: Identifier::new(pos_name),
4631 column_aliases: Vec::new(),
4632 alias_explicit_as: false,
4633 alias_keyword: None,
4634 pre_alias_comments: Vec::new(),
4635 trailing_comments: Vec::new(),
4636 inferred_type: None,
4637 }));
4638
4639 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4641 this: arg,
4642 expressions: Vec::new(),
4643 with_ordinality: false,
4644 alias: None,
4645 offset_alias: None,
4646 inferred_type: None,
4647 }));
4648 let col_alias = Expression::Alias(Box::new(Alias {
4649 this: unnest,
4650 alias: Identifier::new(col_name),
4651 column_aliases: Vec::new(),
4652 alias_explicit_as: false,
4653 alias_keyword: None,
4654 pre_alias_comments: Vec::new(),
4655 trailing_comments: Vec::new(),
4656 inferred_type: None,
4657 }));
4658
4659 new_expressions.push(pos_alias);
4660 new_expressions.push(col_alias);
4661 changed = true;
4662 continue;
4663 }
4664 }
4665 }
4666
4667 if let Expression::Function(ref func) = sel_expr {
4669 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4670 let arg = func.args[0].clone();
4671 let pos_name = "pos";
4672 let col_name = "col";
4673
4674 let gen_subscripts = Expression::Function(Box::new(Function::new(
4676 "GENERATE_SUBSCRIPTS".to_string(),
4677 vec![
4678 arg.clone(),
4679 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4680 ],
4681 )));
4682 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4683 gen_subscripts,
4684 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4685 )));
4686 let pos_alias = Expression::Alias(Box::new(Alias {
4687 this: sub_one,
4688 alias: Identifier::new(pos_name),
4689 column_aliases: Vec::new(),
4690 alias_explicit_as: false,
4691 alias_keyword: None,
4692 pre_alias_comments: Vec::new(),
4693 trailing_comments: Vec::new(),
4694 inferred_type: None,
4695 }));
4696
4697 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4699 this: arg,
4700 expressions: Vec::new(),
4701 with_ordinality: false,
4702 alias: None,
4703 offset_alias: None,
4704 inferred_type: None,
4705 }));
4706 let col_alias = Expression::Alias(Box::new(Alias {
4707 this: unnest,
4708 alias: Identifier::new(col_name),
4709 column_aliases: Vec::new(),
4710 alias_explicit_as: false,
4711 alias_keyword: None,
4712 pre_alias_comments: Vec::new(),
4713 trailing_comments: Vec::new(),
4714 inferred_type: None,
4715 }));
4716
4717 new_expressions.push(pos_alias);
4718 new_expressions.push(col_alias);
4719 changed = true;
4720 continue;
4721 }
4722 }
4723
4724 new_expressions.push(sel_expr);
4726 }
4727
4728 if changed {
4729 select.expressions = new_expressions;
4730 } else {
4731 select.expressions = new_expressions;
4732 }
4733
4734 if let Some(ref mut from) = select.from {
4737 expand_posexplode_in_from_duckdb(from)?;
4738 }
4739
4740 Ok(Expression::Select(select))
4741 }
4742 other => Ok(other),
4743 }
4744}
4745
4746fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
4748 use crate::expressions::{Alias, Function};
4749
4750 let mut new_expressions = Vec::new();
4751 let mut _changed = false;
4752
4753 for table_expr in from.expressions.drain(..) {
4754 if let Expression::Alias(ref alias_box) = table_expr {
4756 if let Expression::Function(ref func) = alias_box.this {
4757 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4758 let arg = func.args[0].clone();
4759 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4760 (
4761 alias_box.column_aliases[0].name.clone(),
4762 alias_box.column_aliases[1].name.clone(),
4763 )
4764 } else {
4765 ("pos".to_string(), "col".to_string())
4766 };
4767
4768 let gen_subscripts = Expression::Function(Box::new(Function::new(
4770 "GENERATE_SUBSCRIPTS".to_string(),
4771 vec![
4772 arg.clone(),
4773 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4774 ],
4775 )));
4776 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4777 gen_subscripts,
4778 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4779 )));
4780 let pos_alias = Expression::Alias(Box::new(Alias {
4781 this: sub_one,
4782 alias: Identifier::new(&pos_name),
4783 column_aliases: Vec::new(),
4784 alias_explicit_as: false,
4785 alias_keyword: None,
4786 pre_alias_comments: Vec::new(),
4787 trailing_comments: Vec::new(),
4788 inferred_type: None,
4789 }));
4790 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4791 this: arg,
4792 expressions: Vec::new(),
4793 with_ordinality: false,
4794 alias: None,
4795 offset_alias: None,
4796 inferred_type: None,
4797 }));
4798 let col_alias = Expression::Alias(Box::new(Alias {
4799 this: unnest,
4800 alias: Identifier::new(&col_name),
4801 column_aliases: Vec::new(),
4802 alias_explicit_as: false,
4803 alias_keyword: None,
4804 pre_alias_comments: Vec::new(),
4805 trailing_comments: Vec::new(),
4806 inferred_type: None,
4807 }));
4808
4809 let mut inner_select = Select::new();
4810 inner_select.expressions = vec![pos_alias, col_alias];
4811
4812 let subquery = Expression::Subquery(Box::new(Subquery {
4813 this: Expression::Select(Box::new(inner_select)),
4814 alias: None,
4815 column_aliases: Vec::new(),
4816 alias_explicit_as: false,
4817 alias_keyword: None,
4818 order_by: None,
4819 limit: None,
4820 offset: None,
4821 distribute_by: None,
4822 sort_by: None,
4823 cluster_by: None,
4824 lateral: false,
4825 modifiers_inside: false,
4826 trailing_comments: Vec::new(),
4827 inferred_type: None,
4828 }));
4829 new_expressions.push(subquery);
4830 _changed = true;
4831 continue;
4832 }
4833 }
4834 }
4835
4836 if let Expression::Function(ref func) = table_expr {
4838 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4839 let arg = func.args[0].clone();
4840
4841 let gen_subscripts = Expression::Function(Box::new(Function::new(
4843 "GENERATE_SUBSCRIPTS".to_string(),
4844 vec![
4845 arg.clone(),
4846 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4847 ],
4848 )));
4849 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4850 gen_subscripts,
4851 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4852 )));
4853 let pos_alias = Expression::Alias(Box::new(Alias {
4854 this: sub_one,
4855 alias: Identifier::new("pos"),
4856 column_aliases: Vec::new(),
4857 alias_explicit_as: false,
4858 alias_keyword: None,
4859 pre_alias_comments: Vec::new(),
4860 trailing_comments: Vec::new(),
4861 inferred_type: None,
4862 }));
4863 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4864 this: arg,
4865 expressions: Vec::new(),
4866 with_ordinality: false,
4867 alias: None,
4868 offset_alias: None,
4869 inferred_type: None,
4870 }));
4871 let col_alias = Expression::Alias(Box::new(Alias {
4872 this: unnest,
4873 alias: Identifier::new("col"),
4874 column_aliases: Vec::new(),
4875 alias_explicit_as: false,
4876 alias_keyword: None,
4877 pre_alias_comments: Vec::new(),
4878 trailing_comments: Vec::new(),
4879 inferred_type: None,
4880 }));
4881
4882 let mut inner_select = Select::new();
4883 inner_select.expressions = vec![pos_alias, col_alias];
4884
4885 let subquery = Expression::Subquery(Box::new(Subquery {
4886 this: Expression::Select(Box::new(inner_select)),
4887 alias: None,
4888 column_aliases: Vec::new(),
4889 alias_explicit_as: false,
4890 alias_keyword: None,
4891 order_by: None,
4892 limit: None,
4893 offset: None,
4894 distribute_by: None,
4895 sort_by: None,
4896 cluster_by: None,
4897 lateral: false,
4898 modifiers_inside: false,
4899 trailing_comments: Vec::new(),
4900 inferred_type: None,
4901 }));
4902 new_expressions.push(subquery);
4903 _changed = true;
4904 continue;
4905 }
4906 }
4907
4908 new_expressions.push(table_expr);
4909 }
4910
4911 from.expressions = new_expressions;
4912 Ok(())
4913}
4914
4915pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
4930 match expr {
4931 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
4932 other => Ok(other),
4933 }
4934}
4935
4936pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
4946 match expr {
4947 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
4948 other => Ok(other),
4949 }
4950}
4951
4952fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
4953 let mut flattened_inputs: Vec<Expression> = Vec::new();
4954 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
4955
4956 for sel_expr in select.expressions.into_iter() {
4957 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
4958
4959 let rewritten = transform_recursive(sel_expr, &|e| {
4960 if let Expression::Lateral(lat) = e {
4961 if let Some(input_expr) = extract_flatten_input(&lat) {
4962 if found_input.borrow().is_none() {
4963 *found_input.borrow_mut() = Some(input_expr);
4964 }
4965 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
4966 }
4967 return Ok(Expression::Lateral(lat));
4968 }
4969 Ok(e)
4970 })?;
4971
4972 if let Some(input) = found_input.into_inner() {
4973 flattened_inputs.push(input);
4974 }
4975 new_selects.push(rewritten);
4976 }
4977
4978 if flattened_inputs.is_empty() {
4979 select.expressions = new_selects;
4980 return Ok(Expression::Select(Box::new(select)));
4981 }
4982
4983 select.expressions = new_selects;
4984
4985 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
4986 let is_first = idx == 0;
4988 let series_alias = if is_first {
4989 "pos".to_string()
4990 } else {
4991 format!("pos_{}", idx + 1)
4992 };
4993 let series_source_alias = if is_first {
4994 "_u".to_string()
4995 } else {
4996 format!("_u_{}", idx * 2 + 1)
4997 };
4998 let unnest_source_alias = if is_first {
4999 "_u_2".to_string()
5000 } else {
5001 format!("_u_{}", idx * 2 + 2)
5002 };
5003 let pos2_alias = if is_first {
5004 "pos_2".to_string()
5005 } else {
5006 format!("{}_2", series_alias)
5007 };
5008 let entity_alias = if is_first {
5009 "entity".to_string()
5010 } else {
5011 format!("entity_{}", idx + 1)
5012 };
5013
5014 let array_size_call = Expression::Function(Box::new(Function::new(
5015 "ARRAY_SIZE".to_string(),
5016 vec![Expression::NamedArgument(Box::new(NamedArgument {
5017 name: Identifier::new("INPUT"),
5018 value: input_expr.clone(),
5019 separator: NamedArgSeparator::DArrow,
5020 }))],
5021 )));
5022
5023 let greatest = Expression::Function(Box::new(Function::new(
5024 "GREATEST".to_string(),
5025 vec![array_size_call.clone()],
5026 )));
5027
5028 let series_end = Expression::Add(Box::new(BinaryOp::new(
5029 Expression::Paren(Box::new(crate::expressions::Paren {
5030 this: Expression::Sub(Box::new(BinaryOp::new(
5031 greatest,
5032 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5033 ))),
5034 trailing_comments: Vec::new(),
5035 })),
5036 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5037 )));
5038
5039 let series_range = Expression::Function(Box::new(Function::new(
5040 "ARRAY_GENERATE_RANGE".to_string(),
5041 vec![
5042 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
5043 series_end,
5044 ],
5045 )));
5046
5047 let series_flatten = Expression::Function(Box::new(Function::new(
5048 "FLATTEN".to_string(),
5049 vec![Expression::NamedArgument(Box::new(NamedArgument {
5050 name: Identifier::new("INPUT"),
5051 value: series_range,
5052 separator: NamedArgSeparator::DArrow,
5053 }))],
5054 )));
5055
5056 let series_table = Expression::Function(Box::new(Function::new(
5057 "TABLE".to_string(),
5058 vec![series_flatten],
5059 )));
5060
5061 let series_alias_expr = Expression::Alias(Box::new(Alias {
5062 this: series_table,
5063 alias: Identifier::new(series_source_alias.clone()),
5064 column_aliases: vec![
5065 Identifier::new("seq"),
5066 Identifier::new("key"),
5067 Identifier::new("path"),
5068 Identifier::new("index"),
5069 Identifier::new(series_alias.clone()),
5070 Identifier::new("this"),
5071 ],
5072 alias_explicit_as: false,
5073 alias_keyword: None,
5074 pre_alias_comments: Vec::new(),
5075 trailing_comments: Vec::new(),
5076 inferred_type: None,
5077 }));
5078
5079 select.joins.push(Join {
5080 this: series_alias_expr,
5081 on: None,
5082 using: Vec::new(),
5083 kind: JoinKind::Cross,
5084 use_inner_keyword: false,
5085 use_outer_keyword: false,
5086 deferred_condition: false,
5087 join_hint: None,
5088 match_condition: None,
5089 pivots: Vec::new(),
5090 comments: Vec::new(),
5091 nesting_group: 0,
5092 directed: false,
5093 });
5094
5095 let entity_flatten = Expression::Function(Box::new(Function::new(
5096 "FLATTEN".to_string(),
5097 vec![Expression::NamedArgument(Box::new(NamedArgument {
5098 name: Identifier::new("INPUT"),
5099 value: input_expr.clone(),
5100 separator: NamedArgSeparator::DArrow,
5101 }))],
5102 )));
5103
5104 let entity_table = Expression::Function(Box::new(Function::new(
5105 "TABLE".to_string(),
5106 vec![entity_flatten],
5107 )));
5108
5109 let entity_alias_expr = Expression::Alias(Box::new(Alias {
5110 this: entity_table,
5111 alias: Identifier::new(unnest_source_alias.clone()),
5112 column_aliases: vec![
5113 Identifier::new("seq"),
5114 Identifier::new("key"),
5115 Identifier::new("path"),
5116 Identifier::new(pos2_alias.clone()),
5117 Identifier::new(entity_alias.clone()),
5118 Identifier::new("this"),
5119 ],
5120 alias_explicit_as: false,
5121 alias_keyword: None,
5122 pre_alias_comments: Vec::new(),
5123 trailing_comments: Vec::new(),
5124 inferred_type: None,
5125 }));
5126
5127 select.joins.push(Join {
5128 this: entity_alias_expr,
5129 on: None,
5130 using: Vec::new(),
5131 kind: JoinKind::Cross,
5132 use_inner_keyword: false,
5133 use_outer_keyword: false,
5134 deferred_condition: false,
5135 join_hint: None,
5136 match_condition: None,
5137 pivots: Vec::new(),
5138 comments: Vec::new(),
5139 nesting_group: 0,
5140 directed: false,
5141 });
5142
5143 let pos_col =
5144 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
5145 let pos2_col =
5146 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
5147
5148 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
5149 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
5150 this: Expression::Sub(Box::new(BinaryOp::new(
5151 array_size_call,
5152 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5153 ))),
5154 trailing_comments: Vec::new(),
5155 }));
5156 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
5157 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
5158 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
5159 let or_cond = Expression::Or(Box::new(BinaryOp::new(
5160 eq,
5161 Expression::Paren(Box::new(crate::expressions::Paren {
5162 this: and_cond,
5163 trailing_comments: Vec::new(),
5164 })),
5165 )));
5166
5167 select.where_clause = Some(match select.where_clause.take() {
5168 Some(existing) => Where {
5169 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
5170 },
5171 None => Where { this: or_cond },
5172 });
5173 }
5174
5175 Ok(Expression::Select(Box::new(select)))
5176}
5177
5178fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
5179 let Expression::Function(f) = lat.this.as_ref() else {
5180 return None;
5181 };
5182 if !f.name.eq_ignore_ascii_case("FLATTEN") {
5183 return None;
5184 }
5185
5186 for arg in &f.args {
5187 if let Expression::NamedArgument(na) = arg {
5188 if na.name.name.eq_ignore_ascii_case("INPUT") {
5189 return Some(na.value.clone());
5190 }
5191 }
5192 }
5193 f.args.first().cloned()
5194}
5195
5196fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
5197 let cond = Expression::Eq(Box::new(BinaryOp::new(
5198 Expression::qualified_column("_u", "pos"),
5199 Expression::qualified_column("_u_2", "pos_2"),
5200 )));
5201 let true_expr = Expression::qualified_column("_u_2", "entity");
5202 let iff_expr = Expression::Function(Box::new(Function::new(
5203 "IFF".to_string(),
5204 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
5205 )));
5206
5207 lat.this = Box::new(iff_expr);
5208 if lat.column_aliases.is_empty() {
5209 lat.column_aliases = vec![
5210 "SEQ".to_string(),
5211 "KEY".to_string(),
5212 "PATH".to_string(),
5213 "INDEX".to_string(),
5214 "VALUE".to_string(),
5215 "THIS".to_string(),
5216 ];
5217 }
5218 lat
5219}
5220
5221struct ExplodeInfo {
5223 arg_sql: String,
5225 explode_alias: String,
5227 pos_alias: String,
5229 unnest_source_alias: String,
5231}
5232
5233fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
5234 let is_presto = matches!(
5235 target,
5236 DialectType::Presto | DialectType::Trino | DialectType::Athena
5237 );
5238 let is_bigquery = matches!(target, DialectType::BigQuery);
5239
5240 if !is_presto && !is_bigquery {
5241 return Ok(Expression::Select(Box::new(select)));
5242 }
5243
5244 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
5246 if !has_explode {
5247 return Ok(Expression::Select(Box::new(select)));
5248 }
5249
5250 let mut taken_select_names = std::collections::HashSet::new();
5252 let mut taken_source_names = std::collections::HashSet::new();
5253
5254 for sel in &select.expressions {
5256 if let Some(name) = get_output_name(sel) {
5257 taken_select_names.insert(name);
5258 }
5259 }
5260
5261 for sel in &select.expressions {
5263 let explode_expr = find_explode_in_expr(sel);
5264 if let Some(arg) = explode_expr {
5265 if let Some(name) = get_output_name(&arg) {
5266 taken_select_names.insert(name);
5267 }
5268 }
5269 }
5270
5271 if let Some(ref from) = select.from {
5273 for from_expr in &from.expressions {
5274 collect_source_names(from_expr, &mut taken_source_names);
5275 }
5276 }
5277 for join in &select.joins {
5279 collect_source_names(&join.this, &mut taken_source_names);
5280 }
5281
5282 let series_alias = new_name(&mut taken_select_names, "pos");
5284
5285 let series_source_alias = new_name(&mut taken_source_names, "_u");
5287
5288 let target_dialect = Dialect::get(target);
5290
5291 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
5293 let mut new_projections: Vec<String> = Vec::new();
5294
5295 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
5296 let explode_data = extract_explode_data(sel_expr);
5297
5298 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
5299 let arg_sql = target_dialect
5301 .generate(&arg_expr)
5302 .unwrap_or_else(|_| "NULL".to_string());
5303
5304 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
5305
5306 let explode_alias = if let Some(ref ea) = explicit_alias {
5307 taken_select_names.remove(ea.as_str());
5310 let name = new_name(&mut taken_select_names, ea);
5312 name
5313 } else {
5314 new_name(&mut taken_select_names, "col")
5315 };
5316
5317 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
5318 taken_select_names.remove(pa.as_str());
5320 let name = new_name(&mut taken_select_names, pa);
5321 name
5322 } else {
5323 new_name(&mut taken_select_names, "pos")
5324 };
5325
5326 if is_presto {
5328 let if_col = format!(
5330 "IF({}.{} = {}.{}, {}.{}) AS {}",
5331 series_source_alias,
5332 series_alias,
5333 unnest_source_alias,
5334 pos_alias,
5335 unnest_source_alias,
5336 explode_alias,
5337 explode_alias
5338 );
5339 new_projections.push(if_col);
5340
5341 if is_posexplode {
5343 let if_pos = format!(
5344 "IF({}.{} = {}.{}, {}.{}) AS {}",
5345 series_source_alias,
5346 series_alias,
5347 unnest_source_alias,
5348 pos_alias,
5349 unnest_source_alias,
5350 pos_alias,
5351 pos_alias
5352 );
5353 new_projections.push(if_pos);
5354 }
5355 } else {
5356 let if_col = format!(
5358 "IF({} = {}, {}, NULL) AS {}",
5359 series_alias, pos_alias, explode_alias, explode_alias
5360 );
5361 new_projections.push(if_col);
5362
5363 if is_posexplode {
5365 let if_pos = format!(
5366 "IF({} = {}, {}, NULL) AS {}",
5367 series_alias, pos_alias, pos_alias, pos_alias
5368 );
5369 new_projections.push(if_pos);
5370 }
5371 }
5372
5373 explode_infos.push(ExplodeInfo {
5374 arg_sql,
5375 explode_alias,
5376 pos_alias,
5377 unnest_source_alias,
5378 });
5379 } else {
5380 let sel_sql = target_dialect
5382 .generate(sel_expr)
5383 .unwrap_or_else(|_| "*".to_string());
5384 new_projections.push(sel_sql);
5385 }
5386 }
5387
5388 if explode_infos.is_empty() {
5389 return Ok(Expression::Select(Box::new(select)));
5390 }
5391
5392 let mut from_parts: Vec<String> = Vec::new();
5394
5395 if let Some(ref from) = select.from {
5397 for from_expr in &from.expressions {
5398 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
5399 from_parts.push(from_sql);
5400 }
5401 }
5402
5403 let size_exprs: Vec<String> = explode_infos
5405 .iter()
5406 .map(|info| {
5407 if is_presto {
5408 format!("CARDINALITY({})", info.arg_sql)
5409 } else {
5410 format!("ARRAY_LENGTH({})", info.arg_sql)
5411 }
5412 })
5413 .collect();
5414
5415 let greatest_arg = if size_exprs.len() == 1 {
5416 size_exprs[0].clone()
5417 } else {
5418 format!("GREATEST({})", size_exprs.join(", "))
5419 };
5420
5421 let series_sql = if is_presto {
5424 if size_exprs.len() == 1 {
5426 format!(
5427 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
5428 greatest_arg, series_source_alias, series_alias
5429 )
5430 } else {
5431 format!(
5433 "UNNEST(SEQUENCE(1, {})) AS {}({})",
5434 greatest_arg, series_source_alias, series_alias
5435 )
5436 }
5437 } else {
5438 if size_exprs.len() == 1 {
5440 format!(
5441 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
5442 greatest_arg, series_alias
5443 )
5444 } else {
5445 format!(
5447 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
5448 greatest_arg, series_alias
5449 )
5450 }
5451 };
5452
5453 let mut cross_joins: Vec<String> = Vec::new();
5457
5458 for info in &explode_infos {
5459 cross_joins.push(format!(
5461 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
5462 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
5463 ));
5464 }
5465
5466 let mut where_conditions: Vec<String> = Vec::new();
5468
5469 for info in &explode_infos {
5470 let size_expr = if is_presto {
5471 format!("CARDINALITY({})", info.arg_sql)
5472 } else {
5473 format!("ARRAY_LENGTH({})", info.arg_sql)
5474 };
5475
5476 let cond = if is_presto {
5477 format!(
5478 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
5479 series_src = series_source_alias,
5480 series_al = series_alias,
5481 unnest_src = info.unnest_source_alias,
5482 pos_al = info.pos_alias,
5483 size = size_expr
5484 )
5485 } else {
5486 format!(
5487 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
5488 series_al = series_alias,
5489 pos_al = info.pos_alias,
5490 size = size_expr
5491 )
5492 };
5493
5494 where_conditions.push(cond);
5495 }
5496
5497 let where_sql = if where_conditions.len() == 1 {
5499 where_conditions[0].clone()
5500 } else {
5501 where_conditions
5502 .iter()
5503 .map(|c| format!("({})", c))
5504 .collect::<Vec<_>>()
5505 .join(" AND ")
5506 };
5507
5508 let select_part = new_projections.join(", ");
5510
5511 let from_and_joins = if from_parts.is_empty() {
5513 format!("FROM {} {}", series_sql, cross_joins.join(" "))
5515 } else {
5516 format!(
5517 "FROM {} {} {}",
5518 from_parts.join(", "),
5519 format!("CROSS JOIN {}", series_sql),
5520 cross_joins.join(" ")
5521 )
5522 };
5523
5524 let full_sql = format!(
5525 "SELECT {} {} WHERE {}",
5526 select_part, from_and_joins, where_sql
5527 );
5528
5529 let generic_dialect = Dialect::get(DialectType::Generic);
5532 let parsed = generic_dialect.parse(&full_sql);
5533 match parsed {
5534 Ok(mut stmts) if !stmts.is_empty() => {
5535 let mut result = stmts.remove(0);
5536
5537 if is_bigquery {
5541 convert_unnest_presto_to_bigquery(&mut result);
5542 }
5543
5544 Ok(result)
5545 }
5546 _ => {
5547 Ok(Expression::Select(Box::new(select)))
5549 }
5550 }
5551}
5552
5553fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
5557 match expr {
5558 Expression::Select(ref mut select) => {
5559 if let Some(ref mut from) = select.from {
5561 for from_item in from.expressions.iter_mut() {
5562 convert_unnest_presto_to_bigquery(from_item);
5563 }
5564 }
5565 for join in select.joins.iter_mut() {
5567 convert_unnest_presto_to_bigquery(&mut join.this);
5568 }
5569 }
5570 Expression::Alias(ref alias) => {
5571 if let Expression::Unnest(ref unnest) = alias.this {
5573 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
5574 let col_alias = alias.column_aliases[0].clone();
5575 let pos_alias = alias.column_aliases[1].clone();
5576 let mut new_unnest = unnest.as_ref().clone();
5577 new_unnest.alias = Some(col_alias);
5578 new_unnest.offset_alias = Some(pos_alias);
5579 *expr = Expression::Unnest(Box::new(new_unnest));
5581 }
5582 }
5583 }
5584 _ => {}
5585 }
5586}
5587
5588fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
5591 if !names.contains(base) {
5592 names.insert(base.to_string());
5593 return base.to_string();
5594 }
5595 let mut i = 2;
5596 loop {
5597 let candidate = format!("{}_{}", base, i);
5598 if !names.contains(&candidate) {
5599 names.insert(candidate.clone());
5600 return candidate;
5601 }
5602 i += 1;
5603 }
5604}
5605
5606fn expr_contains_explode(expr: &Expression) -> bool {
5608 match expr {
5609 Expression::Explode(_) => true,
5610 Expression::ExplodeOuter(_) => true,
5611 Expression::Function(f) => {
5612 let name = f.name.to_uppercase();
5613 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
5614 }
5615 Expression::Alias(a) => expr_contains_explode(&a.this),
5616 _ => false,
5617 }
5618}
5619
5620fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
5622 match expr {
5623 Expression::Explode(uf) => Some(uf.this.clone()),
5624 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
5625 Expression::Function(f) => {
5626 let name = f.name.to_uppercase();
5627 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5628 Some(f.args[0].clone())
5629 } else {
5630 None
5631 }
5632 }
5633 Expression::Alias(a) => find_explode_in_expr(&a.this),
5634 _ => None,
5635 }
5636}
5637
5638fn extract_explode_data(
5641 expr: &Expression,
5642) -> Option<(bool, Expression, Option<String>, Option<String>)> {
5643 match expr {
5644 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
5646 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
5647 Expression::Function(f) => {
5649 let name = f.name.to_uppercase();
5650 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5651 Some((true, f.args[0].clone(), None, None))
5652 } else {
5653 None
5654 }
5655 }
5656 Expression::Alias(a) => {
5658 match &a.this {
5659 Expression::Explode(uf) => {
5660 let alias = if !a.alias.is_empty() {
5661 Some(a.alias.name.clone())
5662 } else {
5663 None
5664 };
5665 Some((false, uf.this.clone(), alias, None))
5666 }
5667 Expression::ExplodeOuter(uf) => {
5668 let alias = if !a.alias.is_empty() {
5669 Some(a.alias.name.clone())
5670 } else {
5671 None
5672 };
5673 Some((false, uf.this.clone(), alias, None))
5674 }
5675 Expression::Function(f) => {
5676 let name = f.name.to_uppercase();
5677 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5678 if a.column_aliases.len() == 2 {
5680 let pos_alias = a.column_aliases[0].name.clone();
5681 let col_alias = a.column_aliases[1].name.clone();
5682 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
5683 } else if !a.alias.is_empty() {
5684 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
5686 } else {
5687 Some((true, f.args[0].clone(), None, None))
5688 }
5689 } else {
5690 None
5691 }
5692 }
5693 _ => None,
5694 }
5695 }
5696 _ => None,
5697 }
5698}
5699
5700fn get_output_name(expr: &Expression) -> Option<String> {
5702 match expr {
5703 Expression::Alias(a) => {
5704 if !a.alias.is_empty() {
5705 Some(a.alias.name.clone())
5706 } else {
5707 None
5708 }
5709 }
5710 Expression::Column(c) => Some(c.name.name.clone()),
5711 Expression::Identifier(id) => Some(id.name.clone()),
5712 _ => None,
5713 }
5714}
5715
5716fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
5718 match expr {
5719 Expression::Alias(a) => {
5720 if !a.alias.is_empty() {
5721 names.insert(a.alias.name.clone());
5722 }
5723 }
5724 Expression::Subquery(s) => {
5725 if let Some(ref alias) = s.alias {
5726 names.insert(alias.name.clone());
5727 }
5728 }
5729 Expression::Table(t) => {
5730 if let Some(ref alias) = t.alias {
5731 names.insert(alias.name.clone());
5732 } else {
5733 names.insert(t.name.name.clone());
5734 }
5735 }
5736 Expression::Column(c) => {
5737 names.insert(c.name.name.clone());
5738 }
5739 Expression::Identifier(id) => {
5740 names.insert(id.name.clone());
5741 }
5742 _ => {}
5743 }
5744}
5745
5746pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
5749 use crate::dialects::transform_recursive;
5750 transform_recursive(expr, &strip_unnest_column_refs_single)
5751}
5752
5753fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
5754 if let Expression::Select(mut select) = expr {
5755 for join in select.joins.iter_mut() {
5757 strip_unnest_from_expr(&mut join.this);
5758 }
5759 if let Some(ref mut from) = select.from {
5761 for from_item in from.expressions.iter_mut() {
5762 strip_unnest_from_expr(from_item);
5763 }
5764 }
5765 Ok(Expression::Select(select))
5766 } else {
5767 Ok(expr)
5768 }
5769}
5770
5771fn strip_unnest_from_expr(expr: &mut Expression) {
5774 if let Expression::Alias(ref mut alias) = expr {
5775 if let Expression::Unnest(ref unnest) = alias.this {
5776 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
5777 if is_column_ref {
5778 let inner = unnest.this.clone();
5780 alias.this = inner;
5781 }
5782 }
5783 }
5784}
5785
5786pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
5789 use crate::dialects::transform_recursive;
5790 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
5791}
5792
5793fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
5794 if let Expression::Select(mut select) = expr {
5795 if let Some(ref mut from) = select.from {
5797 for from_item in from.expressions.iter_mut() {
5798 try_wrap_unnest_in_subquery(from_item);
5799 }
5800 }
5801
5802 for join in select.joins.iter_mut() {
5804 try_wrap_unnest_in_subquery(&mut join.this);
5805 }
5806
5807 Ok(Expression::Select(select))
5808 } else {
5809 Ok(expr)
5810 }
5811}
5812
5813fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
5815 match expr {
5816 Expression::Array(arr) => arr
5818 .expressions
5819 .iter()
5820 .any(|e| matches!(e, Expression::Struct(_))),
5821 Expression::ArrayFunc(arr) => arr
5822 .expressions
5823 .iter()
5824 .any(|e| matches!(e, Expression::Struct(_))),
5825 Expression::Cast(c) => {
5827 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
5828 }
5829 _ => false,
5830 }
5831}
5832
5833fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
5836 if let Expression::Alias(ref alias) = expr {
5838 if let Expression::Unnest(ref unnest) = alias.this {
5839 if is_struct_array_unnest_arg(&unnest.this) {
5840 let unnest_clone = (**unnest).clone();
5841 let alias_name = alias.alias.clone();
5842 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
5843 *expr = new_expr;
5844 return;
5845 }
5846 }
5847 }
5848
5849 if let Expression::Unnest(ref unnest) = expr {
5851 if is_struct_array_unnest_arg(&unnest.this) {
5852 let unnest_clone = (**unnest).clone();
5853 let new_expr = make_unnest_subquery(unnest_clone, None);
5854 *expr = new_expr;
5855 }
5856 }
5857}
5858
5859fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
5861 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
5863 name: Identifier::new("max_depth".to_string()),
5864 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
5865 separator: NamedArgSeparator::DArrow,
5866 }));
5867
5868 let mut unnest_args = vec![unnest.this];
5869 unnest_args.extend(unnest.expressions);
5870 unnest_args.push(max_depth_arg);
5871
5872 let unnest_func =
5873 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
5874
5875 let mut inner_select = Select::new();
5877 inner_select.expressions = vec![unnest_func];
5878 let inner_select = Expression::Select(Box::new(inner_select));
5879
5880 let subquery = Subquery {
5882 this: inner_select,
5883 alias,
5884 column_aliases: Vec::new(),
5885 alias_explicit_as: false,
5886 alias_keyword: None,
5887 order_by: None,
5888 limit: None,
5889 offset: None,
5890 distribute_by: None,
5891 sort_by: None,
5892 cluster_by: None,
5893 lateral: false,
5894 modifiers_inside: false,
5895 trailing_comments: Vec::new(),
5896 inferred_type: None,
5897 };
5898
5899 Expression::Subquery(Box::new(subquery))
5900}
5901
5902pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
5914 use crate::expressions::{Limit as LimitClause, Offset as OffsetClause, OrderBy, Star};
5915
5916 match expr {
5917 Expression::Union(mut u) => {
5918 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
5921 if let Expression::Select(ref mut right_select) = u.right {
5923 if right_select.order_by.is_some()
5924 || right_select.limit.is_some()
5925 || right_select.offset.is_some()
5926 {
5927 u.order_by = right_select.order_by.take();
5929 u.limit = right_select.limit.take().map(|l| Box::new(l.this));
5930 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
5931 }
5932 }
5933 }
5934
5935 let has_order_or_limit =
5936 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
5937 if has_order_or_limit {
5938 let order_by: Option<OrderBy> = u.order_by.take();
5940 let union_limit: Option<Box<Expression>> = u.limit.take();
5941 let union_offset: Option<Box<Expression>> = u.offset.take();
5942
5943 let select_limit: Option<LimitClause> = union_limit.map(|l| LimitClause {
5945 this: *l,
5946 percent: false,
5947 comments: Vec::new(),
5948 });
5949
5950 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
5952 this: *o,
5953 rows: None,
5954 });
5955
5956 let subquery = Subquery {
5958 this: Expression::Union(u),
5959 alias: Some(Identifier::new("_l_0")),
5960 column_aliases: Vec::new(),
5961 alias_explicit_as: true,
5962 alias_keyword: None,
5963 lateral: false,
5964 modifiers_inside: false,
5965 order_by: None,
5966 limit: None,
5967 offset: None,
5968 distribute_by: None,
5969 sort_by: None,
5970 cluster_by: None,
5971 trailing_comments: Vec::new(),
5972 inferred_type: None,
5973 };
5974
5975 let mut select = Select::default();
5977 select.expressions = vec![Expression::Star(Star {
5978 table: None,
5979 except: None,
5980 replace: None,
5981 rename: None,
5982 trailing_comments: Vec::new(),
5983 span: None,
5984 })];
5985 select.from = Some(From {
5986 expressions: vec![Expression::Subquery(Box::new(subquery))],
5987 });
5988 select.order_by = order_by;
5989 select.limit = select_limit;
5990 select.offset = select_offset;
5991
5992 Ok(Expression::Select(Box::new(select)))
5993 } else {
5994 Ok(Expression::Union(u))
5995 }
5996 }
5997 _ => Ok(expr),
5998 }
5999}
6000
6001pub fn expand_like_any(expr: Expression) -> Result<Expression> {
6009 use crate::expressions::{BinaryOp, LikeOp, Paren};
6010
6011 const LIKE_ALL_MARKER: &str = "__LIKE_ALL_EXPANSION__";
6014
6015 fn unwrap_parens(e: &Expression) -> &Expression {
6016 match e {
6017 Expression::Paren(p) => unwrap_parens(&p.this),
6018 _ => e,
6019 }
6020 }
6021
6022 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
6023 let inner = unwrap_parens(e);
6024 match inner {
6025 Expression::Tuple(t) => Some(t.expressions.clone()),
6026 _ if !matches!(e, Expression::Tuple(_)) => Some(vec![inner.clone()]),
6028 _ => None,
6029 }
6030 }
6031
6032 fn expand_like_quantifier(
6034 op: &LikeOp,
6035 values: Vec<Expression>,
6036 is_ilike: bool,
6037 combiner: fn(Expression, Expression) -> Expression,
6038 wrap_marker: bool,
6039 ) -> Expression {
6040 let num_values = values.len();
6041 let mut result: Option<Expression> = None;
6042 for val in values {
6043 let like = if is_ilike {
6044 Expression::ILike(Box::new(LikeOp {
6045 left: op.left.clone(),
6046 right: val,
6047 escape: op.escape.clone(),
6048 quantifier: None,
6049 inferred_type: None,
6050 }))
6051 } else {
6052 Expression::Like(Box::new(LikeOp {
6053 left: op.left.clone(),
6054 right: val,
6055 escape: op.escape.clone(),
6056 quantifier: None,
6057 inferred_type: None,
6058 }))
6059 };
6060 result = Some(match result {
6061 None => like,
6062 Some(prev) => combiner(prev, like),
6063 });
6064 }
6065 let expanded = result.unwrap_or_else(|| unreachable!("values is non-empty"));
6066 if wrap_marker && num_values > 1 {
6070 Expression::Paren(Box::new(Paren {
6071 this: expanded,
6072 trailing_comments: vec![LIKE_ALL_MARKER.to_string()],
6073 }))
6074 } else {
6075 expanded
6076 }
6077 }
6078
6079 fn or_combiner(a: Expression, b: Expression) -> Expression {
6080 Expression::Or(Box::new(BinaryOp::new(a, b)))
6081 }
6082
6083 fn and_combiner(a: Expression, b: Expression) -> Expression {
6084 Expression::And(Box::new(BinaryOp::new(a, b)))
6085 }
6086
6087 fn is_like_all_marker(p: &Paren) -> bool {
6088 p.trailing_comments.len() == 1 && p.trailing_comments[0] == LIKE_ALL_MARKER
6089 }
6090
6091 let result = transform_recursive(expr, &|e| {
6099 match e {
6100 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6102 if let Some(values) = extract_tuple_values(&op.right) {
6103 if values.is_empty() {
6104 return Ok(e);
6105 }
6106 Ok(expand_like_quantifier(
6107 op,
6108 values,
6109 false,
6110 or_combiner,
6111 false,
6112 ))
6113 } else {
6114 Ok(e)
6115 }
6116 }
6117 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6119 if let Some(values) = extract_tuple_values(&op.right) {
6120 if values.is_empty() {
6121 return Ok(e);
6122 }
6123 Ok(expand_like_quantifier(
6124 op,
6125 values,
6126 false,
6127 and_combiner,
6128 true,
6129 ))
6130 } else {
6131 Ok(e)
6132 }
6133 }
6134 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6136 if let Some(values) = extract_tuple_values(&op.right) {
6137 if values.is_empty() {
6138 return Ok(e);
6139 }
6140 Ok(expand_like_quantifier(op, values, true, or_combiner, false))
6141 } else {
6142 Ok(e)
6143 }
6144 }
6145 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6147 if let Some(values) = extract_tuple_values(&op.right) {
6148 if values.is_empty() {
6149 return Ok(e);
6150 }
6151 Ok(expand_like_quantifier(op, values, true, and_combiner, true))
6152 } else {
6153 Ok(e)
6154 }
6155 }
6156 Expression::And(mut op) => {
6161 if matches!(&op.left, Expression::Or(_)) {
6162 op.left = Expression::Paren(Box::new(Paren {
6163 this: op.left,
6164 trailing_comments: vec![],
6165 }));
6166 }
6167 if matches!(&op.right, Expression::Or(_)) {
6168 op.right = Expression::Paren(Box::new(Paren {
6169 this: op.right,
6170 trailing_comments: vec![],
6171 }));
6172 }
6173 Ok(Expression::And(op))
6174 }
6175 Expression::Or(mut op) => {
6178 if let Expression::Paren(ref mut p) = op.left {
6179 if is_like_all_marker(p) {
6180 p.trailing_comments.clear();
6181 }
6182 }
6183 if let Expression::Paren(ref mut p) = op.right {
6184 if is_like_all_marker(p) {
6185 p.trailing_comments.clear();
6186 }
6187 }
6188 Ok(Expression::Or(op))
6189 }
6190 _ => Ok(e),
6191 }
6192 })?;
6193
6194 transform_recursive(result, &|e| {
6198 if let Expression::Paren(p) = &e {
6199 if is_like_all_marker(p) {
6200 let Expression::Paren(p) = e else {
6201 unreachable!()
6202 };
6203 return Ok(p.this);
6204 }
6205 }
6206 Ok(e)
6207 })
6208}
6209
6210pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
6218 use crate::expressions::Alias;
6219
6220 fn add_self_aliases_to_select(select: &mut Select) {
6221 let new_expressions: Vec<Expression> = select
6222 .expressions
6223 .iter()
6224 .map(|e| {
6225 match e {
6226 Expression::Column(col) => {
6228 let alias_name = col.name.clone();
6229 Expression::Alias(Box::new(Alias {
6230 this: e.clone(),
6231 alias: alias_name,
6232 column_aliases: Vec::new(),
6233 alias_explicit_as: false,
6234 alias_keyword: None,
6235 pre_alias_comments: Vec::new(),
6236 trailing_comments: Vec::new(),
6237 inferred_type: None,
6238 }))
6239 }
6240 _ => e.clone(),
6242 }
6243 })
6244 .collect();
6245 select.expressions = new_expressions;
6246 }
6247
6248 fn walk_and_qualify(expr: &mut Expression) {
6249 match expr {
6250 Expression::Select(ref mut select) => {
6251 if let Some(ref mut from) = select.from {
6253 for e in from.expressions.iter_mut() {
6254 qualify_subquery_expr(e);
6255 walk_and_qualify(e);
6256 }
6257 }
6258 for join in select.joins.iter_mut() {
6260 qualify_subquery_expr(&mut join.this);
6261 walk_and_qualify(&mut join.this);
6262 }
6263 for e in select.expressions.iter_mut() {
6265 walk_and_qualify(e);
6266 }
6267 if let Some(ref mut w) = select.where_clause {
6269 walk_and_qualify(&mut w.this);
6270 }
6271 }
6272 Expression::Subquery(ref mut subquery) => {
6273 walk_and_qualify(&mut subquery.this);
6274 }
6275 Expression::Union(ref mut u) => {
6276 walk_and_qualify(&mut u.left);
6277 walk_and_qualify(&mut u.right);
6278 }
6279 Expression::Intersect(ref mut i) => {
6280 walk_and_qualify(&mut i.left);
6281 walk_and_qualify(&mut i.right);
6282 }
6283 Expression::Except(ref mut e) => {
6284 walk_and_qualify(&mut e.left);
6285 walk_and_qualify(&mut e.right);
6286 }
6287 Expression::Cte(ref mut cte) => {
6288 walk_and_qualify(&mut cte.this);
6289 }
6290 _ => {}
6291 }
6292 }
6293
6294 fn qualify_subquery_expr(expr: &mut Expression) {
6295 match expr {
6296 Expression::Subquery(ref mut subquery) => {
6297 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
6299 if let Expression::Select(ref mut inner_select) = subquery.this {
6300 let has_star = inner_select
6302 .expressions
6303 .iter()
6304 .any(|e| matches!(e, Expression::Star(_)));
6305 if !has_star {
6306 add_self_aliases_to_select(inner_select);
6307 }
6308 }
6309 }
6310 walk_and_qualify(&mut subquery.this);
6312 }
6313 Expression::Alias(ref mut alias) => {
6314 qualify_subquery_expr(&mut alias.this);
6315 }
6316 _ => {}
6317 }
6318 }
6319
6320 let mut result = expr;
6321 walk_and_qualify(&mut result);
6322
6323 if let Expression::Select(ref mut select) = result {
6325 if let Some(ref mut with) = select.with {
6326 for cte in with.ctes.iter_mut() {
6327 if cte.columns.is_empty() {
6329 walk_and_qualify(&mut cte.this);
6331 }
6332 }
6333 }
6334 }
6335
6336 Ok(result)
6337}
6338
6339#[cfg(test)]
6340mod tests {
6341 use super::*;
6342 use crate::dialects::{Dialect, DialectType};
6343 use crate::expressions::Column;
6344
6345 fn gen(expr: &Expression) -> String {
6346 let dialect = Dialect::get(DialectType::Generic);
6347 dialect.generate(expr).unwrap()
6348 }
6349
6350 #[test]
6351 fn test_preprocess() {
6352 let expr = Expression::Boolean(BooleanLiteral { value: true });
6353 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
6354 assert!(
6355 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6356 );
6357 }
6358
6359 #[test]
6360 fn test_preprocess_chain() {
6361 let expr = Expression::Boolean(BooleanLiteral { value: true });
6363 let transforms: Vec<fn(Expression) -> Result<Expression>> =
6365 vec![replace_bool_with_int, replace_int_with_bool];
6366 let result = preprocess(expr, &transforms).unwrap();
6367 if let Expression::Boolean(b) = result {
6370 assert!(b.value);
6371 } else {
6372 panic!("Expected boolean literal");
6373 }
6374 }
6375
6376 #[test]
6377 fn test_unnest_to_explode() {
6378 let unnest = Expression::Unnest(Box::new(UnnestFunc {
6379 this: Expression::boxed_column(Column {
6380 name: Identifier::new("arr".to_string()),
6381 table: None,
6382 join_mark: false,
6383 trailing_comments: vec![],
6384 span: None,
6385 inferred_type: None,
6386 }),
6387 expressions: Vec::new(),
6388 with_ordinality: false,
6389 alias: None,
6390 offset_alias: None,
6391 inferred_type: None,
6392 }));
6393
6394 let result = unnest_to_explode(unnest).unwrap();
6395 assert!(matches!(result, Expression::Explode(_)));
6396 }
6397
6398 #[test]
6399 fn test_explode_to_unnest() {
6400 let explode = Expression::Explode(Box::new(UnaryFunc {
6401 this: Expression::boxed_column(Column {
6402 name: Identifier::new("arr".to_string()),
6403 table: None,
6404 join_mark: false,
6405 trailing_comments: vec![],
6406 span: None,
6407 inferred_type: None,
6408 }),
6409 original_name: None,
6410 inferred_type: None,
6411 }));
6412
6413 let result = explode_to_unnest(explode).unwrap();
6414 assert!(matches!(result, Expression::Unnest(_)));
6415 }
6416
6417 #[test]
6418 fn test_replace_bool_with_int() {
6419 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
6420 let result = replace_bool_with_int(true_expr).unwrap();
6421 if let Expression::Literal(lit) = result {
6422 if let Literal::Number(n) = lit.as_ref() {
6423 assert_eq!(n, "1");
6424 }
6425 } else {
6426 panic!("Expected number literal");
6427 }
6428
6429 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
6430 let result = replace_bool_with_int(false_expr).unwrap();
6431 if let Expression::Literal(lit) = result {
6432 if let Literal::Number(n) = lit.as_ref() {
6433 assert_eq!(n, "0");
6434 }
6435 } else {
6436 panic!("Expected number literal");
6437 }
6438 }
6439
6440 #[test]
6441 fn test_replace_int_with_bool() {
6442 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
6443 let result = replace_int_with_bool(one_expr).unwrap();
6444 if let Expression::Boolean(b) = result {
6445 assert!(b.value);
6446 } else {
6447 panic!("Expected boolean true");
6448 }
6449
6450 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
6451 let result = replace_int_with_bool(zero_expr).unwrap();
6452 if let Expression::Boolean(b) = result {
6453 assert!(!b.value);
6454 } else {
6455 panic!("Expected boolean false");
6456 }
6457
6458 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
6460 let result = replace_int_with_bool(two_expr).unwrap();
6461 assert!(
6462 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6463 );
6464 }
6465
6466 #[test]
6467 fn test_strip_data_type_params() {
6468 let decimal = DataType::Decimal {
6470 precision: Some(10),
6471 scale: Some(2),
6472 };
6473 let stripped = strip_data_type_params(decimal);
6474 assert_eq!(
6475 stripped,
6476 DataType::Decimal {
6477 precision: None,
6478 scale: None
6479 }
6480 );
6481
6482 let varchar = DataType::VarChar {
6484 length: Some(255),
6485 parenthesized_length: false,
6486 };
6487 let stripped = strip_data_type_params(varchar);
6488 assert_eq!(
6489 stripped,
6490 DataType::VarChar {
6491 length: None,
6492 parenthesized_length: false
6493 }
6494 );
6495
6496 let char_type = DataType::Char { length: Some(10) };
6498 let stripped = strip_data_type_params(char_type);
6499 assert_eq!(stripped, DataType::Char { length: None });
6500
6501 let timestamp = DataType::Timestamp {
6503 precision: Some(6),
6504 timezone: true,
6505 };
6506 let stripped = strip_data_type_params(timestamp);
6507 assert_eq!(
6508 stripped,
6509 DataType::Timestamp {
6510 precision: None,
6511 timezone: true
6512 }
6513 );
6514
6515 let array = DataType::Array {
6517 element_type: Box::new(DataType::VarChar {
6518 length: Some(100),
6519 parenthesized_length: false,
6520 }),
6521 dimension: None,
6522 };
6523 let stripped = strip_data_type_params(array);
6524 assert_eq!(
6525 stripped,
6526 DataType::Array {
6527 element_type: Box::new(DataType::VarChar {
6528 length: None,
6529 parenthesized_length: false
6530 }),
6531 dimension: None,
6532 }
6533 );
6534
6535 let text = DataType::Text;
6537 let stripped = strip_data_type_params(text);
6538 assert_eq!(stripped, DataType::Text);
6539 }
6540
6541 #[test]
6542 fn test_remove_precision_parameterized_types_cast() {
6543 let cast_expr = Expression::Cast(Box::new(Cast {
6545 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6546 to: DataType::Decimal {
6547 precision: Some(10),
6548 scale: Some(2),
6549 },
6550 trailing_comments: vec![],
6551 double_colon_syntax: false,
6552 format: None,
6553 default: None,
6554 inferred_type: None,
6555 }));
6556
6557 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6558 if let Expression::Cast(cast) = result {
6559 assert_eq!(
6560 cast.to,
6561 DataType::Decimal {
6562 precision: None,
6563 scale: None
6564 }
6565 );
6566 } else {
6567 panic!("Expected Cast expression");
6568 }
6569 }
6570
6571 #[test]
6572 fn test_remove_precision_parameterized_types_varchar() {
6573 let cast_expr = Expression::Cast(Box::new(Cast {
6575 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
6576 to: DataType::VarChar {
6577 length: Some(10),
6578 parenthesized_length: false,
6579 },
6580 trailing_comments: vec![],
6581 double_colon_syntax: false,
6582 format: None,
6583 default: None,
6584 inferred_type: None,
6585 }));
6586
6587 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6588 if let Expression::Cast(cast) = result {
6589 assert_eq!(
6590 cast.to,
6591 DataType::VarChar {
6592 length: None,
6593 parenthesized_length: false
6594 }
6595 );
6596 } else {
6597 panic!("Expected Cast expression");
6598 }
6599 }
6600
6601 #[test]
6602 fn test_remove_precision_direct_cast() {
6603 let cast = Expression::Cast(Box::new(Cast {
6607 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6608 to: DataType::Decimal {
6609 precision: Some(10),
6610 scale: Some(2),
6611 },
6612 trailing_comments: vec![],
6613 double_colon_syntax: false,
6614 format: None,
6615 default: None,
6616 inferred_type: None,
6617 }));
6618
6619 let transformed = remove_precision_parameterized_types(cast).unwrap();
6620 let generated = gen(&transformed);
6621
6622 assert!(generated.contains("DECIMAL"));
6624 assert!(!generated.contains("(10"));
6625 }
6626
6627 #[test]
6628 fn test_epoch_cast_to_ts() {
6629 let cast_expr = Expression::Cast(Box::new(Cast {
6631 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
6632 to: DataType::Timestamp {
6633 precision: None,
6634 timezone: false,
6635 },
6636 trailing_comments: vec![],
6637 double_colon_syntax: false,
6638 format: None,
6639 default: None,
6640 inferred_type: None,
6641 }));
6642
6643 let result = epoch_cast_to_ts(cast_expr).unwrap();
6644 if let Expression::Cast(cast) = result {
6645 if let Expression::Literal(lit) = cast.this {
6646 if let Literal::String(s) = lit.as_ref() {
6647 assert_eq!(s, "1970-01-01 00:00:00");
6648 }
6649 } else {
6650 panic!("Expected string literal");
6651 }
6652 } else {
6653 panic!("Expected Cast expression");
6654 }
6655 }
6656
6657 #[test]
6658 fn test_epoch_cast_to_ts_preserves_non_epoch() {
6659 let cast_expr = Expression::Cast(Box::new(Cast {
6661 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
6662 to: DataType::Timestamp {
6663 precision: None,
6664 timezone: false,
6665 },
6666 trailing_comments: vec![],
6667 double_colon_syntax: false,
6668 format: None,
6669 default: None,
6670 inferred_type: None,
6671 }));
6672
6673 let result = epoch_cast_to_ts(cast_expr).unwrap();
6674 if let Expression::Cast(cast) = result {
6675 if let Expression::Literal(lit) = cast.this {
6676 if let Literal::String(s) = lit.as_ref() {
6677 assert_eq!(s, "2024-01-15");
6678 }
6679 } else {
6680 panic!("Expected string literal");
6681 }
6682 } else {
6683 panic!("Expected Cast expression");
6684 }
6685 }
6686
6687 #[test]
6688 fn test_unqualify_columns() {
6689 let col = Expression::boxed_column(Column {
6691 name: Identifier::new("id".to_string()),
6692 table: Some(Identifier::new("users".to_string())),
6693 join_mark: false,
6694 trailing_comments: vec![],
6695 span: None,
6696 inferred_type: None,
6697 });
6698
6699 let result = unqualify_columns(col).unwrap();
6700 if let Expression::Column(c) = result {
6701 assert!(c.table.is_none());
6702 assert_eq!(c.name.name, "id");
6703 } else {
6704 panic!("Expected Column expression");
6705 }
6706 }
6707
6708 #[test]
6709 fn test_is_temporal_type() {
6710 assert!(is_temporal_type(&DataType::Date));
6711 assert!(is_temporal_type(&DataType::Timestamp {
6712 precision: None,
6713 timezone: false
6714 }));
6715 assert!(is_temporal_type(&DataType::Time {
6716 precision: None,
6717 timezone: false
6718 }));
6719 assert!(!is_temporal_type(&DataType::Int {
6720 length: None,
6721 integer_spelling: false
6722 }));
6723 assert!(!is_temporal_type(&DataType::VarChar {
6724 length: None,
6725 parenthesized_length: false
6726 }));
6727 }
6728
6729 #[test]
6730 fn test_eliminate_semi_join_basic() {
6731 use crate::expressions::{Join, TableRef};
6732
6733 let select = Expression::Select(Box::new(Select {
6735 expressions: vec![Expression::boxed_column(Column {
6736 name: Identifier::new("a".to_string()),
6737 table: None,
6738 join_mark: false,
6739 trailing_comments: vec![],
6740 span: None,
6741 inferred_type: None,
6742 })],
6743 from: Some(From {
6744 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
6745 }),
6746 joins: vec![Join {
6747 this: Expression::Table(Box::new(TableRef::new("t2"))),
6748 kind: JoinKind::Semi,
6749 on: Some(Expression::Eq(Box::new(BinaryOp {
6750 left: Expression::boxed_column(Column {
6751 name: Identifier::new("x".to_string()),
6752 table: None,
6753 join_mark: false,
6754 trailing_comments: vec![],
6755 span: None,
6756 inferred_type: None,
6757 }),
6758 right: Expression::boxed_column(Column {
6759 name: Identifier::new("y".to_string()),
6760 table: None,
6761 join_mark: false,
6762 trailing_comments: vec![],
6763 span: None,
6764 inferred_type: None,
6765 }),
6766 left_comments: vec![],
6767 operator_comments: vec![],
6768 trailing_comments: vec![],
6769 inferred_type: None,
6770 }))),
6771 using: vec![],
6772 use_inner_keyword: false,
6773 use_outer_keyword: false,
6774 deferred_condition: false,
6775 join_hint: None,
6776 match_condition: None,
6777 pivots: Vec::new(),
6778 comments: Vec::new(),
6779 nesting_group: 0,
6780 directed: false,
6781 }],
6782 ..Select::new()
6783 }));
6784
6785 let result = eliminate_semi_and_anti_joins(select).unwrap();
6786 if let Expression::Select(s) = result {
6787 assert!(s.joins.is_empty());
6789 assert!(s.where_clause.is_some());
6791 } else {
6792 panic!("Expected Select expression");
6793 }
6794 }
6795
6796 #[test]
6797 fn test_no_ilike_sql() {
6798 use crate::expressions::LikeOp;
6799
6800 let ilike_expr = Expression::ILike(Box::new(LikeOp {
6802 left: Expression::boxed_column(Column {
6803 name: Identifier::new("name".to_string()),
6804 table: None,
6805 join_mark: false,
6806 trailing_comments: vec![],
6807 span: None,
6808 inferred_type: None,
6809 }),
6810 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
6811 escape: None,
6812 quantifier: None,
6813 inferred_type: None,
6814 }));
6815
6816 let result = no_ilike_sql(ilike_expr).unwrap();
6817 if let Expression::Like(like) = result {
6818 if let Expression::Function(f) = &like.left {
6820 assert_eq!(f.name, "LOWER");
6821 } else {
6822 panic!("Expected LOWER function on left");
6823 }
6824 if let Expression::Function(f) = &like.right {
6826 assert_eq!(f.name, "LOWER");
6827 } else {
6828 panic!("Expected LOWER function on right");
6829 }
6830 } else {
6831 panic!("Expected Like expression");
6832 }
6833 }
6834
6835 #[test]
6836 fn test_no_trycast_sql() {
6837 let trycast_expr = Expression::TryCast(Box::new(Cast {
6839 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6840 to: DataType::Int {
6841 length: None,
6842 integer_spelling: false,
6843 },
6844 trailing_comments: vec![],
6845 double_colon_syntax: false,
6846 format: None,
6847 default: None,
6848 inferred_type: None,
6849 }));
6850
6851 let result = no_trycast_sql(trycast_expr).unwrap();
6852 assert!(matches!(result, Expression::Cast(_)));
6853 }
6854
6855 #[test]
6856 fn test_no_safe_cast_sql() {
6857 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
6859 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6860 to: DataType::Int {
6861 length: None,
6862 integer_spelling: false,
6863 },
6864 trailing_comments: vec![],
6865 double_colon_syntax: false,
6866 format: None,
6867 default: None,
6868 inferred_type: None,
6869 }));
6870
6871 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
6872 assert!(matches!(result, Expression::Cast(_)));
6873 }
6874
6875 #[test]
6876 fn test_explode_to_unnest_presto() {
6877 let spark = Dialect::get(DialectType::Spark);
6878 let result = spark
6879 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
6880 .unwrap();
6881 assert_eq!(
6882 result[0],
6883 "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))"
6884 );
6885 }
6886
6887 #[test]
6888 fn test_explode_to_unnest_bigquery() {
6889 let spark = Dialect::get(DialectType::Spark);
6890 let result = spark
6891 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
6892 .unwrap();
6893 assert_eq!(
6894 result[0],
6895 "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))"
6896 );
6897 }
6898}