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