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 inferred_type: arr.inferred_type.clone(),
4363 })));
4364 }
4365 }
4366
4367 if let Expression::ArrayFunc(ref arr) = expr {
4369 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
4370 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
4371 expressions: new_elements,
4372 bracket_notation: arr.bracket_notation,
4373 use_list_keyword: arr.use_list_keyword,
4374 inferred_type: arr.inferred_type.clone(),
4375 })));
4376 }
4377 }
4378
4379 Ok(expr)
4380}
4381
4382pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
4385 use crate::dialects::transform_recursive;
4386 transform_recursive(expr, &unnest_alias_transform_single_select)
4387}
4388
4389pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
4392 use crate::dialects::transform_recursive;
4393 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
4394}
4395
4396fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
4397 if let Expression::Select(mut select) = expr {
4398 if let Some(ref mut from) = select.from {
4399 if from.expressions.len() > 1 {
4400 let mut new_from_exprs = Vec::new();
4401 let mut new_cross_joins = Vec::new();
4402
4403 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4404 if idx == 0 {
4405 new_from_exprs.push(from_item);
4406 } else {
4407 let is_unnest = match &from_item {
4408 Expression::Unnest(_) => true,
4409 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4410 _ => false,
4411 };
4412
4413 if is_unnest {
4414 new_cross_joins.push(crate::expressions::Join {
4415 this: from_item,
4416 on: None,
4417 using: Vec::new(),
4418 kind: JoinKind::Cross,
4419 use_inner_keyword: false,
4420 use_outer_keyword: false,
4421 deferred_condition: false,
4422 join_hint: None,
4423 match_condition: None,
4424 pivots: Vec::new(),
4425 comments: Vec::new(),
4426 nesting_group: 0,
4427 directed: false,
4428 });
4429 } else {
4430 new_from_exprs.push(from_item);
4431 }
4432 }
4433 }
4434
4435 from.expressions = new_from_exprs;
4436 new_cross_joins.append(&mut select.joins);
4437 select.joins = new_cross_joins;
4438 }
4439 }
4440
4441 Ok(Expression::Select(select))
4442 } else {
4443 Ok(expr)
4444 }
4445}
4446
4447pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
4451 use crate::dialects::transform_recursive;
4452 transform_recursive(expr, &wrap_unnest_join_aliases_single)
4453}
4454
4455fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
4456 if let Expression::Select(mut select) = expr {
4457 for join in &mut select.joins {
4459 wrap_unnest_alias_in_join_item(&mut join.this);
4460 }
4461 Ok(Expression::Select(select))
4462 } else {
4463 Ok(expr)
4464 }
4465}
4466
4467fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
4469 use crate::expressions::Identifier;
4470 if let Expression::Alias(alias) = expr {
4471 let is_unnest = match &alias.this {
4473 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
4474 _ => false,
4475 };
4476
4477 if is_unnest && alias.column_aliases.is_empty() {
4478 let original_alias_name = alias.alias.name.clone();
4480 alias.alias = Identifier {
4481 name: "_u".to_string(),
4482 quoted: false,
4483 trailing_comments: Vec::new(),
4484 span: None,
4485 };
4486 alias.column_aliases = vec![Identifier {
4487 name: original_alias_name,
4488 quoted: false,
4489 trailing_comments: Vec::new(),
4490 span: None,
4491 }];
4492 }
4493 }
4494}
4495
4496fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
4497 if let Expression::Select(mut select) = expr {
4498 let mut counter = 0usize;
4499
4500 if let Some(ref mut from) = select.from {
4502 for from_item in from.expressions.iter_mut() {
4504 convert_unnest_alias_in_from(from_item, &mut counter);
4505 }
4506
4507 if from.expressions.len() > 1 {
4509 let mut new_from_exprs = Vec::new();
4510 let mut new_cross_joins = Vec::new();
4511
4512 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4513 if idx == 0 {
4514 new_from_exprs.push(from_item);
4516 } else {
4517 let is_unnest = match &from_item {
4519 Expression::Unnest(_) => true,
4520 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4521 _ => false,
4522 };
4523
4524 if is_unnest {
4525 new_cross_joins.push(crate::expressions::Join {
4527 this: from_item,
4528 on: None,
4529 using: Vec::new(),
4530 kind: JoinKind::Cross,
4531 use_inner_keyword: false,
4532 use_outer_keyword: false,
4533 deferred_condition: false,
4534 join_hint: None,
4535 match_condition: None,
4536 pivots: Vec::new(),
4537 comments: Vec::new(),
4538 nesting_group: 0,
4539 directed: false,
4540 });
4541 } else {
4542 new_from_exprs.push(from_item);
4544 }
4545 }
4546 }
4547
4548 from.expressions = new_from_exprs;
4549 new_cross_joins.append(&mut select.joins);
4551 select.joins = new_cross_joins;
4552 }
4553 }
4554
4555 for join in select.joins.iter_mut() {
4557 convert_unnest_alias_in_from(&mut join.this, &mut counter);
4558 }
4559
4560 Ok(Expression::Select(select))
4561 } else {
4562 Ok(expr)
4563 }
4564}
4565
4566fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
4567 use crate::expressions::Identifier;
4568
4569 if let Expression::Alias(ref mut alias) = expr {
4570 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
4572 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
4573
4574 if is_unnest && alias.column_aliases.is_empty() {
4575 let col_alias = alias.alias.clone();
4577 alias.column_aliases = vec![col_alias];
4578 alias.alias = Identifier::new(format!("_t{}", counter));
4579 *counter += 1;
4580 }
4581 }
4582}
4583
4584pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
4591 use crate::expressions::{Alias, Function};
4592
4593 match expr {
4594 Expression::Select(mut select) => {
4595 let mut new_expressions = Vec::new();
4597 let mut changed = false;
4598
4599 for sel_expr in select.expressions.drain(..) {
4600 if let Expression::Alias(ref alias_box) = sel_expr {
4602 if let Expression::Function(ref func) = alias_box.this {
4603 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4604 let arg = func.args[0].clone();
4605 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4607 (
4608 alias_box.column_aliases[0].name.clone(),
4609 alias_box.column_aliases[1].name.clone(),
4610 )
4611 } else if !alias_box.alias.is_empty() {
4612 ("pos".to_string(), alias_box.alias.name.clone())
4614 } else {
4615 ("pos".to_string(), "col".to_string())
4616 };
4617
4618 let gen_subscripts = Expression::Function(Box::new(Function::new(
4620 "GENERATE_SUBSCRIPTS".to_string(),
4621 vec![
4622 arg.clone(),
4623 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4624 ],
4625 )));
4626 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4627 gen_subscripts,
4628 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4629 )));
4630 let pos_alias = Expression::Alias(Box::new(Alias {
4631 this: sub_one,
4632 alias: Identifier::new(pos_name),
4633 column_aliases: Vec::new(),
4634 alias_explicit_as: false,
4635 alias_keyword: None,
4636 pre_alias_comments: Vec::new(),
4637 trailing_comments: Vec::new(),
4638 inferred_type: None,
4639 }));
4640
4641 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4643 this: arg,
4644 expressions: Vec::new(),
4645 with_ordinality: false,
4646 alias: None,
4647 offset_alias: None,
4648 inferred_type: None,
4649 }));
4650 let col_alias = Expression::Alias(Box::new(Alias {
4651 this: unnest,
4652 alias: Identifier::new(col_name),
4653 column_aliases: Vec::new(),
4654 alias_explicit_as: false,
4655 alias_keyword: None,
4656 pre_alias_comments: Vec::new(),
4657 trailing_comments: Vec::new(),
4658 inferred_type: None,
4659 }));
4660
4661 new_expressions.push(pos_alias);
4662 new_expressions.push(col_alias);
4663 changed = true;
4664 continue;
4665 }
4666 }
4667 }
4668
4669 if let Expression::Function(ref func) = sel_expr {
4671 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4672 let arg = func.args[0].clone();
4673 let pos_name = "pos";
4674 let col_name = "col";
4675
4676 let gen_subscripts = Expression::Function(Box::new(Function::new(
4678 "GENERATE_SUBSCRIPTS".to_string(),
4679 vec![
4680 arg.clone(),
4681 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4682 ],
4683 )));
4684 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4685 gen_subscripts,
4686 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4687 )));
4688 let pos_alias = Expression::Alias(Box::new(Alias {
4689 this: sub_one,
4690 alias: Identifier::new(pos_name),
4691 column_aliases: Vec::new(),
4692 alias_explicit_as: false,
4693 alias_keyword: None,
4694 pre_alias_comments: Vec::new(),
4695 trailing_comments: Vec::new(),
4696 inferred_type: None,
4697 }));
4698
4699 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4701 this: arg,
4702 expressions: Vec::new(),
4703 with_ordinality: false,
4704 alias: None,
4705 offset_alias: None,
4706 inferred_type: None,
4707 }));
4708 let col_alias = Expression::Alias(Box::new(Alias {
4709 this: unnest,
4710 alias: Identifier::new(col_name),
4711 column_aliases: Vec::new(),
4712 alias_explicit_as: false,
4713 alias_keyword: None,
4714 pre_alias_comments: Vec::new(),
4715 trailing_comments: Vec::new(),
4716 inferred_type: None,
4717 }));
4718
4719 new_expressions.push(pos_alias);
4720 new_expressions.push(col_alias);
4721 changed = true;
4722 continue;
4723 }
4724 }
4725
4726 new_expressions.push(sel_expr);
4728 }
4729
4730 if changed {
4731 select.expressions = new_expressions;
4732 } else {
4733 select.expressions = new_expressions;
4734 }
4735
4736 if let Some(ref mut from) = select.from {
4739 expand_posexplode_in_from_duckdb(from)?;
4740 }
4741
4742 Ok(Expression::Select(select))
4743 }
4744 other => Ok(other),
4745 }
4746}
4747
4748fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
4750 use crate::expressions::{Alias, Function};
4751
4752 let mut new_expressions = Vec::new();
4753 let mut _changed = false;
4754
4755 for table_expr in from.expressions.drain(..) {
4756 if let Expression::Alias(ref alias_box) = table_expr {
4758 if let Expression::Function(ref func) = alias_box.this {
4759 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4760 let arg = func.args[0].clone();
4761 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4762 (
4763 alias_box.column_aliases[0].name.clone(),
4764 alias_box.column_aliases[1].name.clone(),
4765 )
4766 } else {
4767 ("pos".to_string(), "col".to_string())
4768 };
4769
4770 let gen_subscripts = Expression::Function(Box::new(Function::new(
4772 "GENERATE_SUBSCRIPTS".to_string(),
4773 vec![
4774 arg.clone(),
4775 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4776 ],
4777 )));
4778 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4779 gen_subscripts,
4780 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4781 )));
4782 let pos_alias = Expression::Alias(Box::new(Alias {
4783 this: sub_one,
4784 alias: Identifier::new(&pos_name),
4785 column_aliases: Vec::new(),
4786 alias_explicit_as: false,
4787 alias_keyword: None,
4788 pre_alias_comments: Vec::new(),
4789 trailing_comments: Vec::new(),
4790 inferred_type: None,
4791 }));
4792 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4793 this: arg,
4794 expressions: Vec::new(),
4795 with_ordinality: false,
4796 alias: None,
4797 offset_alias: None,
4798 inferred_type: None,
4799 }));
4800 let col_alias = Expression::Alias(Box::new(Alias {
4801 this: unnest,
4802 alias: Identifier::new(&col_name),
4803 column_aliases: Vec::new(),
4804 alias_explicit_as: false,
4805 alias_keyword: None,
4806 pre_alias_comments: Vec::new(),
4807 trailing_comments: Vec::new(),
4808 inferred_type: None,
4809 }));
4810
4811 let mut inner_select = Select::new();
4812 inner_select.expressions = vec![pos_alias, col_alias];
4813
4814 let subquery = Expression::Subquery(Box::new(Subquery {
4815 this: Expression::Select(Box::new(inner_select)),
4816 alias: None,
4817 column_aliases: Vec::new(),
4818 alias_explicit_as: false,
4819 alias_keyword: None,
4820 order_by: None,
4821 limit: None,
4822 offset: None,
4823 distribute_by: None,
4824 sort_by: None,
4825 cluster_by: None,
4826 lateral: false,
4827 modifiers_inside: false,
4828 trailing_comments: Vec::new(),
4829 inferred_type: None,
4830 }));
4831 new_expressions.push(subquery);
4832 _changed = true;
4833 continue;
4834 }
4835 }
4836 }
4837
4838 if let Expression::Function(ref func) = table_expr {
4840 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4841 let arg = func.args[0].clone();
4842
4843 let gen_subscripts = Expression::Function(Box::new(Function::new(
4845 "GENERATE_SUBSCRIPTS".to_string(),
4846 vec![
4847 arg.clone(),
4848 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4849 ],
4850 )));
4851 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4852 gen_subscripts,
4853 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4854 )));
4855 let pos_alias = Expression::Alias(Box::new(Alias {
4856 this: sub_one,
4857 alias: Identifier::new("pos"),
4858 column_aliases: Vec::new(),
4859 alias_explicit_as: false,
4860 alias_keyword: None,
4861 pre_alias_comments: Vec::new(),
4862 trailing_comments: Vec::new(),
4863 inferred_type: None,
4864 }));
4865 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4866 this: arg,
4867 expressions: Vec::new(),
4868 with_ordinality: false,
4869 alias: None,
4870 offset_alias: None,
4871 inferred_type: None,
4872 }));
4873 let col_alias = Expression::Alias(Box::new(Alias {
4874 this: unnest,
4875 alias: Identifier::new("col"),
4876 column_aliases: Vec::new(),
4877 alias_explicit_as: false,
4878 alias_keyword: None,
4879 pre_alias_comments: Vec::new(),
4880 trailing_comments: Vec::new(),
4881 inferred_type: None,
4882 }));
4883
4884 let mut inner_select = Select::new();
4885 inner_select.expressions = vec![pos_alias, col_alias];
4886
4887 let subquery = Expression::Subquery(Box::new(Subquery {
4888 this: Expression::Select(Box::new(inner_select)),
4889 alias: None,
4890 column_aliases: Vec::new(),
4891 alias_explicit_as: false,
4892 alias_keyword: None,
4893 order_by: None,
4894 limit: None,
4895 offset: None,
4896 distribute_by: None,
4897 sort_by: None,
4898 cluster_by: None,
4899 lateral: false,
4900 modifiers_inside: false,
4901 trailing_comments: Vec::new(),
4902 inferred_type: None,
4903 }));
4904 new_expressions.push(subquery);
4905 _changed = true;
4906 continue;
4907 }
4908 }
4909
4910 new_expressions.push(table_expr);
4911 }
4912
4913 from.expressions = new_expressions;
4914 Ok(())
4915}
4916
4917pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
4932 match expr {
4933 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
4934 other => Ok(other),
4935 }
4936}
4937
4938pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
4948 match expr {
4949 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
4950 other => Ok(other),
4951 }
4952}
4953
4954fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
4955 let mut flattened_inputs: Vec<Expression> = Vec::new();
4956 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
4957
4958 for sel_expr in select.expressions.into_iter() {
4959 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
4960
4961 let rewritten = transform_recursive(sel_expr, &|e| {
4962 if let Expression::Lateral(lat) = e {
4963 if let Some(input_expr) = extract_flatten_input(&lat) {
4964 if found_input.borrow().is_none() {
4965 *found_input.borrow_mut() = Some(input_expr);
4966 }
4967 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
4968 }
4969 return Ok(Expression::Lateral(lat));
4970 }
4971 Ok(e)
4972 })?;
4973
4974 if let Some(input) = found_input.into_inner() {
4975 flattened_inputs.push(input);
4976 }
4977 new_selects.push(rewritten);
4978 }
4979
4980 if flattened_inputs.is_empty() {
4981 select.expressions = new_selects;
4982 return Ok(Expression::Select(Box::new(select)));
4983 }
4984
4985 select.expressions = new_selects;
4986
4987 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
4988 let is_first = idx == 0;
4990 let series_alias = if is_first {
4991 "pos".to_string()
4992 } else {
4993 format!("pos_{}", idx + 1)
4994 };
4995 let series_source_alias = if is_first {
4996 "_u".to_string()
4997 } else {
4998 format!("_u_{}", idx * 2 + 1)
4999 };
5000 let unnest_source_alias = if is_first {
5001 "_u_2".to_string()
5002 } else {
5003 format!("_u_{}", idx * 2 + 2)
5004 };
5005 let pos2_alias = if is_first {
5006 "pos_2".to_string()
5007 } else {
5008 format!("{}_2", series_alias)
5009 };
5010 let entity_alias = if is_first {
5011 "entity".to_string()
5012 } else {
5013 format!("entity_{}", idx + 1)
5014 };
5015
5016 let array_size_call = Expression::Function(Box::new(Function::new(
5017 "ARRAY_SIZE".to_string(),
5018 vec![Expression::NamedArgument(Box::new(NamedArgument {
5019 name: Identifier::new("INPUT"),
5020 value: input_expr.clone(),
5021 separator: NamedArgSeparator::DArrow,
5022 }))],
5023 )));
5024
5025 let greatest = Expression::Function(Box::new(Function::new(
5026 "GREATEST".to_string(),
5027 vec![array_size_call.clone()],
5028 )));
5029
5030 let series_end = Expression::Add(Box::new(BinaryOp::new(
5031 Expression::Paren(Box::new(crate::expressions::Paren {
5032 this: Expression::Sub(Box::new(BinaryOp::new(
5033 greatest,
5034 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5035 ))),
5036 trailing_comments: Vec::new(),
5037 })),
5038 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5039 )));
5040
5041 let series_range = Expression::Function(Box::new(Function::new(
5042 "ARRAY_GENERATE_RANGE".to_string(),
5043 vec![
5044 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
5045 series_end,
5046 ],
5047 )));
5048
5049 let series_flatten = Expression::Function(Box::new(Function::new(
5050 "FLATTEN".to_string(),
5051 vec![Expression::NamedArgument(Box::new(NamedArgument {
5052 name: Identifier::new("INPUT"),
5053 value: series_range,
5054 separator: NamedArgSeparator::DArrow,
5055 }))],
5056 )));
5057
5058 let series_table = Expression::Function(Box::new(Function::new(
5059 "TABLE".to_string(),
5060 vec![series_flatten],
5061 )));
5062
5063 let series_alias_expr = Expression::Alias(Box::new(Alias {
5064 this: series_table,
5065 alias: Identifier::new(series_source_alias.clone()),
5066 column_aliases: vec![
5067 Identifier::new("seq"),
5068 Identifier::new("key"),
5069 Identifier::new("path"),
5070 Identifier::new("index"),
5071 Identifier::new(series_alias.clone()),
5072 Identifier::new("this"),
5073 ],
5074 alias_explicit_as: false,
5075 alias_keyword: None,
5076 pre_alias_comments: Vec::new(),
5077 trailing_comments: Vec::new(),
5078 inferred_type: None,
5079 }));
5080
5081 select.joins.push(Join {
5082 this: series_alias_expr,
5083 on: None,
5084 using: Vec::new(),
5085 kind: JoinKind::Cross,
5086 use_inner_keyword: false,
5087 use_outer_keyword: false,
5088 deferred_condition: false,
5089 join_hint: None,
5090 match_condition: None,
5091 pivots: Vec::new(),
5092 comments: Vec::new(),
5093 nesting_group: 0,
5094 directed: false,
5095 });
5096
5097 let entity_flatten = Expression::Function(Box::new(Function::new(
5098 "FLATTEN".to_string(),
5099 vec![Expression::NamedArgument(Box::new(NamedArgument {
5100 name: Identifier::new("INPUT"),
5101 value: input_expr.clone(),
5102 separator: NamedArgSeparator::DArrow,
5103 }))],
5104 )));
5105
5106 let entity_table = Expression::Function(Box::new(Function::new(
5107 "TABLE".to_string(),
5108 vec![entity_flatten],
5109 )));
5110
5111 let entity_alias_expr = Expression::Alias(Box::new(Alias {
5112 this: entity_table,
5113 alias: Identifier::new(unnest_source_alias.clone()),
5114 column_aliases: vec![
5115 Identifier::new("seq"),
5116 Identifier::new("key"),
5117 Identifier::new("path"),
5118 Identifier::new(pos2_alias.clone()),
5119 Identifier::new(entity_alias.clone()),
5120 Identifier::new("this"),
5121 ],
5122 alias_explicit_as: false,
5123 alias_keyword: None,
5124 pre_alias_comments: Vec::new(),
5125 trailing_comments: Vec::new(),
5126 inferred_type: None,
5127 }));
5128
5129 select.joins.push(Join {
5130 this: entity_alias_expr,
5131 on: None,
5132 using: Vec::new(),
5133 kind: JoinKind::Cross,
5134 use_inner_keyword: false,
5135 use_outer_keyword: false,
5136 deferred_condition: false,
5137 join_hint: None,
5138 match_condition: None,
5139 pivots: Vec::new(),
5140 comments: Vec::new(),
5141 nesting_group: 0,
5142 directed: false,
5143 });
5144
5145 let pos_col =
5146 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
5147 let pos2_col =
5148 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
5149
5150 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
5151 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
5152 this: Expression::Sub(Box::new(BinaryOp::new(
5153 array_size_call,
5154 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5155 ))),
5156 trailing_comments: Vec::new(),
5157 }));
5158 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
5159 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
5160 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
5161 let or_cond = Expression::Or(Box::new(BinaryOp::new(
5162 eq,
5163 Expression::Paren(Box::new(crate::expressions::Paren {
5164 this: and_cond,
5165 trailing_comments: Vec::new(),
5166 })),
5167 )));
5168
5169 select.where_clause = Some(match select.where_clause.take() {
5170 Some(existing) => Where {
5171 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
5172 },
5173 None => Where { this: or_cond },
5174 });
5175 }
5176
5177 Ok(Expression::Select(Box::new(select)))
5178}
5179
5180fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
5181 let Expression::Function(f) = lat.this.as_ref() else {
5182 return None;
5183 };
5184 if !f.name.eq_ignore_ascii_case("FLATTEN") {
5185 return None;
5186 }
5187
5188 for arg in &f.args {
5189 if let Expression::NamedArgument(na) = arg {
5190 if na.name.name.eq_ignore_ascii_case("INPUT") {
5191 return Some(na.value.clone());
5192 }
5193 }
5194 }
5195 f.args.first().cloned()
5196}
5197
5198fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
5199 let cond = Expression::Eq(Box::new(BinaryOp::new(
5200 Expression::qualified_column("_u", "pos"),
5201 Expression::qualified_column("_u_2", "pos_2"),
5202 )));
5203 let true_expr = Expression::qualified_column("_u_2", "entity");
5204 let iff_expr = Expression::Function(Box::new(Function::new(
5205 "IFF".to_string(),
5206 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
5207 )));
5208
5209 lat.this = Box::new(iff_expr);
5210 if lat.column_aliases.is_empty() {
5211 lat.column_aliases = vec![
5212 "SEQ".to_string(),
5213 "KEY".to_string(),
5214 "PATH".to_string(),
5215 "INDEX".to_string(),
5216 "VALUE".to_string(),
5217 "THIS".to_string(),
5218 ];
5219 }
5220 lat
5221}
5222
5223struct ExplodeInfo {
5225 arg_sql: String,
5227 explode_alias: String,
5229 pos_alias: String,
5231 unnest_source_alias: String,
5233}
5234
5235fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
5236 let is_presto = matches!(
5237 target,
5238 DialectType::Presto | DialectType::Trino | DialectType::Athena
5239 );
5240 let is_bigquery = matches!(target, DialectType::BigQuery);
5241
5242 if !is_presto && !is_bigquery {
5243 return Ok(Expression::Select(Box::new(select)));
5244 }
5245
5246 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
5248 if !has_explode {
5249 return Ok(Expression::Select(Box::new(select)));
5250 }
5251
5252 let mut taken_select_names = std::collections::HashSet::new();
5254 let mut taken_source_names = std::collections::HashSet::new();
5255
5256 for sel in &select.expressions {
5258 if let Some(name) = get_output_name(sel) {
5259 taken_select_names.insert(name);
5260 }
5261 }
5262
5263 for sel in &select.expressions {
5265 let explode_expr = find_explode_in_expr(sel);
5266 if let Some(arg) = explode_expr {
5267 if let Some(name) = get_output_name(&arg) {
5268 taken_select_names.insert(name);
5269 }
5270 }
5271 }
5272
5273 if let Some(ref from) = select.from {
5275 for from_expr in &from.expressions {
5276 collect_source_names(from_expr, &mut taken_source_names);
5277 }
5278 }
5279 for join in &select.joins {
5281 collect_source_names(&join.this, &mut taken_source_names);
5282 }
5283
5284 let series_alias = new_name(&mut taken_select_names, "pos");
5286
5287 let series_source_alias = new_name(&mut taken_source_names, "_u");
5289
5290 let target_dialect = Dialect::get(target);
5292
5293 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
5295 let mut new_projections: Vec<String> = Vec::new();
5296
5297 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
5298 let explode_data = extract_explode_data(sel_expr);
5299
5300 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
5301 let arg_sql = target_dialect
5303 .generate(&arg_expr)
5304 .unwrap_or_else(|_| "NULL".to_string());
5305
5306 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
5307
5308 let explode_alias = if let Some(ref ea) = explicit_alias {
5309 taken_select_names.remove(ea.as_str());
5312 let name = new_name(&mut taken_select_names, ea);
5314 name
5315 } else {
5316 new_name(&mut taken_select_names, "col")
5317 };
5318
5319 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
5320 taken_select_names.remove(pa.as_str());
5322 let name = new_name(&mut taken_select_names, pa);
5323 name
5324 } else {
5325 new_name(&mut taken_select_names, "pos")
5326 };
5327
5328 if is_presto {
5330 let if_col = format!(
5332 "IF({}.{} = {}.{}, {}.{}) AS {}",
5333 series_source_alias,
5334 series_alias,
5335 unnest_source_alias,
5336 pos_alias,
5337 unnest_source_alias,
5338 explode_alias,
5339 explode_alias
5340 );
5341 new_projections.push(if_col);
5342
5343 if is_posexplode {
5345 let if_pos = format!(
5346 "IF({}.{} = {}.{}, {}.{}) AS {}",
5347 series_source_alias,
5348 series_alias,
5349 unnest_source_alias,
5350 pos_alias,
5351 unnest_source_alias,
5352 pos_alias,
5353 pos_alias
5354 );
5355 new_projections.push(if_pos);
5356 }
5357 } else {
5358 let if_col = format!(
5360 "IF({} = {}, {}, NULL) AS {}",
5361 series_alias, pos_alias, explode_alias, explode_alias
5362 );
5363 new_projections.push(if_col);
5364
5365 if is_posexplode {
5367 let if_pos = format!(
5368 "IF({} = {}, {}, NULL) AS {}",
5369 series_alias, pos_alias, pos_alias, pos_alias
5370 );
5371 new_projections.push(if_pos);
5372 }
5373 }
5374
5375 explode_infos.push(ExplodeInfo {
5376 arg_sql,
5377 explode_alias,
5378 pos_alias,
5379 unnest_source_alias,
5380 });
5381 } else {
5382 let sel_sql = target_dialect
5384 .generate(sel_expr)
5385 .unwrap_or_else(|_| "*".to_string());
5386 new_projections.push(sel_sql);
5387 }
5388 }
5389
5390 if explode_infos.is_empty() {
5391 return Ok(Expression::Select(Box::new(select)));
5392 }
5393
5394 let mut from_parts: Vec<String> = Vec::new();
5396
5397 if let Some(ref from) = select.from {
5399 for from_expr in &from.expressions {
5400 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
5401 from_parts.push(from_sql);
5402 }
5403 }
5404
5405 let size_exprs: Vec<String> = explode_infos
5407 .iter()
5408 .map(|info| {
5409 if is_presto {
5410 format!("CARDINALITY({})", info.arg_sql)
5411 } else {
5412 format!("ARRAY_LENGTH({})", info.arg_sql)
5413 }
5414 })
5415 .collect();
5416
5417 let greatest_arg = if size_exprs.len() == 1 {
5418 size_exprs[0].clone()
5419 } else {
5420 format!("GREATEST({})", size_exprs.join(", "))
5421 };
5422
5423 let series_sql = if is_presto {
5426 if size_exprs.len() == 1 {
5428 format!(
5429 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
5430 greatest_arg, series_source_alias, series_alias
5431 )
5432 } else {
5433 format!(
5435 "UNNEST(SEQUENCE(1, {})) AS {}({})",
5436 greatest_arg, series_source_alias, series_alias
5437 )
5438 }
5439 } else {
5440 if size_exprs.len() == 1 {
5442 format!(
5443 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
5444 greatest_arg, series_alias
5445 )
5446 } else {
5447 format!(
5449 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
5450 greatest_arg, series_alias
5451 )
5452 }
5453 };
5454
5455 let mut cross_joins: Vec<String> = Vec::new();
5459
5460 for info in &explode_infos {
5461 cross_joins.push(format!(
5463 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
5464 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
5465 ));
5466 }
5467
5468 let mut where_conditions: Vec<String> = Vec::new();
5470
5471 for info in &explode_infos {
5472 let size_expr = if is_presto {
5473 format!("CARDINALITY({})", info.arg_sql)
5474 } else {
5475 format!("ARRAY_LENGTH({})", info.arg_sql)
5476 };
5477
5478 let cond = if is_presto {
5479 format!(
5480 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
5481 series_src = series_source_alias,
5482 series_al = series_alias,
5483 unnest_src = info.unnest_source_alias,
5484 pos_al = info.pos_alias,
5485 size = size_expr
5486 )
5487 } else {
5488 format!(
5489 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
5490 series_al = series_alias,
5491 pos_al = info.pos_alias,
5492 size = size_expr
5493 )
5494 };
5495
5496 where_conditions.push(cond);
5497 }
5498
5499 let where_sql = if where_conditions.len() == 1 {
5501 where_conditions[0].clone()
5502 } else {
5503 where_conditions
5504 .iter()
5505 .map(|c| format!("({})", c))
5506 .collect::<Vec<_>>()
5507 .join(" AND ")
5508 };
5509
5510 let select_part = new_projections.join(", ");
5512
5513 let from_and_joins = if from_parts.is_empty() {
5515 format!("FROM {} {}", series_sql, cross_joins.join(" "))
5517 } else {
5518 format!(
5519 "FROM {} {} {}",
5520 from_parts.join(", "),
5521 format!("CROSS JOIN {}", series_sql),
5522 cross_joins.join(" ")
5523 )
5524 };
5525
5526 let full_sql = format!(
5527 "SELECT {} {} WHERE {}",
5528 select_part, from_and_joins, where_sql
5529 );
5530
5531 let generic_dialect = Dialect::get(DialectType::Generic);
5534 let parsed = generic_dialect.parse(&full_sql);
5535 match parsed {
5536 Ok(mut stmts) if !stmts.is_empty() => {
5537 let mut result = stmts.remove(0);
5538
5539 if is_bigquery {
5543 convert_unnest_presto_to_bigquery(&mut result);
5544 }
5545
5546 Ok(result)
5547 }
5548 _ => {
5549 Ok(Expression::Select(Box::new(select)))
5551 }
5552 }
5553}
5554
5555fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
5559 match expr {
5560 Expression::Select(ref mut select) => {
5561 if let Some(ref mut from) = select.from {
5563 for from_item in from.expressions.iter_mut() {
5564 convert_unnest_presto_to_bigquery(from_item);
5565 }
5566 }
5567 for join in select.joins.iter_mut() {
5569 convert_unnest_presto_to_bigquery(&mut join.this);
5570 }
5571 }
5572 Expression::Alias(ref alias) => {
5573 if let Expression::Unnest(ref unnest) = alias.this {
5575 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
5576 let col_alias = alias.column_aliases[0].clone();
5577 let pos_alias = alias.column_aliases[1].clone();
5578 let mut new_unnest = unnest.as_ref().clone();
5579 new_unnest.alias = Some(col_alias);
5580 new_unnest.offset_alias = Some(pos_alias);
5581 *expr = Expression::Unnest(Box::new(new_unnest));
5583 }
5584 }
5585 }
5586 _ => {}
5587 }
5588}
5589
5590fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
5593 if !names.contains(base) {
5594 names.insert(base.to_string());
5595 return base.to_string();
5596 }
5597 let mut i = 2;
5598 loop {
5599 let candidate = format!("{}_{}", base, i);
5600 if !names.contains(&candidate) {
5601 names.insert(candidate.clone());
5602 return candidate;
5603 }
5604 i += 1;
5605 }
5606}
5607
5608fn expr_contains_explode(expr: &Expression) -> bool {
5610 match expr {
5611 Expression::Explode(_) => true,
5612 Expression::ExplodeOuter(_) => true,
5613 Expression::Function(f) => {
5614 let name = f.name.to_uppercase();
5615 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
5616 }
5617 Expression::Alias(a) => expr_contains_explode(&a.this),
5618 _ => false,
5619 }
5620}
5621
5622fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
5624 match expr {
5625 Expression::Explode(uf) => Some(uf.this.clone()),
5626 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
5627 Expression::Function(f) => {
5628 let name = f.name.to_uppercase();
5629 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5630 Some(f.args[0].clone())
5631 } else {
5632 None
5633 }
5634 }
5635 Expression::Alias(a) => find_explode_in_expr(&a.this),
5636 _ => None,
5637 }
5638}
5639
5640fn extract_explode_data(
5643 expr: &Expression,
5644) -> Option<(bool, Expression, Option<String>, Option<String>)> {
5645 match expr {
5646 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
5648 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
5649 Expression::Function(f) => {
5651 let name = f.name.to_uppercase();
5652 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5653 Some((true, f.args[0].clone(), None, None))
5654 } else {
5655 None
5656 }
5657 }
5658 Expression::Alias(a) => {
5660 match &a.this {
5661 Expression::Explode(uf) => {
5662 let alias = if !a.alias.is_empty() {
5663 Some(a.alias.name.clone())
5664 } else {
5665 None
5666 };
5667 Some((false, uf.this.clone(), alias, None))
5668 }
5669 Expression::ExplodeOuter(uf) => {
5670 let alias = if !a.alias.is_empty() {
5671 Some(a.alias.name.clone())
5672 } else {
5673 None
5674 };
5675 Some((false, uf.this.clone(), alias, None))
5676 }
5677 Expression::Function(f) => {
5678 let name = f.name.to_uppercase();
5679 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5680 if a.column_aliases.len() == 2 {
5682 let pos_alias = a.column_aliases[0].name.clone();
5683 let col_alias = a.column_aliases[1].name.clone();
5684 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
5685 } else if !a.alias.is_empty() {
5686 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
5688 } else {
5689 Some((true, f.args[0].clone(), None, None))
5690 }
5691 } else {
5692 None
5693 }
5694 }
5695 _ => None,
5696 }
5697 }
5698 _ => None,
5699 }
5700}
5701
5702fn get_output_name(expr: &Expression) -> Option<String> {
5704 match expr {
5705 Expression::Alias(a) => {
5706 if !a.alias.is_empty() {
5707 Some(a.alias.name.clone())
5708 } else {
5709 None
5710 }
5711 }
5712 Expression::Column(c) => Some(c.name.name.clone()),
5713 Expression::Identifier(id) => Some(id.name.clone()),
5714 _ => None,
5715 }
5716}
5717
5718fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
5720 match expr {
5721 Expression::Alias(a) => {
5722 if !a.alias.is_empty() {
5723 names.insert(a.alias.name.clone());
5724 }
5725 }
5726 Expression::Subquery(s) => {
5727 if let Some(ref alias) = s.alias {
5728 names.insert(alias.name.clone());
5729 }
5730 }
5731 Expression::Table(t) => {
5732 if let Some(ref alias) = t.alias {
5733 names.insert(alias.name.clone());
5734 } else {
5735 names.insert(t.name.name.clone());
5736 }
5737 }
5738 Expression::Column(c) => {
5739 names.insert(c.name.name.clone());
5740 }
5741 Expression::Identifier(id) => {
5742 names.insert(id.name.clone());
5743 }
5744 _ => {}
5745 }
5746}
5747
5748pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
5751 use crate::dialects::transform_recursive;
5752 transform_recursive(expr, &strip_unnest_column_refs_single)
5753}
5754
5755fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
5756 if let Expression::Select(mut select) = expr {
5757 for join in select.joins.iter_mut() {
5759 strip_unnest_from_expr(&mut join.this);
5760 }
5761 if let Some(ref mut from) = select.from {
5763 for from_item in from.expressions.iter_mut() {
5764 strip_unnest_from_expr(from_item);
5765 }
5766 }
5767 Ok(Expression::Select(select))
5768 } else {
5769 Ok(expr)
5770 }
5771}
5772
5773fn strip_unnest_from_expr(expr: &mut Expression) {
5776 if let Expression::Alias(ref mut alias) = expr {
5777 if let Expression::Unnest(ref unnest) = alias.this {
5778 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
5779 if is_column_ref {
5780 let inner = unnest.this.clone();
5782 alias.this = inner;
5783 }
5784 }
5785 }
5786}
5787
5788pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
5791 use crate::dialects::transform_recursive;
5792 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
5793}
5794
5795fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
5796 if let Expression::Select(mut select) = expr {
5797 if let Some(ref mut from) = select.from {
5799 for from_item in from.expressions.iter_mut() {
5800 try_wrap_unnest_in_subquery(from_item);
5801 }
5802 }
5803
5804 for join in select.joins.iter_mut() {
5806 try_wrap_unnest_in_subquery(&mut join.this);
5807 }
5808
5809 Ok(Expression::Select(select))
5810 } else {
5811 Ok(expr)
5812 }
5813}
5814
5815fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
5817 match expr {
5818 Expression::Array(arr) => arr
5820 .expressions
5821 .iter()
5822 .any(|e| matches!(e, Expression::Struct(_))),
5823 Expression::ArrayFunc(arr) => arr
5824 .expressions
5825 .iter()
5826 .any(|e| matches!(e, Expression::Struct(_))),
5827 Expression::Cast(c) => {
5829 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
5830 }
5831 _ => false,
5832 }
5833}
5834
5835fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
5838 if let Expression::Alias(ref alias) = expr {
5840 if let Expression::Unnest(ref unnest) = alias.this {
5841 if is_struct_array_unnest_arg(&unnest.this) {
5842 let unnest_clone = (**unnest).clone();
5843 let alias_name = alias.alias.clone();
5844 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
5845 *expr = new_expr;
5846 return;
5847 }
5848 }
5849 }
5850
5851 if let Expression::Unnest(ref unnest) = expr {
5853 if is_struct_array_unnest_arg(&unnest.this) {
5854 let unnest_clone = (**unnest).clone();
5855 let new_expr = make_unnest_subquery(unnest_clone, None);
5856 *expr = new_expr;
5857 }
5858 }
5859}
5860
5861fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
5863 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
5865 name: Identifier::new("max_depth".to_string()),
5866 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
5867 separator: NamedArgSeparator::DArrow,
5868 }));
5869
5870 let mut unnest_args = vec![unnest.this];
5871 unnest_args.extend(unnest.expressions);
5872 unnest_args.push(max_depth_arg);
5873
5874 let unnest_func =
5875 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
5876
5877 let mut inner_select = Select::new();
5879 inner_select.expressions = vec![unnest_func];
5880 let inner_select = Expression::Select(Box::new(inner_select));
5881
5882 let subquery = Subquery {
5884 this: inner_select,
5885 alias,
5886 column_aliases: Vec::new(),
5887 alias_explicit_as: false,
5888 alias_keyword: None,
5889 order_by: None,
5890 limit: None,
5891 offset: None,
5892 distribute_by: None,
5893 sort_by: None,
5894 cluster_by: None,
5895 lateral: false,
5896 modifiers_inside: false,
5897 trailing_comments: Vec::new(),
5898 inferred_type: None,
5899 };
5900
5901 Expression::Subquery(Box::new(subquery))
5902}
5903
5904pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
5916 use crate::expressions::{Limit as LimitClause, Offset as OffsetClause, OrderBy, Star};
5917
5918 match expr {
5919 Expression::Union(mut u) => {
5920 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
5923 if let Expression::Select(ref mut right_select) = u.right {
5925 if right_select.order_by.is_some()
5926 || right_select.limit.is_some()
5927 || right_select.offset.is_some()
5928 {
5929 u.order_by = right_select.order_by.take();
5931 u.limit = right_select.limit.take().map(|l| Box::new(l.this));
5932 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
5933 }
5934 }
5935 }
5936
5937 let has_order_or_limit =
5938 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
5939 if has_order_or_limit {
5940 let order_by: Option<OrderBy> = u.order_by.take();
5942 let union_limit: Option<Box<Expression>> = u.limit.take();
5943 let union_offset: Option<Box<Expression>> = u.offset.take();
5944
5945 let select_limit: Option<LimitClause> = union_limit.map(|l| LimitClause {
5947 this: *l,
5948 percent: false,
5949 comments: Vec::new(),
5950 });
5951
5952 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
5954 this: *o,
5955 rows: None,
5956 });
5957
5958 let subquery = Subquery {
5960 this: Expression::Union(u),
5961 alias: Some(Identifier::new("_l_0")),
5962 column_aliases: Vec::new(),
5963 alias_explicit_as: true,
5964 alias_keyword: None,
5965 lateral: false,
5966 modifiers_inside: false,
5967 order_by: None,
5968 limit: None,
5969 offset: None,
5970 distribute_by: None,
5971 sort_by: None,
5972 cluster_by: None,
5973 trailing_comments: Vec::new(),
5974 inferred_type: None,
5975 };
5976
5977 let mut select = Select::default();
5979 select.expressions = vec![Expression::Star(Star {
5980 table: None,
5981 except: None,
5982 replace: None,
5983 rename: None,
5984 trailing_comments: Vec::new(),
5985 span: None,
5986 })];
5987 select.from = Some(From {
5988 expressions: vec![Expression::Subquery(Box::new(subquery))],
5989 });
5990 select.order_by = order_by;
5991 select.limit = select_limit;
5992 select.offset = select_offset;
5993
5994 Ok(Expression::Select(Box::new(select)))
5995 } else {
5996 Ok(Expression::Union(u))
5997 }
5998 }
5999 _ => Ok(expr),
6000 }
6001}
6002
6003pub fn expand_like_any(expr: Expression) -> Result<Expression> {
6011 use crate::expressions::{BinaryOp, LikeOp, Paren};
6012
6013 const LIKE_ALL_MARKER: &str = "__LIKE_ALL_EXPANSION__";
6016
6017 fn unwrap_parens(e: &Expression) -> &Expression {
6018 match e {
6019 Expression::Paren(p) => unwrap_parens(&p.this),
6020 _ => e,
6021 }
6022 }
6023
6024 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
6025 let inner = unwrap_parens(e);
6026 match inner {
6027 Expression::Tuple(t) => Some(t.expressions.clone()),
6028 _ if !matches!(e, Expression::Tuple(_)) => Some(vec![inner.clone()]),
6030 _ => None,
6031 }
6032 }
6033
6034 fn expand_like_quantifier(
6036 op: &LikeOp,
6037 values: Vec<Expression>,
6038 is_ilike: bool,
6039 combiner: fn(Expression, Expression) -> Expression,
6040 wrap_marker: bool,
6041 ) -> Expression {
6042 let num_values = values.len();
6043 let mut result: Option<Expression> = None;
6044 for val in values {
6045 let like = if is_ilike {
6046 Expression::ILike(Box::new(LikeOp {
6047 left: op.left.clone(),
6048 right: val,
6049 escape: op.escape.clone(),
6050 quantifier: None,
6051 inferred_type: None,
6052 }))
6053 } else {
6054 Expression::Like(Box::new(LikeOp {
6055 left: op.left.clone(),
6056 right: val,
6057 escape: op.escape.clone(),
6058 quantifier: None,
6059 inferred_type: None,
6060 }))
6061 };
6062 result = Some(match result {
6063 None => like,
6064 Some(prev) => combiner(prev, like),
6065 });
6066 }
6067 let expanded = result.unwrap_or_else(|| unreachable!("values is non-empty"));
6068 if wrap_marker && num_values > 1 {
6072 Expression::Paren(Box::new(Paren {
6073 this: expanded,
6074 trailing_comments: vec![LIKE_ALL_MARKER.to_string()],
6075 }))
6076 } else {
6077 expanded
6078 }
6079 }
6080
6081 fn or_combiner(a: Expression, b: Expression) -> Expression {
6082 Expression::Or(Box::new(BinaryOp::new(a, b)))
6083 }
6084
6085 fn and_combiner(a: Expression, b: Expression) -> Expression {
6086 Expression::And(Box::new(BinaryOp::new(a, b)))
6087 }
6088
6089 fn is_like_all_marker(p: &Paren) -> bool {
6090 p.trailing_comments.len() == 1 && p.trailing_comments[0] == LIKE_ALL_MARKER
6091 }
6092
6093 let result = transform_recursive(expr, &|e| {
6101 match e {
6102 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6104 if let Some(values) = extract_tuple_values(&op.right) {
6105 if values.is_empty() {
6106 return Ok(e);
6107 }
6108 Ok(expand_like_quantifier(
6109 op,
6110 values,
6111 false,
6112 or_combiner,
6113 false,
6114 ))
6115 } else {
6116 Ok(e)
6117 }
6118 }
6119 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6121 if let Some(values) = extract_tuple_values(&op.right) {
6122 if values.is_empty() {
6123 return Ok(e);
6124 }
6125 Ok(expand_like_quantifier(
6126 op,
6127 values,
6128 false,
6129 and_combiner,
6130 true,
6131 ))
6132 } else {
6133 Ok(e)
6134 }
6135 }
6136 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6138 if let Some(values) = extract_tuple_values(&op.right) {
6139 if values.is_empty() {
6140 return Ok(e);
6141 }
6142 Ok(expand_like_quantifier(op, values, true, or_combiner, false))
6143 } else {
6144 Ok(e)
6145 }
6146 }
6147 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6149 if let Some(values) = extract_tuple_values(&op.right) {
6150 if values.is_empty() {
6151 return Ok(e);
6152 }
6153 Ok(expand_like_quantifier(op, values, true, and_combiner, true))
6154 } else {
6155 Ok(e)
6156 }
6157 }
6158 Expression::And(mut op) => {
6163 if matches!(&op.left, Expression::Or(_)) {
6164 op.left = Expression::Paren(Box::new(Paren {
6165 this: op.left,
6166 trailing_comments: vec![],
6167 }));
6168 }
6169 if matches!(&op.right, Expression::Or(_)) {
6170 op.right = Expression::Paren(Box::new(Paren {
6171 this: op.right,
6172 trailing_comments: vec![],
6173 }));
6174 }
6175 Ok(Expression::And(op))
6176 }
6177 Expression::Or(mut op) => {
6180 if let Expression::Paren(ref mut p) = op.left {
6181 if is_like_all_marker(p) {
6182 p.trailing_comments.clear();
6183 }
6184 }
6185 if let Expression::Paren(ref mut p) = op.right {
6186 if is_like_all_marker(p) {
6187 p.trailing_comments.clear();
6188 }
6189 }
6190 Ok(Expression::Or(op))
6191 }
6192 _ => Ok(e),
6193 }
6194 })?;
6195
6196 transform_recursive(result, &|e| {
6200 if let Expression::Paren(p) = &e {
6201 if is_like_all_marker(p) {
6202 let Expression::Paren(p) = e else {
6203 unreachable!()
6204 };
6205 return Ok(p.this);
6206 }
6207 }
6208 Ok(e)
6209 })
6210}
6211
6212pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
6220 use crate::expressions::Alias;
6221
6222 fn add_self_aliases_to_select(select: &mut Select) {
6223 let new_expressions: Vec<Expression> = select
6224 .expressions
6225 .iter()
6226 .map(|e| {
6227 match e {
6228 Expression::Column(col) => {
6230 let alias_name = col.name.clone();
6231 Expression::Alias(Box::new(Alias {
6232 this: e.clone(),
6233 alias: alias_name,
6234 column_aliases: Vec::new(),
6235 alias_explicit_as: false,
6236 alias_keyword: None,
6237 pre_alias_comments: Vec::new(),
6238 trailing_comments: Vec::new(),
6239 inferred_type: None,
6240 }))
6241 }
6242 _ => e.clone(),
6244 }
6245 })
6246 .collect();
6247 select.expressions = new_expressions;
6248 }
6249
6250 fn walk_and_qualify(expr: &mut Expression) {
6251 match expr {
6252 Expression::Select(ref mut select) => {
6253 if let Some(ref mut from) = select.from {
6255 for e in from.expressions.iter_mut() {
6256 qualify_subquery_expr(e);
6257 walk_and_qualify(e);
6258 }
6259 }
6260 for join in select.joins.iter_mut() {
6262 qualify_subquery_expr(&mut join.this);
6263 walk_and_qualify(&mut join.this);
6264 }
6265 for e in select.expressions.iter_mut() {
6267 walk_and_qualify(e);
6268 }
6269 if let Some(ref mut w) = select.where_clause {
6271 walk_and_qualify(&mut w.this);
6272 }
6273 }
6274 Expression::Subquery(ref mut subquery) => {
6275 walk_and_qualify(&mut subquery.this);
6276 }
6277 Expression::Union(ref mut u) => {
6278 walk_and_qualify(&mut u.left);
6279 walk_and_qualify(&mut u.right);
6280 }
6281 Expression::Intersect(ref mut i) => {
6282 walk_and_qualify(&mut i.left);
6283 walk_and_qualify(&mut i.right);
6284 }
6285 Expression::Except(ref mut e) => {
6286 walk_and_qualify(&mut e.left);
6287 walk_and_qualify(&mut e.right);
6288 }
6289 Expression::Cte(ref mut cte) => {
6290 walk_and_qualify(&mut cte.this);
6291 }
6292 _ => {}
6293 }
6294 }
6295
6296 fn qualify_subquery_expr(expr: &mut Expression) {
6297 match expr {
6298 Expression::Subquery(ref mut subquery) => {
6299 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
6301 if let Expression::Select(ref mut inner_select) = subquery.this {
6302 let has_star = inner_select
6304 .expressions
6305 .iter()
6306 .any(|e| matches!(e, Expression::Star(_)));
6307 if !has_star {
6308 add_self_aliases_to_select(inner_select);
6309 }
6310 }
6311 }
6312 walk_and_qualify(&mut subquery.this);
6314 }
6315 Expression::Alias(ref mut alias) => {
6316 qualify_subquery_expr(&mut alias.this);
6317 }
6318 _ => {}
6319 }
6320 }
6321
6322 let mut result = expr;
6323 walk_and_qualify(&mut result);
6324
6325 if let Expression::Select(ref mut select) = result {
6327 if let Some(ref mut with) = select.with {
6328 for cte in with.ctes.iter_mut() {
6329 if cte.columns.is_empty() {
6331 walk_and_qualify(&mut cte.this);
6333 }
6334 }
6335 }
6336 }
6337
6338 Ok(result)
6339}
6340
6341#[cfg(test)]
6342mod tests {
6343 use super::*;
6344 use crate::dialects::{Dialect, DialectType};
6345 use crate::expressions::Column;
6346
6347 fn gen(expr: &Expression) -> String {
6348 let dialect = Dialect::get(DialectType::Generic);
6349 dialect.generate(expr).unwrap()
6350 }
6351
6352 #[test]
6353 fn test_preprocess() {
6354 let expr = Expression::Boolean(BooleanLiteral { value: true });
6355 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
6356 assert!(
6357 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6358 );
6359 }
6360
6361 #[test]
6362 fn test_preprocess_chain() {
6363 let expr = Expression::Boolean(BooleanLiteral { value: true });
6365 let transforms: Vec<fn(Expression) -> Result<Expression>> =
6367 vec![replace_bool_with_int, replace_int_with_bool];
6368 let result = preprocess(expr, &transforms).unwrap();
6369 if let Expression::Boolean(b) = result {
6372 assert!(b.value);
6373 } else {
6374 panic!("Expected boolean literal");
6375 }
6376 }
6377
6378 #[test]
6379 fn test_unnest_to_explode() {
6380 let unnest = Expression::Unnest(Box::new(UnnestFunc {
6381 this: Expression::boxed_column(Column {
6382 name: Identifier::new("arr".to_string()),
6383 table: None,
6384 join_mark: false,
6385 trailing_comments: vec![],
6386 span: None,
6387 inferred_type: None,
6388 }),
6389 expressions: Vec::new(),
6390 with_ordinality: false,
6391 alias: None,
6392 offset_alias: None,
6393 inferred_type: None,
6394 }));
6395
6396 let result = unnest_to_explode(unnest).unwrap();
6397 assert!(matches!(result, Expression::Explode(_)));
6398 }
6399
6400 #[test]
6401 fn test_explode_to_unnest() {
6402 let explode = Expression::Explode(Box::new(UnaryFunc {
6403 this: Expression::boxed_column(Column {
6404 name: Identifier::new("arr".to_string()),
6405 table: None,
6406 join_mark: false,
6407 trailing_comments: vec![],
6408 span: None,
6409 inferred_type: None,
6410 }),
6411 original_name: None,
6412 inferred_type: None,
6413 }));
6414
6415 let result = explode_to_unnest(explode).unwrap();
6416 assert!(matches!(result, Expression::Unnest(_)));
6417 }
6418
6419 #[test]
6420 fn test_replace_bool_with_int() {
6421 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
6422 let result = replace_bool_with_int(true_expr).unwrap();
6423 if let Expression::Literal(lit) = result {
6424 if let Literal::Number(n) = lit.as_ref() {
6425 assert_eq!(n, "1");
6426 }
6427 } else {
6428 panic!("Expected number literal");
6429 }
6430
6431 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
6432 let result = replace_bool_with_int(false_expr).unwrap();
6433 if let Expression::Literal(lit) = result {
6434 if let Literal::Number(n) = lit.as_ref() {
6435 assert_eq!(n, "0");
6436 }
6437 } else {
6438 panic!("Expected number literal");
6439 }
6440 }
6441
6442 #[test]
6443 fn test_replace_int_with_bool() {
6444 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
6445 let result = replace_int_with_bool(one_expr).unwrap();
6446 if let Expression::Boolean(b) = result {
6447 assert!(b.value);
6448 } else {
6449 panic!("Expected boolean true");
6450 }
6451
6452 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
6453 let result = replace_int_with_bool(zero_expr).unwrap();
6454 if let Expression::Boolean(b) = result {
6455 assert!(!b.value);
6456 } else {
6457 panic!("Expected boolean false");
6458 }
6459
6460 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
6462 let result = replace_int_with_bool(two_expr).unwrap();
6463 assert!(
6464 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6465 );
6466 }
6467
6468 #[test]
6469 fn test_strip_data_type_params() {
6470 let decimal = DataType::Decimal {
6472 precision: Some(10),
6473 scale: Some(2),
6474 };
6475 let stripped = strip_data_type_params(decimal);
6476 assert_eq!(
6477 stripped,
6478 DataType::Decimal {
6479 precision: None,
6480 scale: None
6481 }
6482 );
6483
6484 let varchar = DataType::VarChar {
6486 length: Some(255),
6487 parenthesized_length: false,
6488 };
6489 let stripped = strip_data_type_params(varchar);
6490 assert_eq!(
6491 stripped,
6492 DataType::VarChar {
6493 length: None,
6494 parenthesized_length: false
6495 }
6496 );
6497
6498 let char_type = DataType::Char { length: Some(10) };
6500 let stripped = strip_data_type_params(char_type);
6501 assert_eq!(stripped, DataType::Char { length: None });
6502
6503 let timestamp = DataType::Timestamp {
6505 precision: Some(6),
6506 timezone: true,
6507 };
6508 let stripped = strip_data_type_params(timestamp);
6509 assert_eq!(
6510 stripped,
6511 DataType::Timestamp {
6512 precision: None,
6513 timezone: true
6514 }
6515 );
6516
6517 let array = DataType::Array {
6519 element_type: Box::new(DataType::VarChar {
6520 length: Some(100),
6521 parenthesized_length: false,
6522 }),
6523 dimension: None,
6524 };
6525 let stripped = strip_data_type_params(array);
6526 assert_eq!(
6527 stripped,
6528 DataType::Array {
6529 element_type: Box::new(DataType::VarChar {
6530 length: None,
6531 parenthesized_length: false
6532 }),
6533 dimension: None,
6534 }
6535 );
6536
6537 let text = DataType::Text;
6539 let stripped = strip_data_type_params(text);
6540 assert_eq!(stripped, DataType::Text);
6541 }
6542
6543 #[test]
6544 fn test_remove_precision_parameterized_types_cast() {
6545 let cast_expr = Expression::Cast(Box::new(Cast {
6547 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6548 to: DataType::Decimal {
6549 precision: Some(10),
6550 scale: Some(2),
6551 },
6552 trailing_comments: vec![],
6553 double_colon_syntax: false,
6554 format: None,
6555 default: None,
6556 inferred_type: None,
6557 }));
6558
6559 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6560 if let Expression::Cast(cast) = result {
6561 assert_eq!(
6562 cast.to,
6563 DataType::Decimal {
6564 precision: None,
6565 scale: None
6566 }
6567 );
6568 } else {
6569 panic!("Expected Cast expression");
6570 }
6571 }
6572
6573 #[test]
6574 fn test_remove_precision_parameterized_types_varchar() {
6575 let cast_expr = Expression::Cast(Box::new(Cast {
6577 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
6578 to: DataType::VarChar {
6579 length: Some(10),
6580 parenthesized_length: false,
6581 },
6582 trailing_comments: vec![],
6583 double_colon_syntax: false,
6584 format: None,
6585 default: None,
6586 inferred_type: None,
6587 }));
6588
6589 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6590 if let Expression::Cast(cast) = result {
6591 assert_eq!(
6592 cast.to,
6593 DataType::VarChar {
6594 length: None,
6595 parenthesized_length: false
6596 }
6597 );
6598 } else {
6599 panic!("Expected Cast expression");
6600 }
6601 }
6602
6603 #[test]
6604 fn test_remove_precision_direct_cast() {
6605 let cast = Expression::Cast(Box::new(Cast {
6609 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6610 to: DataType::Decimal {
6611 precision: Some(10),
6612 scale: Some(2),
6613 },
6614 trailing_comments: vec![],
6615 double_colon_syntax: false,
6616 format: None,
6617 default: None,
6618 inferred_type: None,
6619 }));
6620
6621 let transformed = remove_precision_parameterized_types(cast).unwrap();
6622 let generated = gen(&transformed);
6623
6624 assert!(generated.contains("DECIMAL"));
6626 assert!(!generated.contains("(10"));
6627 }
6628
6629 #[test]
6630 fn test_epoch_cast_to_ts() {
6631 let cast_expr = Expression::Cast(Box::new(Cast {
6633 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
6634 to: DataType::Timestamp {
6635 precision: None,
6636 timezone: false,
6637 },
6638 trailing_comments: vec![],
6639 double_colon_syntax: false,
6640 format: None,
6641 default: None,
6642 inferred_type: None,
6643 }));
6644
6645 let result = epoch_cast_to_ts(cast_expr).unwrap();
6646 if let Expression::Cast(cast) = result {
6647 if let Expression::Literal(lit) = cast.this {
6648 if let Literal::String(s) = lit.as_ref() {
6649 assert_eq!(s, "1970-01-01 00:00:00");
6650 }
6651 } else {
6652 panic!("Expected string literal");
6653 }
6654 } else {
6655 panic!("Expected Cast expression");
6656 }
6657 }
6658
6659 #[test]
6660 fn test_epoch_cast_to_ts_preserves_non_epoch() {
6661 let cast_expr = Expression::Cast(Box::new(Cast {
6663 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
6664 to: DataType::Timestamp {
6665 precision: None,
6666 timezone: false,
6667 },
6668 trailing_comments: vec![],
6669 double_colon_syntax: false,
6670 format: None,
6671 default: None,
6672 inferred_type: None,
6673 }));
6674
6675 let result = epoch_cast_to_ts(cast_expr).unwrap();
6676 if let Expression::Cast(cast) = result {
6677 if let Expression::Literal(lit) = cast.this {
6678 if let Literal::String(s) = lit.as_ref() {
6679 assert_eq!(s, "2024-01-15");
6680 }
6681 } else {
6682 panic!("Expected string literal");
6683 }
6684 } else {
6685 panic!("Expected Cast expression");
6686 }
6687 }
6688
6689 #[test]
6690 fn test_unqualify_columns() {
6691 let col = Expression::boxed_column(Column {
6693 name: Identifier::new("id".to_string()),
6694 table: Some(Identifier::new("users".to_string())),
6695 join_mark: false,
6696 trailing_comments: vec![],
6697 span: None,
6698 inferred_type: None,
6699 });
6700
6701 let result = unqualify_columns(col).unwrap();
6702 if let Expression::Column(c) = result {
6703 assert!(c.table.is_none());
6704 assert_eq!(c.name.name, "id");
6705 } else {
6706 panic!("Expected Column expression");
6707 }
6708 }
6709
6710 #[test]
6711 fn test_is_temporal_type() {
6712 assert!(is_temporal_type(&DataType::Date));
6713 assert!(is_temporal_type(&DataType::Timestamp {
6714 precision: None,
6715 timezone: false
6716 }));
6717 assert!(is_temporal_type(&DataType::Time {
6718 precision: None,
6719 timezone: false
6720 }));
6721 assert!(!is_temporal_type(&DataType::Int {
6722 length: None,
6723 integer_spelling: false
6724 }));
6725 assert!(!is_temporal_type(&DataType::VarChar {
6726 length: None,
6727 parenthesized_length: false
6728 }));
6729 }
6730
6731 #[test]
6732 fn test_eliminate_semi_join_basic() {
6733 use crate::expressions::{Join, TableRef};
6734
6735 let select = Expression::Select(Box::new(Select {
6737 expressions: vec![Expression::boxed_column(Column {
6738 name: Identifier::new("a".to_string()),
6739 table: None,
6740 join_mark: false,
6741 trailing_comments: vec![],
6742 span: None,
6743 inferred_type: None,
6744 })],
6745 from: Some(From {
6746 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
6747 }),
6748 joins: vec![Join {
6749 this: Expression::Table(Box::new(TableRef::new("t2"))),
6750 kind: JoinKind::Semi,
6751 on: Some(Expression::Eq(Box::new(BinaryOp {
6752 left: Expression::boxed_column(Column {
6753 name: Identifier::new("x".to_string()),
6754 table: None,
6755 join_mark: false,
6756 trailing_comments: vec![],
6757 span: None,
6758 inferred_type: None,
6759 }),
6760 right: Expression::boxed_column(Column {
6761 name: Identifier::new("y".to_string()),
6762 table: None,
6763 join_mark: false,
6764 trailing_comments: vec![],
6765 span: None,
6766 inferred_type: None,
6767 }),
6768 left_comments: vec![],
6769 operator_comments: vec![],
6770 trailing_comments: vec![],
6771 inferred_type: None,
6772 }))),
6773 using: vec![],
6774 use_inner_keyword: false,
6775 use_outer_keyword: false,
6776 deferred_condition: false,
6777 join_hint: None,
6778 match_condition: None,
6779 pivots: Vec::new(),
6780 comments: Vec::new(),
6781 nesting_group: 0,
6782 directed: false,
6783 }],
6784 ..Select::new()
6785 }));
6786
6787 let result = eliminate_semi_and_anti_joins(select).unwrap();
6788 if let Expression::Select(s) = result {
6789 assert!(s.joins.is_empty());
6791 assert!(s.where_clause.is_some());
6793 } else {
6794 panic!("Expected Select expression");
6795 }
6796 }
6797
6798 #[test]
6799 fn test_no_ilike_sql() {
6800 use crate::expressions::LikeOp;
6801
6802 let ilike_expr = Expression::ILike(Box::new(LikeOp {
6804 left: Expression::boxed_column(Column {
6805 name: Identifier::new("name".to_string()),
6806 table: None,
6807 join_mark: false,
6808 trailing_comments: vec![],
6809 span: None,
6810 inferred_type: None,
6811 }),
6812 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
6813 escape: None,
6814 quantifier: None,
6815 inferred_type: None,
6816 }));
6817
6818 let result = no_ilike_sql(ilike_expr).unwrap();
6819 if let Expression::Like(like) = result {
6820 if let Expression::Function(f) = &like.left {
6822 assert_eq!(f.name, "LOWER");
6823 } else {
6824 panic!("Expected LOWER function on left");
6825 }
6826 if let Expression::Function(f) = &like.right {
6828 assert_eq!(f.name, "LOWER");
6829 } else {
6830 panic!("Expected LOWER function on right");
6831 }
6832 } else {
6833 panic!("Expected Like expression");
6834 }
6835 }
6836
6837 #[test]
6838 fn test_no_trycast_sql() {
6839 let trycast_expr = Expression::TryCast(Box::new(Cast {
6841 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6842 to: DataType::Int {
6843 length: None,
6844 integer_spelling: false,
6845 },
6846 trailing_comments: vec![],
6847 double_colon_syntax: false,
6848 format: None,
6849 default: None,
6850 inferred_type: None,
6851 }));
6852
6853 let result = no_trycast_sql(trycast_expr).unwrap();
6854 assert!(matches!(result, Expression::Cast(_)));
6855 }
6856
6857 #[test]
6858 fn test_no_safe_cast_sql() {
6859 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
6861 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6862 to: DataType::Int {
6863 length: None,
6864 integer_spelling: false,
6865 },
6866 trailing_comments: vec![],
6867 double_colon_syntax: false,
6868 format: None,
6869 default: None,
6870 inferred_type: None,
6871 }));
6872
6873 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
6874 assert!(matches!(result, Expression::Cast(_)));
6875 }
6876
6877 #[test]
6878 fn test_explode_to_unnest_presto() {
6879 let spark = Dialect::get(DialectType::Spark);
6880 let result = spark
6881 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
6882 .unwrap();
6883 assert_eq!(
6884 result[0],
6885 "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))"
6886 );
6887 }
6888
6889 #[test]
6890 fn test_explode_to_unnest_bigquery() {
6891 let spark = Dialect::get(DialectType::Spark);
6892 let result = spark
6893 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
6894 .unwrap();
6895 assert_eq!(
6896 result[0],
6897 "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))"
6898 );
6899 }
6900}