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 vertica: None,
1299 expressions: outer_exprs,
1300 from: Some(From {
1301 expressions: vec![Expression::Subquery(Box::new(subquery))],
1302 }),
1303 where_clause: Some(Where { this: outer_where }),
1304 ..Select::new()
1305 };
1306
1307 return Ok(Expression::Select(Box::new(outer_select)));
1308 } else {
1309 let qualify_alias = Expression::Alias(Box::new(crate::expressions::Alias {
1311 this: qualify_filter.clone(),
1312 alias: window_alias_ident.clone(),
1313 column_aliases: vec![],
1314 alias_explicit_as: false,
1315 alias_keyword: None,
1316 pre_alias_comments: vec![],
1317 trailing_comments: vec![],
1318 inferred_type: None,
1319 }));
1320
1321 let original_exprs = select.expressions.clone();
1322 select.expressions.push(qualify_alias);
1323
1324 let inner_select = Expression::Select(select);
1325 let subquery = Subquery {
1326 this: inner_select,
1327 alias: Some(Identifier::new("_t".to_string())),
1328 column_aliases: vec![],
1329 alias_explicit_as: false,
1330 alias_keyword: None,
1331 order_by: None,
1332 limit: None,
1333 offset: None,
1334 distribute_by: None,
1335 sort_by: None,
1336 cluster_by: None,
1337 lateral: false,
1338 modifiers_inside: false,
1339 trailing_comments: vec![],
1340 inferred_type: None,
1341 };
1342
1343 let outer_select = Select {
1344 vertica: None,
1345 expressions: original_exprs,
1346 from: Some(From {
1347 expressions: vec![Expression::Subquery(Box::new(subquery))],
1348 }),
1349 where_clause: Some(Where {
1350 this: Expression::Column(Box::new(crate::expressions::Column {
1351 name: window_alias_ident,
1352 table: None,
1353 join_mark: false,
1354 trailing_comments: vec![],
1355 span: None,
1356 inferred_type: None,
1357 })),
1358 }),
1359 ..Select::new()
1360 };
1361
1362 return Ok(Expression::Select(Box::new(outer_select)));
1363 }
1364 }
1365 Ok(Expression::Select(select))
1366 }
1367 other => Ok(other),
1368 }
1369}
1370
1371fn extract_window_from_condition(
1375 condition: Expression,
1376 alias: &Identifier,
1377) -> (Option<Expression>, Expression) {
1378 let alias_col = Expression::Column(Box::new(crate::expressions::Column {
1379 name: alias.clone(),
1380 table: None,
1381 join_mark: false,
1382 trailing_comments: vec![],
1383 span: None,
1384 inferred_type: None,
1385 }));
1386
1387 match condition {
1389 Expression::Eq(ref op) => {
1391 if is_window_expr(&op.left) {
1392 (
1393 Some(op.left.clone()),
1394 Expression::Eq(Box::new(BinaryOp {
1395 left: alias_col,
1396 right: op.right.clone(),
1397 ..(**op).clone()
1398 })),
1399 )
1400 } else if is_window_expr(&op.right) {
1401 (
1402 Some(op.right.clone()),
1403 Expression::Eq(Box::new(BinaryOp {
1404 left: op.left.clone(),
1405 right: alias_col,
1406 ..(**op).clone()
1407 })),
1408 )
1409 } else {
1410 (None, condition)
1411 }
1412 }
1413 Expression::Neq(ref op) => {
1414 if is_window_expr(&op.left) {
1415 (
1416 Some(op.left.clone()),
1417 Expression::Neq(Box::new(BinaryOp {
1418 left: alias_col,
1419 right: op.right.clone(),
1420 ..(**op).clone()
1421 })),
1422 )
1423 } else if is_window_expr(&op.right) {
1424 (
1425 Some(op.right.clone()),
1426 Expression::Neq(Box::new(BinaryOp {
1427 left: op.left.clone(),
1428 right: alias_col,
1429 ..(**op).clone()
1430 })),
1431 )
1432 } else {
1433 (None, condition)
1434 }
1435 }
1436 Expression::Lt(ref op) => {
1437 if is_window_expr(&op.left) {
1438 (
1439 Some(op.left.clone()),
1440 Expression::Lt(Box::new(BinaryOp {
1441 left: alias_col,
1442 right: op.right.clone(),
1443 ..(**op).clone()
1444 })),
1445 )
1446 } else if is_window_expr(&op.right) {
1447 (
1448 Some(op.right.clone()),
1449 Expression::Lt(Box::new(BinaryOp {
1450 left: op.left.clone(),
1451 right: alias_col,
1452 ..(**op).clone()
1453 })),
1454 )
1455 } else {
1456 (None, condition)
1457 }
1458 }
1459 Expression::Lte(ref op) => {
1460 if is_window_expr(&op.left) {
1461 (
1462 Some(op.left.clone()),
1463 Expression::Lte(Box::new(BinaryOp {
1464 left: alias_col,
1465 right: op.right.clone(),
1466 ..(**op).clone()
1467 })),
1468 )
1469 } else if is_window_expr(&op.right) {
1470 (
1471 Some(op.right.clone()),
1472 Expression::Lte(Box::new(BinaryOp {
1473 left: op.left.clone(),
1474 right: alias_col,
1475 ..(**op).clone()
1476 })),
1477 )
1478 } else {
1479 (None, condition)
1480 }
1481 }
1482 Expression::Gt(ref op) => {
1483 if is_window_expr(&op.left) {
1484 (
1485 Some(op.left.clone()),
1486 Expression::Gt(Box::new(BinaryOp {
1487 left: alias_col,
1488 right: op.right.clone(),
1489 ..(**op).clone()
1490 })),
1491 )
1492 } else if is_window_expr(&op.right) {
1493 (
1494 Some(op.right.clone()),
1495 Expression::Gt(Box::new(BinaryOp {
1496 left: op.left.clone(),
1497 right: alias_col,
1498 ..(**op).clone()
1499 })),
1500 )
1501 } else {
1502 (None, condition)
1503 }
1504 }
1505 Expression::Gte(ref op) => {
1506 if is_window_expr(&op.left) {
1507 (
1508 Some(op.left.clone()),
1509 Expression::Gte(Box::new(BinaryOp {
1510 left: alias_col,
1511 right: op.right.clone(),
1512 ..(**op).clone()
1513 })),
1514 )
1515 } else if is_window_expr(&op.right) {
1516 (
1517 Some(op.right.clone()),
1518 Expression::Gte(Box::new(BinaryOp {
1519 left: op.left.clone(),
1520 right: alias_col,
1521 ..(**op).clone()
1522 })),
1523 )
1524 } else {
1525 (None, condition)
1526 }
1527 }
1528 _ if is_window_expr(&condition) => (Some(condition), alias_col),
1530 _ => (None, condition),
1532 }
1533}
1534
1535fn is_window_expr(expr: &Expression) -> bool {
1537 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
1538}
1539
1540pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
1559 eliminate_distinct_on_for_dialect(expr, None, None)
1560}
1561
1562pub fn strip_cte_materialization(expr: Expression) -> Result<Expression> {
1565 transform_recursive(expr, &strip_cte_materialization_single)
1566}
1567
1568fn strip_cte_materialization_single(expr: Expression) -> Result<Expression> {
1569 Ok(match expr {
1570 Expression::Select(mut select) => {
1571 strip_with_cte_materialization(&mut select.with);
1572 Expression::Select(select)
1573 }
1574 Expression::Union(mut union) => {
1575 strip_with_cte_materialization(&mut union.with);
1576 Expression::Union(union)
1577 }
1578 Expression::Intersect(mut intersect) => {
1579 strip_with_cte_materialization(&mut intersect.with);
1580 Expression::Intersect(intersect)
1581 }
1582 Expression::Except(mut except) => {
1583 strip_with_cte_materialization(&mut except.with);
1584 Expression::Except(except)
1585 }
1586 Expression::Pivot(mut pivot) => {
1587 strip_with_cte_materialization(&mut pivot.with);
1588 Expression::Pivot(pivot)
1589 }
1590 Expression::Insert(mut insert) => {
1591 strip_with_cte_materialization(&mut insert.with);
1592 Expression::Insert(insert)
1593 }
1594 Expression::Update(mut update) => {
1595 strip_with_cte_materialization(&mut update.with);
1596 Expression::Update(update)
1597 }
1598 Expression::Delete(mut delete) => {
1599 strip_with_cte_materialization(&mut delete.with);
1600 Expression::Delete(delete)
1601 }
1602 Expression::CreateTable(mut create_table) => {
1603 strip_with_cte_materialization(&mut create_table.with_cte);
1604 Expression::CreateTable(create_table)
1605 }
1606 Expression::With(mut with) => {
1607 strip_cte_materialization_in_with(&mut with);
1608 Expression::With(with)
1609 }
1610 Expression::Cte(mut cte) => {
1611 cte.materialized = None;
1612 Expression::Cte(cte)
1613 }
1614 _ => expr,
1615 })
1616}
1617
1618fn strip_with_cte_materialization(with: &mut Option<With>) {
1619 if let Some(with) = with {
1620 strip_cte_materialization_in_with(with);
1621 }
1622}
1623
1624fn strip_cte_materialization_in_with(with: &mut With) {
1625 for cte in &mut with.ctes {
1626 cte.materialized = None;
1627 }
1628}
1629
1630#[derive(Clone, Copy)]
1631enum DistinctOnNullsMode {
1632 None,
1633 NullsFirst,
1634 CaseExpr,
1635}
1636
1637pub fn eliminate_distinct_on_for_dialect(
1642 expr: Expression,
1643 target: Option<DialectType>,
1644 source: Option<DialectType>,
1645) -> Result<Expression> {
1646 if matches!(
1648 target,
1649 Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)
1650 ) {
1651 return Ok(expr);
1652 }
1653
1654 let nulls_mode = match target {
1659 Some(DialectType::MySQL)
1660 | Some(DialectType::SingleStore)
1661 | Some(DialectType::TSQL)
1662 | Some(DialectType::Fabric) => DistinctOnNullsMode::CaseExpr,
1663 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => {
1664 DistinctOnNullsMode::None
1665 }
1666 Some(DialectType::StarRocks) => {
1667 if matches!(source, Some(DialectType::Redshift)) {
1668 DistinctOnNullsMode::CaseExpr
1669 } else {
1670 DistinctOnNullsMode::None
1671 }
1672 }
1673 _ => DistinctOnNullsMode::NullsFirst,
1675 };
1676
1677 transform_recursive(expr, &|expr| eliminate_distinct_on_select(expr, nulls_mode))
1678}
1679
1680fn eliminate_distinct_on_select(
1681 expr: Expression,
1682 nulls_mode: DistinctOnNullsMode,
1683) -> Result<Expression> {
1684 use crate::expressions::Case;
1685
1686 match expr {
1687 Expression::Select(mut select) => {
1688 if let Some(distinct_cols) = select.distinct_on.take() {
1689 if !distinct_cols.is_empty() {
1690 let row_number_alias = Identifier::new("_row_number".to_string());
1692
1693 let order_exprs = if let Some(ref order_by) = select.order_by {
1695 let mut exprs = order_by.expressions.clone();
1696 match nulls_mode {
1698 DistinctOnNullsMode::NullsFirst => {
1699 for ord in &mut exprs {
1700 if ord.desc && ord.nulls_first.is_none() {
1701 ord.nulls_first = Some(true);
1702 }
1703 }
1704 }
1705 DistinctOnNullsMode::CaseExpr => {
1706 let mut new_exprs = Vec::new();
1709 for ord in &exprs {
1710 if ord.desc && ord.nulls_first.is_none() {
1711 let null_check = Expression::Case(Box::new(Case {
1713 operand: None,
1714 whens: vec![(
1715 Expression::IsNull(Box::new(
1716 crate::expressions::IsNull {
1717 this: ord.this.clone(),
1718 not: false,
1719 postfix_form: false,
1720 },
1721 )),
1722 Expression::Literal(Box::new(Literal::Number(
1723 "1".to_string(),
1724 ))),
1725 )],
1726 else_: Some(Expression::Literal(Box::new(
1727 Literal::Number("0".to_string()),
1728 ))),
1729 comments: Vec::new(),
1730 inferred_type: None,
1731 }));
1732 new_exprs.push(crate::expressions::Ordered {
1733 nulls_auto: false,
1734 this: null_check,
1735 desc: true,
1736 nulls_first: None,
1737 explicit_asc: false,
1738 with_fill: None,
1739 });
1740 }
1741 new_exprs.push(ord.clone());
1742 }
1743 exprs = new_exprs;
1744 }
1745 DistinctOnNullsMode::None => {}
1746 }
1747 exprs
1748 } else {
1749 distinct_cols
1750 .iter()
1751 .map(|e| crate::expressions::Ordered {
1752 nulls_auto: false,
1753 this: e.clone(),
1754 desc: false,
1755 nulls_first: None,
1756 explicit_asc: false,
1757 with_fill: None,
1758 })
1759 .collect()
1760 };
1761
1762 let row_number_func =
1764 Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
1765 this: Expression::RowNumber(crate::expressions::RowNumber),
1766 over: Over {
1767 partition_by: distinct_cols,
1768 order_by: order_exprs,
1769 frame: None,
1770 window_name: None,
1771 alias: None,
1772 },
1773 keep: None,
1774 inferred_type: None,
1775 }));
1776
1777 let mut inner_aliased_exprs = Vec::new();
1781 let mut outer_select_exprs = Vec::new();
1782 for orig_expr in &select.expressions {
1783 match orig_expr {
1784 Expression::Alias(alias) => {
1785 inner_aliased_exprs.push(orig_expr.clone());
1787 outer_select_exprs.push(Expression::Column(Box::new(
1788 crate::expressions::Column {
1789 name: alias.alias.clone(),
1790 table: None,
1791 join_mark: false,
1792 trailing_comments: vec![],
1793 span: None,
1794 inferred_type: None,
1795 },
1796 )));
1797 }
1798 Expression::Column(col) => {
1799 inner_aliased_exprs.push(Expression::Alias(Box::new(
1801 crate::expressions::Alias {
1802 this: orig_expr.clone(),
1803 alias: col.name.clone(),
1804 column_aliases: vec![],
1805 alias_explicit_as: false,
1806 alias_keyword: None,
1807 pre_alias_comments: vec![],
1808 trailing_comments: vec![],
1809 inferred_type: None,
1810 },
1811 )));
1812 outer_select_exprs.push(Expression::Column(Box::new(
1813 crate::expressions::Column {
1814 name: col.name.clone(),
1815 table: None,
1816 join_mark: false,
1817 trailing_comments: vec![],
1818 span: None,
1819 inferred_type: None,
1820 },
1821 )));
1822 }
1823 _ => {
1824 inner_aliased_exprs.push(orig_expr.clone());
1826 outer_select_exprs.push(orig_expr.clone());
1827 }
1828 }
1829 }
1830
1831 let row_number_alias_expr =
1833 Expression::Alias(Box::new(crate::expressions::Alias {
1834 this: row_number_func,
1835 alias: row_number_alias.clone(),
1836 column_aliases: vec![],
1837 alias_explicit_as: false,
1838 alias_keyword: None,
1839 pre_alias_comments: vec![],
1840 trailing_comments: vec![],
1841 inferred_type: None,
1842 }));
1843 inner_aliased_exprs.push(row_number_alias_expr);
1844
1845 select.expressions = inner_aliased_exprs;
1847
1848 let _inner_order_by = select.order_by.take();
1850
1851 select.distinct = false;
1853
1854 let inner_select = Expression::Select(select);
1856 let subquery = Subquery {
1857 this: inner_select,
1858 alias: Some(Identifier::new("_t".to_string())),
1859 column_aliases: vec![],
1860 alias_explicit_as: false,
1861 alias_keyword: None,
1862 order_by: None,
1863 limit: None,
1864 offset: None,
1865 distribute_by: None,
1866 sort_by: None,
1867 cluster_by: None,
1868 lateral: false,
1869 modifiers_inside: false,
1870 trailing_comments: vec![],
1871 inferred_type: None,
1872 };
1873
1874 let outer_select = Select {
1877 vertica: None,
1878 expressions: outer_select_exprs,
1879 from: Some(From {
1880 expressions: vec![Expression::Subquery(Box::new(subquery))],
1881 }),
1882 where_clause: Some(Where {
1883 this: Expression::Eq(Box::new(BinaryOp {
1884 left: Expression::Column(Box::new(crate::expressions::Column {
1885 name: row_number_alias,
1886 table: None,
1887 join_mark: false,
1888 trailing_comments: vec![],
1889 span: None,
1890 inferred_type: None,
1891 })),
1892 right: Expression::Literal(Box::new(Literal::Number(
1893 "1".to_string(),
1894 ))),
1895 left_comments: vec![],
1896 operator_comments: vec![],
1897 trailing_comments: vec![],
1898 inferred_type: None,
1899 })),
1900 }),
1901 ..Select::new()
1902 };
1903
1904 return Ok(Expression::Select(Box::new(outer_select)));
1905 }
1906 }
1907 Ok(Expression::Select(select))
1908 }
1909 other => Ok(other),
1910 }
1911}
1912
1913pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
1921 match expr {
1922 Expression::Select(mut select) => {
1923 let mut new_joins = Vec::new();
1924 let mut extra_where_conditions = Vec::new();
1925
1926 for join in select.joins.drain(..) {
1927 match join.kind {
1928 JoinKind::Semi | JoinKind::LeftSemi => {
1929 if let Some(on_condition) = join.on {
1930 let subquery_select = Select {
1932 vertica: None,
1933 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1934 "1".to_string(),
1935 )))],
1936 from: Some(From {
1937 expressions: vec![join.this],
1938 }),
1939 where_clause: Some(Where { this: on_condition }),
1940 ..Select::new()
1941 };
1942
1943 let exists = Expression::Exists(Box::new(Exists {
1944 this: Expression::Subquery(Box::new(Subquery {
1945 this: Expression::Select(Box::new(subquery_select)),
1946 alias: None,
1947 column_aliases: vec![],
1948 alias_explicit_as: false,
1949 alias_keyword: None,
1950 order_by: None,
1951 limit: None,
1952 offset: None,
1953 distribute_by: None,
1954 sort_by: None,
1955 cluster_by: None,
1956 lateral: false,
1957 modifiers_inside: false,
1958 trailing_comments: vec![],
1959 inferred_type: None,
1960 })),
1961 not: false,
1962 }));
1963
1964 extra_where_conditions.push(exists);
1965 }
1966 }
1967 JoinKind::Anti | JoinKind::LeftAnti => {
1968 if let Some(on_condition) = join.on {
1969 let subquery_select = Select {
1971 vertica: None,
1972 expressions: vec![Expression::Literal(Box::new(Literal::Number(
1973 "1".to_string(),
1974 )))],
1975 from: Some(From {
1976 expressions: vec![join.this],
1977 }),
1978 where_clause: Some(Where { this: on_condition }),
1979 ..Select::new()
1980 };
1981
1982 let not_exists = Expression::Exists(Box::new(Exists {
1984 this: Expression::Subquery(Box::new(Subquery {
1985 this: Expression::Select(Box::new(subquery_select)),
1986 alias: None,
1987 column_aliases: vec![],
1988 alias_explicit_as: false,
1989 alias_keyword: None,
1990 order_by: None,
1991 limit: None,
1992 offset: None,
1993 distribute_by: None,
1994 sort_by: None,
1995 cluster_by: None,
1996 lateral: false,
1997 modifiers_inside: false,
1998 trailing_comments: vec![],
1999 inferred_type: None,
2000 })),
2001 not: true,
2002 }));
2003
2004 extra_where_conditions.push(not_exists);
2005 }
2006 }
2007 _ => {
2008 new_joins.push(join);
2010 }
2011 }
2012 }
2013
2014 select.joins = new_joins;
2015
2016 if !extra_where_conditions.is_empty() {
2018 let combined = extra_where_conditions
2019 .into_iter()
2020 .reduce(|acc, cond| {
2021 Expression::And(Box::new(BinaryOp {
2022 left: acc,
2023 right: cond,
2024 left_comments: vec![],
2025 operator_comments: vec![],
2026 trailing_comments: vec![],
2027 inferred_type: None,
2028 }))
2029 })
2030 .unwrap();
2031
2032 select.where_clause = match select.where_clause {
2033 Some(Where { this: existing }) => Some(Where {
2034 this: Expression::And(Box::new(BinaryOp {
2035 left: existing,
2036 right: combined,
2037 left_comments: vec![],
2038 operator_comments: vec![],
2039 trailing_comments: vec![],
2040 inferred_type: None,
2041 })),
2042 }),
2043 None => Some(Where { this: combined }),
2044 };
2045 }
2046
2047 Ok(Expression::Select(select))
2048 }
2049 other => Ok(other),
2050 }
2051}
2052
2053pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
2071 match expr {
2072 Expression::Select(mut select) => {
2073 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
2075
2076 if let Some(idx) = full_outer_join_idx {
2077 let full_join_count = select
2079 .joins
2080 .iter()
2081 .filter(|j| j.kind == JoinKind::Full)
2082 .count();
2083 if full_join_count != 1 {
2084 return Ok(Expression::Select(select));
2085 }
2086
2087 let mut right_select = select.clone();
2089
2090 let full_join = &select.joins[idx];
2092 let join_condition = full_join.on.clone();
2093
2094 select.joins[idx].kind = JoinKind::Left;
2096
2097 right_select.joins[idx].kind = JoinKind::Right;
2099
2100 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
2102 if !from.expressions.is_empty() {
2103 let anti_subquery = Expression::Select(Box::new(Select {
2104 vertica: None,
2105 expressions: vec![Expression::Literal(Box::new(Literal::Number(
2106 "1".to_string(),
2107 )))],
2108 from: Some(from.clone()),
2109 where_clause: Some(Where {
2110 this: join_cond.clone(),
2111 }),
2112 ..Select::new()
2113 }));
2114
2115 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
2116 inferred_type: None,
2117 this: Expression::Exists(Box::new(Exists {
2118 this: Expression::Subquery(Box::new(Subquery {
2119 this: anti_subquery,
2120 alias: None,
2121 column_aliases: vec![],
2122 alias_explicit_as: false,
2123 alias_keyword: None,
2124 order_by: None,
2125 limit: None,
2126 offset: None,
2127 distribute_by: None,
2128 sort_by: None,
2129 cluster_by: None,
2130 lateral: false,
2131 modifiers_inside: false,
2132 trailing_comments: vec![],
2133 inferred_type: None,
2134 })),
2135 not: false,
2136 })),
2137 }));
2138
2139 right_select.where_clause = Some(Where {
2141 this: match right_select.where_clause {
2142 Some(w) => Expression::And(Box::new(BinaryOp {
2143 left: w.this,
2144 right: not_exists,
2145 left_comments: vec![],
2146 operator_comments: vec![],
2147 trailing_comments: vec![],
2148 inferred_type: None,
2149 })),
2150 None => not_exists,
2151 },
2152 });
2153 }
2154 }
2155
2156 right_select.with = None;
2158
2159 let order_by = select.order_by.take();
2161
2162 let union = crate::expressions::Union {
2164 left: Expression::Select(select),
2165 right: Expression::Select(right_select),
2166 all: true, distinct: false,
2168 with: None,
2169 order_by,
2170 limit: None,
2171 offset: None,
2172 distribute_by: None,
2173 sort_by: None,
2174 cluster_by: None,
2175 by_name: false,
2176 side: None,
2177 kind: None,
2178 corresponding: false,
2179 strict: false,
2180 on_columns: Vec::new(),
2181 };
2182
2183 return Ok(Expression::Union(Box::new(union)));
2184 }
2185
2186 Ok(Expression::Select(select))
2187 }
2188 other => Ok(other),
2189 }
2190}
2191
2192pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
2205 match expr {
2206 Expression::Select(mut select) => {
2207 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
2209 let mut has_recursive = false;
2210
2211 collect_nested_ctes(
2212 &Expression::Select(select.clone()),
2213 &mut collected_ctes,
2214 &mut has_recursive,
2215 true,
2216 );
2217
2218 let mut cte_body_collected: Vec<(String, Vec<crate::expressions::Cte>)> = Vec::new();
2221 if let Some(ref with) = select.with {
2222 for cte in &with.ctes {
2223 let mut body_ctes: Vec<crate::expressions::Cte> = Vec::new();
2224 collect_ctes_from_cte_body(&cte.this, &mut body_ctes, &mut has_recursive);
2225 if !body_ctes.is_empty() {
2226 cte_body_collected.push((cte.alias.name.clone(), body_ctes));
2227 }
2228 }
2229 }
2230
2231 let has_subquery_ctes = !collected_ctes.is_empty();
2232 let has_body_ctes = !cte_body_collected.is_empty();
2233
2234 if has_subquery_ctes || has_body_ctes {
2235 strip_nested_with_clauses(&mut select, true);
2237
2238 if has_body_ctes {
2240 if let Some(ref mut with) = select.with {
2241 for cte in with.ctes.iter_mut() {
2242 strip_with_from_cte_body(&mut cte.this);
2243 }
2244 }
2245 }
2246
2247 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
2248 ctes: Vec::new(),
2249 recursive: false,
2250 leading_comments: vec![],
2251 search: None,
2252 });
2253
2254 if has_recursive {
2255 top_with.recursive = true;
2256 }
2257
2258 if has_body_ctes {
2260 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2261 for mut cte in top_with.ctes.drain(..) {
2262 if let Some(pos) = cte_body_collected
2264 .iter()
2265 .position(|(name, _)| *name == cte.alias.name)
2266 {
2267 let (_, mut nested) = cte_body_collected.remove(pos);
2268 for nested_cte in nested.iter_mut() {
2270 strip_with_from_cte_body(&mut nested_cte.this);
2271 }
2272 new_ctes.extend(nested);
2273 }
2274 strip_with_from_cte_body(&mut cte.this);
2276 new_ctes.push(cte);
2277 }
2278 top_with.ctes = new_ctes;
2279 }
2280
2281 top_with.ctes.extend(collected_ctes);
2283 }
2284
2285 Ok(Expression::Select(select))
2286 }
2287 other => Ok(other),
2288 }
2289}
2290
2291fn collect_ctes_from_cte_body(
2293 expr: &Expression,
2294 collected: &mut Vec<crate::expressions::Cte>,
2295 has_recursive: &mut bool,
2296) {
2297 if let Expression::Select(select) = expr {
2298 if let Some(ref with) = select.with {
2299 if with.recursive {
2300 *has_recursive = true;
2301 }
2302 for cte in &with.ctes {
2303 collect_ctes_from_cte_body(&cte.this, collected, has_recursive);
2305 collected.push(cte.clone());
2307 }
2308 }
2309 }
2310}
2311
2312fn strip_with_from_cte_body(expr: &mut Expression) {
2314 if let Expression::Select(ref mut select) = expr {
2315 select.with = None;
2316 }
2317}
2318
2319fn strip_nested_with_clauses(select: &mut Select, _is_top_level: bool) {
2321 if let Some(ref mut from) = select.from {
2323 for expr in from.expressions.iter_mut() {
2324 strip_with_from_expr(expr);
2325 }
2326 }
2327 for join in select.joins.iter_mut() {
2329 strip_with_from_expr(&mut join.this);
2330 }
2331 for expr in select.expressions.iter_mut() {
2333 strip_with_from_expr(expr);
2334 }
2335 if let Some(ref mut w) = select.where_clause {
2337 strip_with_from_expr(&mut w.this);
2338 }
2339}
2340
2341fn strip_with_from_expr(expr: &mut Expression) {
2342 match expr {
2343 Expression::Subquery(ref mut subquery) => {
2344 strip_with_from_inner_query(&mut subquery.this);
2345 }
2346 Expression::Alias(ref mut alias) => {
2347 strip_with_from_expr(&mut alias.this);
2348 }
2349 Expression::Select(ref mut select) => {
2350 select.with = None;
2352 strip_nested_with_clauses(select, false);
2354 }
2355 _ => {}
2356 }
2357}
2358
2359fn strip_with_from_inner_query(expr: &mut Expression) {
2360 if let Expression::Select(ref mut select) = expr {
2361 select.with = None;
2362 strip_nested_with_clauses(select, false);
2363 }
2364}
2365
2366fn collect_nested_ctes(
2368 expr: &Expression,
2369 collected: &mut Vec<crate::expressions::Cte>,
2370 has_recursive: &mut bool,
2371 is_top_level: bool,
2372) {
2373 match expr {
2374 Expression::Select(select) => {
2375 if !is_top_level {
2377 if let Some(ref with) = select.with {
2378 if with.recursive {
2379 *has_recursive = true;
2380 }
2381 collected.extend(with.ctes.clone());
2382 }
2383 }
2384
2385 if let Some(ref from) = select.from {
2387 for expr in &from.expressions {
2388 collect_nested_ctes(expr, collected, has_recursive, false);
2389 }
2390 }
2391
2392 for join in &select.joins {
2394 collect_nested_ctes(&join.this, collected, has_recursive, false);
2395 }
2396
2397 for sel_expr in &select.expressions {
2399 collect_nested_ctes(sel_expr, collected, has_recursive, false);
2400 }
2401
2402 if let Some(ref where_clause) = select.where_clause {
2404 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
2405 }
2406 }
2407 Expression::Subquery(subquery) => {
2408 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
2410 }
2411 Expression::Alias(alias) => {
2412 collect_nested_ctes(&alias.this, collected, has_recursive, false);
2413 }
2414 _ => {}
2416 }
2417}
2418
2419pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
2435 match expr {
2436 Expression::Select(mut select) => {
2437 if let Some(named_windows) = select.windows.take() {
2438 let window_map: std::collections::HashMap<String, &Over> = named_windows
2440 .iter()
2441 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
2442 .collect();
2443
2444 select.expressions = select
2446 .expressions
2447 .into_iter()
2448 .map(|e| inline_window_refs(e, &window_map))
2449 .collect();
2450 }
2451 Ok(Expression::Select(select))
2452 }
2453 other => Ok(other),
2454 }
2455}
2456
2457fn inline_window_refs(
2459 expr: Expression,
2460 window_map: &std::collections::HashMap<String, &Over>,
2461) -> Expression {
2462 match expr {
2463 Expression::WindowFunction(mut wf) => {
2464 if let Some(ref name) = wf.over.window_name {
2466 let key = name.name.to_lowercase();
2467 if let Some(named_spec) = window_map.get(&key) {
2468 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
2470 wf.over.partition_by = named_spec.partition_by.clone();
2471 }
2472 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
2473 wf.over.order_by = named_spec.order_by.clone();
2474 }
2475 if wf.over.frame.is_none() && named_spec.frame.is_some() {
2476 wf.over.frame = named_spec.frame.clone();
2477 }
2478 wf.over.window_name = None;
2480 }
2481 }
2482 Expression::WindowFunction(wf)
2483 }
2484 Expression::Alias(mut alias) => {
2485 alias.this = inline_window_refs(alias.this, window_map);
2487 Expression::Alias(alias)
2488 }
2489 other => other,
2492 }
2493}
2494
2495pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
2509 match expr {
2510 Expression::Select(mut select) => {
2511 let has_join_marks = select
2513 .where_clause
2514 .as_ref()
2515 .map_or(false, |w| contains_join_mark(&w.this));
2516
2517 if !has_join_marks {
2518 return Ok(Expression::Select(select));
2519 }
2520
2521 let from_tables: Vec<String> = select
2523 .from
2524 .as_ref()
2525 .map(|f| {
2526 f.expressions
2527 .iter()
2528 .filter_map(|e| get_table_name(e))
2529 .collect()
2530 })
2531 .unwrap_or_default();
2532
2533 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
2535 std::collections::HashMap::new();
2536 let mut remaining_conditions: Vec<Expression> = Vec::new();
2537
2538 if let Some(ref where_clause) = select.where_clause {
2539 extract_join_mark_conditions(
2540 &where_clause.this,
2541 &mut join_conditions,
2542 &mut remaining_conditions,
2543 );
2544 }
2545
2546 let mut new_joins = select.joins.clone();
2548 for (table_name, conditions) in join_conditions {
2549 let table_in_from = from_tables.contains(&table_name);
2551
2552 if table_in_from && !conditions.is_empty() {
2553 let combined_condition = conditions.into_iter().reduce(|a, b| {
2555 Expression::And(Box::new(BinaryOp {
2556 left: a,
2557 right: b,
2558 left_comments: vec![],
2559 operator_comments: vec![],
2560 trailing_comments: vec![],
2561 inferred_type: None,
2562 }))
2563 });
2564
2565 if let Some(ref mut from) = select.from {
2567 if let Some(pos) = from
2568 .expressions
2569 .iter()
2570 .position(|e| get_table_name(e).map_or(false, |n| n == table_name))
2571 {
2572 if from.expressions.len() > 1 {
2573 let join_table = from.expressions.remove(pos);
2574 new_joins.push(crate::expressions::Join {
2575 this: join_table,
2576 kind: JoinKind::Left,
2577 on: combined_condition,
2578 using: vec![],
2579 use_inner_keyword: false,
2580 use_outer_keyword: true,
2581 deferred_condition: false,
2582 join_hint: None,
2583 match_condition: None,
2584 pivots: Vec::new(),
2585 comments: Vec::new(),
2586 nesting_group: 0,
2587 directed: false,
2588 });
2589 }
2590 }
2591 }
2592 }
2593 }
2594
2595 select.joins = new_joins;
2596
2597 if remaining_conditions.is_empty() {
2599 select.where_clause = None;
2600 } else {
2601 let combined = remaining_conditions.into_iter().reduce(|a, b| {
2602 Expression::And(Box::new(BinaryOp {
2603 left: a,
2604 right: b,
2605 left_comments: vec![],
2606 operator_comments: vec![],
2607 trailing_comments: vec![],
2608 inferred_type: None,
2609 }))
2610 });
2611 select.where_clause = combined.map(|c| Where { this: c });
2612 }
2613
2614 clear_join_marks(&mut Expression::Select(select.clone()));
2616
2617 Ok(Expression::Select(select))
2618 }
2619 other => Ok(other),
2620 }
2621}
2622
2623fn contains_join_mark(expr: &Expression) -> bool {
2625 match expr {
2626 Expression::Column(col) => col.join_mark,
2627 Expression::And(op) | Expression::Or(op) => {
2628 contains_join_mark(&op.left) || contains_join_mark(&op.right)
2629 }
2630 Expression::Eq(op)
2631 | Expression::Neq(op)
2632 | Expression::Lt(op)
2633 | Expression::Lte(op)
2634 | Expression::Gt(op)
2635 | Expression::Gte(op) => contains_join_mark(&op.left) || contains_join_mark(&op.right),
2636 Expression::Not(op) => contains_join_mark(&op.this),
2637 _ => false,
2638 }
2639}
2640
2641fn get_table_name(expr: &Expression) -> Option<String> {
2643 match expr {
2644 Expression::Table(t) => Some(t.name.name.clone()),
2645 Expression::Alias(a) => Some(a.alias.name.clone()),
2646 _ => None,
2647 }
2648}
2649
2650fn extract_join_mark_conditions(
2652 expr: &Expression,
2653 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
2654 remaining: &mut Vec<Expression>,
2655) {
2656 match expr {
2657 Expression::And(op) => {
2658 extract_join_mark_conditions(&op.left, join_conditions, remaining);
2659 extract_join_mark_conditions(&op.right, join_conditions, remaining);
2660 }
2661 _ => {
2662 if let Some(table) = get_join_mark_table(expr) {
2663 join_conditions
2664 .entry(table)
2665 .or_insert_with(Vec::new)
2666 .push(expr.clone());
2667 } else {
2668 remaining.push(expr.clone());
2669 }
2670 }
2671 }
2672}
2673
2674fn get_join_mark_table(expr: &Expression) -> Option<String> {
2676 match expr {
2677 Expression::Eq(op)
2678 | Expression::Neq(op)
2679 | Expression::Lt(op)
2680 | Expression::Lte(op)
2681 | Expression::Gt(op)
2682 | Expression::Gte(op) => {
2683 if let Expression::Column(col) = &op.left {
2685 if col.join_mark {
2686 return col.table.as_ref().map(|t| t.name.clone());
2687 }
2688 }
2689 if let Expression::Column(col) = &op.right {
2690 if col.join_mark {
2691 return col.table.as_ref().map(|t| t.name.clone());
2692 }
2693 }
2694 None
2695 }
2696 _ => None,
2697 }
2698}
2699
2700fn clear_join_marks(expr: &mut Expression) {
2702 match expr {
2703 Expression::Column(col) => col.join_mark = false,
2704 Expression::Select(select) => {
2705 if let Some(ref mut w) = select.where_clause {
2706 clear_join_marks(&mut w.this);
2707 }
2708 for sel_expr in &mut select.expressions {
2709 clear_join_marks(sel_expr);
2710 }
2711 }
2712 Expression::And(op) | Expression::Or(op) => {
2713 clear_join_marks(&mut op.left);
2714 clear_join_marks(&mut op.right);
2715 }
2716 Expression::Eq(op)
2717 | Expression::Neq(op)
2718 | Expression::Lt(op)
2719 | Expression::Lte(op)
2720 | Expression::Gt(op)
2721 | Expression::Gte(op) => {
2722 clear_join_marks(&mut op.left);
2723 clear_join_marks(&mut op.right);
2724 }
2725 _ => {}
2726 }
2727}
2728
2729pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
2736 match expr {
2737 Expression::Select(mut select) => {
2738 if let Some(ref mut with) = select.with {
2739 if with.recursive {
2740 let mut counter = 0;
2741 for cte in &mut with.ctes {
2742 if cte.columns.is_empty() {
2743 if let Expression::Select(ref cte_select) = cte.this {
2745 let names: Vec<Identifier> = cte_select
2746 .expressions
2747 .iter()
2748 .map(|e| match e {
2749 Expression::Alias(a) => a.alias.clone(),
2750 Expression::Column(c) => c.name.clone(),
2751 _ => {
2752 counter += 1;
2753 Identifier::new(format!("_c_{}", counter))
2754 }
2755 })
2756 .collect();
2757 cte.columns = names;
2758 }
2759 }
2760 }
2761 }
2762 }
2763 Ok(Expression::Select(select))
2764 }
2765 other => Ok(other),
2766 }
2767}
2768
2769pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
2776 match expr {
2777 Expression::Cast(mut cast) => {
2778 if let Expression::Literal(ref lit) = cast.this {
2779 if let Literal::String(ref s) = lit.as_ref() {
2780 if s.to_lowercase() == "epoch" {
2781 if is_temporal_type(&cast.to) {
2782 cast.this = Expression::Literal(Box::new(Literal::String(
2783 "1970-01-01 00:00:00".to_string(),
2784 )));
2785 }
2786 }
2787 }
2788 }
2789 Ok(Expression::Cast(cast))
2790 }
2791 Expression::TryCast(mut try_cast) => {
2792 if let Expression::Literal(ref lit) = try_cast.this {
2793 if let Literal::String(ref s) = lit.as_ref() {
2794 if s.to_lowercase() == "epoch" {
2795 if is_temporal_type(&try_cast.to) {
2796 try_cast.this = Expression::Literal(Box::new(Literal::String(
2797 "1970-01-01 00:00:00".to_string(),
2798 )));
2799 }
2800 }
2801 }
2802 }
2803 Ok(Expression::TryCast(try_cast))
2804 }
2805 other => Ok(other),
2806 }
2807}
2808
2809fn is_temporal_type(dt: &DataType) -> bool {
2811 matches!(
2812 dt,
2813 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
2814 )
2815}
2816
2817pub fn ensure_bools(expr: Expression) -> Result<Expression> {
2842 let expr = ensure_bools_in_value_context(expr);
2843
2844 Ok(match expr {
2845 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => ensure_bool_condition(expr),
2847 other => other,
2848 })
2849}
2850
2851fn ensure_bools_in_value_context(expr: Expression) -> Expression {
2855 match expr {
2856 Expression::Case(mut case) => {
2857 let is_simple_case = case.operand.is_some();
2858 if let Some(operand) = case.operand.take() {
2859 case.operand = Some(ensure_bools_in_value_context(operand));
2860 }
2861 case.whens = case
2862 .whens
2863 .into_iter()
2864 .map(|(condition, result)| {
2865 let new_condition = if is_simple_case {
2866 ensure_bools_in_value_context(condition)
2867 } else {
2868 ensure_bool_condition(ensure_bools_in_value_context(condition))
2869 };
2870 let new_result = ensure_bools_in_value_context(result);
2871 (new_condition, new_result)
2872 })
2873 .collect();
2874 if let Some(else_expr) = case.else_ {
2875 case.else_ = Some(ensure_bools_in_value_context(else_expr));
2876 }
2877 Expression::Case(Box::new(*case))
2878 }
2879 Expression::Select(select) => Expression::Select(Box::new(ensure_bools_in_select(*select))),
2880 Expression::Subquery(mut subquery) => {
2881 subquery.this = ensure_bools_in_value_context(subquery.this);
2882 Expression::Subquery(subquery)
2883 }
2884 Expression::JoinedTable(mut joined_table) => {
2885 joined_table.left = ensure_bools_in_value_context(joined_table.left);
2886 joined_table.joins = joined_table
2887 .joins
2888 .into_iter()
2889 .map(ensure_bools_in_join)
2890 .collect();
2891 joined_table.lateral_views = joined_table
2892 .lateral_views
2893 .into_iter()
2894 .map(|mut lateral_view| {
2895 lateral_view.this = ensure_bools_in_value_context(lateral_view.this);
2896 lateral_view
2897 })
2898 .collect();
2899 Expression::JoinedTable(joined_table)
2900 }
2901 Expression::Union(mut union) => {
2902 let left = std::mem::replace(&mut union.left, Expression::null());
2903 let right = std::mem::replace(&mut union.right, Expression::null());
2904 union.left = ensure_bools_in_value_context(left);
2905 union.right = ensure_bools_in_value_context(right);
2906 if let Some(with) = union.with.take() {
2907 union.with = Some(ensure_bools_in_with(with));
2908 }
2909 Expression::Union(union)
2910 }
2911 Expression::Intersect(mut intersect) => {
2912 let left = std::mem::replace(&mut intersect.left, Expression::null());
2913 let right = std::mem::replace(&mut intersect.right, Expression::null());
2914 intersect.left = ensure_bools_in_value_context(left);
2915 intersect.right = ensure_bools_in_value_context(right);
2916 if let Some(with) = intersect.with.take() {
2917 intersect.with = Some(ensure_bools_in_with(with));
2918 }
2919 Expression::Intersect(intersect)
2920 }
2921 Expression::Except(mut except) => {
2922 let left = std::mem::replace(&mut except.left, Expression::null());
2923 let right = std::mem::replace(&mut except.right, Expression::null());
2924 except.left = ensure_bools_in_value_context(left);
2925 except.right = ensure_bools_in_value_context(right);
2926 if let Some(with) = except.with.take() {
2927 except.with = Some(ensure_bools_in_with(with));
2928 }
2929 Expression::Except(except)
2930 }
2931 Expression::Alias(mut alias) => {
2932 alias.this = ensure_bools_in_value_context(alias.this);
2933 Expression::Alias(alias)
2934 }
2935 Expression::Paren(mut paren) => {
2936 paren.this = ensure_bools_in_value_context(paren.this);
2937 Expression::Paren(paren)
2938 }
2939 other => other,
2940 }
2941}
2942
2943fn ensure_bools_in_select(mut select: Select) -> Select {
2944 select.expressions = select
2945 .expressions
2946 .into_iter()
2947 .map(ensure_bools_in_value_context)
2948 .collect();
2949
2950 if let Some(from) = select.from.take() {
2951 select.from = Some(crate::expressions::From {
2952 expressions: from
2953 .expressions
2954 .into_iter()
2955 .map(ensure_bools_in_value_context)
2956 .collect(),
2957 });
2958 }
2959
2960 select.joins = select.joins.into_iter().map(ensure_bools_in_join).collect();
2961
2962 if let Some(mut where_clause) = select.where_clause.take() {
2963 where_clause.this = ensure_bool_condition(ensure_bools_in_value_context(where_clause.this));
2964 select.where_clause = Some(where_clause);
2965 }
2966
2967 if let Some(mut having) = select.having.take() {
2968 having.this = ensure_bool_condition(ensure_bools_in_value_context(having.this));
2969 select.having = Some(having);
2970 }
2971
2972 if let Some(with) = select.with.take() {
2973 select.with = Some(ensure_bools_in_with(with));
2974 }
2975
2976 select
2977}
2978
2979fn ensure_bools_in_join(mut join: Join) -> Join {
2980 join.this = ensure_bools_in_value_context(join.this);
2981
2982 if let Some(on) = join.on.take() {
2983 join.on = Some(ensure_bool_condition(ensure_bools_in_value_context(on)));
2984 }
2985
2986 if let Some(match_condition) = join.match_condition.take() {
2987 join.match_condition = Some(ensure_bool_condition(ensure_bools_in_value_context(
2988 match_condition,
2989 )));
2990 }
2991
2992 join.pivots = join
2993 .pivots
2994 .into_iter()
2995 .map(ensure_bools_in_value_context)
2996 .collect();
2997
2998 join
2999}
3000
3001fn ensure_bools_in_with(mut with: With) -> With {
3002 with.ctes = with
3003 .ctes
3004 .into_iter()
3005 .map(|mut cte| {
3006 cte.this = ensure_bools_in_value_context(cte.this);
3007 cte
3008 })
3009 .collect();
3010 with
3011}
3012
3013fn is_boolean_expression(expr: &Expression) -> bool {
3016 matches!(
3017 expr,
3018 Expression::Eq(_)
3019 | Expression::Neq(_)
3020 | Expression::Lt(_)
3021 | Expression::Lte(_)
3022 | Expression::Gt(_)
3023 | Expression::Gte(_)
3024 | Expression::Is(_)
3025 | Expression::IsNull(_)
3026 | Expression::IsTrue(_)
3027 | Expression::IsFalse(_)
3028 | Expression::Like(_)
3029 | Expression::ILike(_)
3030 | Expression::StartsWith(_)
3031 | Expression::SimilarTo(_)
3032 | Expression::Glob(_)
3033 | Expression::RegexpLike(_)
3034 | Expression::In(_)
3035 | Expression::Between(_)
3036 | Expression::Exists(_)
3037 | Expression::And(_)
3038 | Expression::Or(_)
3039 | Expression::Not(_)
3040 | Expression::Any(_)
3041 | Expression::All(_)
3042 | Expression::NullSafeEq(_)
3043 | Expression::NullSafeNeq(_)
3044 | Expression::EqualNull(_)
3045 )
3046}
3047
3048fn wrap_neq_zero(expr: Expression) -> Expression {
3050 Expression::Neq(Box::new(BinaryOp {
3051 left: expr,
3052 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
3053 left_comments: vec![],
3054 operator_comments: vec![],
3055 trailing_comments: vec![],
3056 inferred_type: None,
3057 }))
3058}
3059
3060pub(crate) fn ensure_bool_condition(expr: Expression) -> Expression {
3066 match expr {
3067 Expression::And(op) => {
3069 let new_op = BinaryOp {
3070 left: ensure_bool_condition(op.left.clone()),
3071 right: ensure_bool_condition(op.right.clone()),
3072 left_comments: op.left_comments.clone(),
3073 operator_comments: op.operator_comments.clone(),
3074 trailing_comments: op.trailing_comments.clone(),
3075 inferred_type: None,
3076 };
3077 Expression::And(Box::new(new_op))
3078 }
3079 Expression::Or(op) => {
3080 let new_op = BinaryOp {
3081 left: ensure_bool_condition(op.left.clone()),
3082 right: ensure_bool_condition(op.right.clone()),
3083 left_comments: op.left_comments.clone(),
3084 operator_comments: op.operator_comments.clone(),
3085 trailing_comments: op.trailing_comments.clone(),
3086 inferred_type: None,
3087 };
3088 Expression::Or(Box::new(new_op))
3089 }
3090 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
3092 this: ensure_bool_condition(op.this.clone()),
3093 inferred_type: None,
3094 })),
3095 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
3097 this: ensure_bool_condition(paren.this.clone()),
3098 trailing_comments: paren.trailing_comments.clone(),
3099 })),
3100 Expression::Boolean(BooleanLiteral { value: true }) => {
3102 Expression::Paren(Box::new(crate::expressions::Paren {
3103 this: Expression::Eq(Box::new(BinaryOp {
3104 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3105 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3106 left_comments: vec![],
3107 operator_comments: vec![],
3108 trailing_comments: vec![],
3109 inferred_type: None,
3110 })),
3111 trailing_comments: vec![],
3112 }))
3113 }
3114 Expression::Boolean(BooleanLiteral { value: false }) => {
3115 Expression::Paren(Box::new(crate::expressions::Paren {
3116 this: Expression::Eq(Box::new(BinaryOp {
3117 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3118 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
3119 left_comments: vec![],
3120 operator_comments: vec![],
3121 trailing_comments: vec![],
3122 inferred_type: None,
3123 })),
3124 trailing_comments: vec![],
3125 }))
3126 }
3127 ref e if is_boolean_expression(e) => expr,
3129 _ => wrap_neq_zero(expr),
3132 }
3133}
3134
3135pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
3141 Ok(unqualify_columns_recursive(expr))
3142}
3143
3144fn unqualify_columns_recursive(expr: Expression) -> Expression {
3146 match expr {
3147 Expression::Column(mut col) => {
3148 col.table = None;
3149 Expression::Column(col)
3150 }
3151 Expression::Select(mut select) => {
3152 select.expressions = select
3153 .expressions
3154 .into_iter()
3155 .map(unqualify_columns_recursive)
3156 .collect();
3157 if let Some(ref mut where_clause) = select.where_clause {
3158 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
3159 }
3160 if let Some(ref mut having) = select.having {
3161 having.this = unqualify_columns_recursive(having.this.clone());
3162 }
3163 if let Some(ref mut group_by) = select.group_by {
3164 group_by.expressions = group_by
3165 .expressions
3166 .iter()
3167 .cloned()
3168 .map(unqualify_columns_recursive)
3169 .collect();
3170 }
3171 if let Some(ref mut order_by) = select.order_by {
3172 order_by.expressions = order_by
3173 .expressions
3174 .iter()
3175 .map(|o| crate::expressions::Ordered {
3176 nulls_auto: o.nulls_auto,
3177 this: unqualify_columns_recursive(o.this.clone()),
3178 desc: o.desc,
3179 nulls_first: o.nulls_first,
3180 explicit_asc: o.explicit_asc,
3181 with_fill: o.with_fill.clone(),
3182 })
3183 .collect();
3184 }
3185 for join in &mut select.joins {
3186 if let Some(ref mut on) = join.on {
3187 *on = unqualify_columns_recursive(on.clone());
3188 }
3189 }
3190 Expression::Select(select)
3191 }
3192 Expression::Alias(mut alias) => {
3193 alias.this = unqualify_columns_recursive(alias.this);
3194 Expression::Alias(alias)
3195 }
3196 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
3198 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
3199 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
3200 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
3201 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
3202 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
3203 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
3204 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
3205 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
3206 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
3207 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
3208 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
3209 Expression::Function(mut func) => {
3211 func.args = func
3212 .args
3213 .into_iter()
3214 .map(unqualify_columns_recursive)
3215 .collect();
3216 Expression::Function(func)
3217 }
3218 Expression::AggregateFunction(mut func) => {
3219 func.args = func
3220 .args
3221 .into_iter()
3222 .map(unqualify_columns_recursive)
3223 .collect();
3224 Expression::AggregateFunction(func)
3225 }
3226 Expression::Case(mut case) => {
3227 case.whens = case
3228 .whens
3229 .into_iter()
3230 .map(|(cond, result)| {
3231 (
3232 unqualify_columns_recursive(cond),
3233 unqualify_columns_recursive(result),
3234 )
3235 })
3236 .collect();
3237 if let Some(else_expr) = case.else_ {
3238 case.else_ = Some(unqualify_columns_recursive(else_expr));
3239 }
3240 Expression::Case(case)
3241 }
3242 other => other,
3244 }
3245}
3246
3247fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
3249 op.left = unqualify_columns_recursive(op.left);
3250 op.right = unqualify_columns_recursive(op.right);
3251 op
3252}
3253
3254pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
3274 match expr {
3275 Expression::Select(mut select) => {
3276 let mut cte_count = 0;
3277 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
3278
3279 if let Some(ref mut with) = select.with {
3281 for cte in &mut with.ctes {
3282 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
3283 }
3284 }
3285
3286 if let Some(ref mut from) = select.from {
3288 for table_expr in &mut from.expressions {
3289 if let Some((cte, replacement)) =
3290 try_convert_generate_date_array(table_expr, &mut cte_count)
3291 {
3292 new_ctes.push(cte);
3293 *table_expr = replacement;
3294 }
3295 }
3296 }
3297
3298 for join in &mut select.joins {
3300 if let Some((cte, replacement)) =
3301 try_convert_generate_date_array(&join.this, &mut cte_count)
3302 {
3303 new_ctes.push(cte);
3304 join.this = replacement;
3305 }
3306 }
3307
3308 if !new_ctes.is_empty() {
3310 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
3311 ctes: Vec::new(),
3312 recursive: true, leading_comments: vec![],
3314 search: None,
3315 });
3316 with_clause.recursive = true;
3317
3318 let mut all_ctes = new_ctes;
3320 all_ctes.append(&mut with_clause.ctes);
3321 with_clause.ctes = all_ctes;
3322 }
3323
3324 Ok(Expression::Select(select))
3325 }
3326 other => Ok(other),
3327 }
3328}
3329
3330fn process_expression_for_gda(
3333 expr: &mut Expression,
3334 cte_count: &mut usize,
3335 new_ctes: &mut Vec<crate::expressions::Cte>,
3336) {
3337 match expr {
3338 Expression::Select(ref mut select) => {
3339 if let Some(ref mut from) = select.from {
3341 for table_expr in &mut from.expressions {
3342 if let Some((cte, replacement)) =
3343 try_convert_generate_date_array(table_expr, cte_count)
3344 {
3345 new_ctes.push(cte);
3346 *table_expr = replacement;
3347 }
3348 }
3349 }
3350 for join in &mut select.joins {
3352 if let Some((cte, replacement)) =
3353 try_convert_generate_date_array(&join.this, cte_count)
3354 {
3355 new_ctes.push(cte);
3356 join.this = replacement;
3357 }
3358 }
3359 }
3360 Expression::Union(ref mut u) => {
3361 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
3362 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
3363 }
3364 Expression::Subquery(ref mut sq) => {
3365 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
3366 }
3367 _ => {}
3368 }
3369}
3370
3371fn try_convert_generate_date_array(
3374 expr: &Expression,
3375 cte_count: &mut usize,
3376) -> Option<(crate::expressions::Cte, Expression)> {
3377 try_convert_generate_date_array_with_name(expr, cte_count, None)
3378}
3379
3380fn try_convert_generate_date_array_with_name(
3381 expr: &Expression,
3382 cte_count: &mut usize,
3383 column_name_override: Option<&str>,
3384) -> Option<(crate::expressions::Cte, Expression)> {
3385 fn extract_gda_args(
3387 inner: &Expression,
3388 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
3389 match inner {
3390 Expression::GenerateDateArray(gda) => {
3391 let start = gda.start.as_ref()?;
3392 let end = gda.end.as_ref()?;
3393 let step = gda.step.as_deref();
3394 Some((start, end, step))
3395 }
3396 Expression::GenerateSeries(gs) => {
3397 let start = gs.start.as_deref()?;
3398 let end = gs.end.as_deref()?;
3399 let step = gs.step.as_deref();
3400 Some((start, end, step))
3401 }
3402 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
3403 if f.args.len() >= 2 {
3404 let start = &f.args[0];
3405 let end = &f.args[1];
3406 let step = f.args.get(2);
3407 Some((start, end, step))
3408 } else {
3409 None
3410 }
3411 }
3412 _ => None,
3413 }
3414 }
3415
3416 if let Expression::Unnest(unnest) = expr {
3418 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
3419 let start = start;
3420 let end = end;
3421 let step: Option<&Expression> = step_opt;
3422
3423 let cte_name = if *cte_count == 0 {
3425 "_generated_dates".to_string()
3426 } else {
3427 format!("_generated_dates_{}", cte_count)
3428 };
3429 *cte_count += 1;
3430
3431 let column_name =
3432 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
3433
3434 let cast_to_date = |expr: &Expression| -> Expression {
3436 match expr {
3437 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
3438 if let Expression::Literal(lit) = expr {
3440 if let Literal::Date(d) = lit.as_ref() {
3441 Expression::Cast(Box::new(Cast {
3442 this: Expression::Literal(Box::new(Literal::String(d.clone()))),
3443 to: DataType::Date,
3444 trailing_comments: vec![],
3445 double_colon_syntax: false,
3446 format: None,
3447 default: None,
3448 inferred_type: None,
3449 }))
3450 } else {
3451 expr.clone()
3452 }
3453 } else {
3454 unreachable!()
3455 }
3456 }
3457 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
3458 _ => Expression::Cast(Box::new(Cast {
3459 this: expr.clone(),
3460 to: DataType::Date,
3461 trailing_comments: vec![],
3462 double_colon_syntax: false,
3463 format: None,
3464 default: None,
3465 inferred_type: None,
3466 })),
3467 }
3468 };
3469
3470 let base_select = Select {
3472 vertica: None,
3473 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
3474 this: cast_to_date(start),
3475 alias: column_name.clone(),
3476 column_aliases: vec![],
3477 alias_explicit_as: false,
3478 alias_keyword: None,
3479 pre_alias_comments: vec![],
3480 trailing_comments: vec![],
3481 inferred_type: None,
3482 }))],
3483 ..Select::new()
3484 };
3485
3486 let normalize_interval = |expr: &Expression| -> Expression {
3488 if let Expression::Interval(ref iv) = expr {
3489 let mut iv_clone = iv.as_ref().clone();
3490 if let Some(Expression::Literal(ref lit)) = iv_clone.this {
3491 if let Literal::String(ref s) = lit.as_ref() {
3492 if s.parse::<f64>().is_ok() {
3494 iv_clone.this =
3495 Some(Expression::Literal(Box::new(Literal::Number(s.clone()))));
3496 }
3497 }
3498 }
3499 Expression::Interval(Box::new(iv_clone))
3500 } else {
3501 expr.clone()
3502 }
3503 };
3504
3505 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
3508 Expression::Interval(Box::new(crate::expressions::Interval {
3509 this: Some(Expression::Literal(Box::new(Literal::Number(
3510 "1".to_string(),
3511 )))),
3512 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
3513 unit: crate::expressions::IntervalUnit::Day,
3514 use_plural: false,
3515 }),
3516 }))
3517 });
3518
3519 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
3521
3522 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
3523 this: Expression::Column(Box::new(crate::expressions::Column {
3524 name: column_name.clone(),
3525 table: None,
3526 join_mark: false,
3527 trailing_comments: vec![],
3528 span: None,
3529 inferred_type: None,
3530 })),
3531 interval: add_count,
3532 unit: add_unit,
3533 }));
3534
3535 let cast_date_add = Expression::Cast(Box::new(Cast {
3536 this: date_add_expr.clone(),
3537 to: DataType::Date,
3538 trailing_comments: vec![],
3539 double_colon_syntax: false,
3540 format: None,
3541 default: None,
3542 inferred_type: None,
3543 }));
3544
3545 let recursive_select = Select {
3546 vertica: None,
3547 expressions: vec![cast_date_add.clone()],
3548 from: Some(From {
3549 expressions: vec![Expression::Table(Box::new(
3550 crate::expressions::TableRef::new(&cte_name),
3551 ))],
3552 }),
3553 where_clause: Some(Where {
3554 this: Expression::Lte(Box::new(BinaryOp {
3555 left: cast_date_add,
3556 right: cast_to_date(end),
3557 left_comments: vec![],
3558 operator_comments: vec![],
3559 trailing_comments: vec![],
3560 inferred_type: None,
3561 })),
3562 }),
3563 ..Select::new()
3564 };
3565
3566 let union = crate::expressions::Union {
3568 left: Expression::Select(Box::new(base_select)),
3569 right: Expression::Select(Box::new(recursive_select)),
3570 all: true, distinct: false,
3572 with: None,
3573 order_by: None,
3574 limit: None,
3575 offset: None,
3576 distribute_by: None,
3577 sort_by: None,
3578 cluster_by: None,
3579 by_name: false,
3580 side: None,
3581 kind: None,
3582 corresponding: false,
3583 strict: false,
3584 on_columns: Vec::new(),
3585 };
3586
3587 let cte = crate::expressions::Cte {
3589 this: Expression::Union(Box::new(union)),
3590 alias: Identifier::new(cte_name.clone()),
3591 columns: vec![column_name.clone()],
3592 materialized: None,
3593 key_expressions: Vec::new(),
3594 alias_first: true,
3595 comments: Vec::new(),
3596 };
3597
3598 let replacement_select = Select {
3600 vertica: None,
3601 expressions: vec![Expression::Column(Box::new(crate::expressions::Column {
3602 name: column_name,
3603 table: None,
3604 join_mark: false,
3605 trailing_comments: vec![],
3606 span: None,
3607 inferred_type: None,
3608 }))],
3609 from: Some(From {
3610 expressions: vec![Expression::Table(Box::new(
3611 crate::expressions::TableRef::new(&cte_name),
3612 ))],
3613 }),
3614 ..Select::new()
3615 };
3616
3617 let replacement = Expression::Subquery(Box::new(Subquery {
3618 this: Expression::Select(Box::new(replacement_select)),
3619 alias: Some(Identifier::new(cte_name)),
3620 column_aliases: vec![],
3621 alias_explicit_as: false,
3622 alias_keyword: None,
3623 order_by: None,
3624 limit: None,
3625 offset: None,
3626 distribute_by: None,
3627 sort_by: None,
3628 cluster_by: None,
3629 lateral: false,
3630 modifiers_inside: false,
3631 trailing_comments: vec![],
3632 inferred_type: None,
3633 }));
3634
3635 return Some((cte, replacement));
3636 }
3637 }
3638
3639 if let Expression::Alias(alias) = expr {
3641 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
3643 if let Some((cte, replacement)) =
3644 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
3645 {
3646 if col_name.is_some() {
3649 return Some((cte, replacement));
3650 }
3651 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
3652 this: replacement,
3653 alias: alias.alias.clone(),
3654 column_aliases: alias.column_aliases.clone(),
3655 alias_explicit_as: false,
3656 alias_keyword: None,
3657 pre_alias_comments: alias.pre_alias_comments.clone(),
3658 trailing_comments: alias.trailing_comments.clone(),
3659 inferred_type: None,
3660 }));
3661 return Some((cte, new_alias));
3662 }
3663 }
3664
3665 None
3666}
3667
3668fn extract_interval_unit_and_count(
3673 expr: &Expression,
3674) -> (crate::expressions::IntervalUnit, Expression) {
3675 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
3676
3677 if let Expression::Interval(ref iv) = expr {
3678 if let Some(ref unit_spec) = iv.unit {
3680 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
3681 let count = match &iv.this {
3682 Some(e) => e.clone(),
3683 None => Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3684 };
3685 return (unit.clone(), count);
3686 }
3687 }
3688
3689 if let Some(ref val_expr) = iv.this {
3691 match val_expr {
3692 Expression::Literal(lit)
3693 if matches!(lit.as_ref(), Literal::String(_) | Literal::Number(_)) =>
3694 {
3695 let s = match lit.as_ref() {
3696 Literal::String(s) | Literal::Number(s) => s,
3697 _ => unreachable!(),
3698 };
3699 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
3701 if parts.len() == 2 {
3702 let count_str = parts[0].trim();
3703 let unit_str = parts[1].trim().to_uppercase();
3704 let unit = match unit_str.as_str() {
3705 "YEAR" | "YEARS" => IntervalUnit::Year,
3706 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
3707 "MONTH" | "MONTHS" => IntervalUnit::Month,
3708 "WEEK" | "WEEKS" => IntervalUnit::Week,
3709 "DAY" | "DAYS" => IntervalUnit::Day,
3710 "HOUR" | "HOURS" => IntervalUnit::Hour,
3711 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
3712 "SECOND" | "SECONDS" => IntervalUnit::Second,
3713 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
3714 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
3715 _ => IntervalUnit::Day,
3716 };
3717 return (
3718 unit,
3719 Expression::Literal(Box::new(Literal::Number(count_str.to_string()))),
3720 );
3721 }
3722 if s.parse::<f64>().is_ok() {
3724 return (
3725 IntervalUnit::Day,
3726 Expression::Literal(Box::new(Literal::Number(s.clone()))),
3727 );
3728 }
3729 }
3730 _ => {}
3731 }
3732 }
3733
3734 (
3736 IntervalUnit::Day,
3737 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3738 )
3739 } else {
3740 (
3741 IntervalUnit::Day,
3742 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3743 )
3744 }
3745}
3746
3747pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
3760 match expr {
3761 Expression::ILike(ilike) => {
3762 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
3764 on_error: None,
3765 qualified_name: Vec::new(),
3766 source_dialect: None,
3767
3768 name: "LOWER".to_string(),
3769 args: vec![ilike.left],
3770 distinct: false,
3771 trailing_comments: vec![],
3772 use_bracket_syntax: false,
3773 no_parens: false,
3774 quoted: false,
3775 span: None,
3776 inferred_type: None,
3777 }));
3778
3779 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
3780 on_error: None,
3781 qualified_name: Vec::new(),
3782 source_dialect: None,
3783
3784 name: "LOWER".to_string(),
3785 args: vec![ilike.right],
3786 distinct: false,
3787 trailing_comments: vec![],
3788 use_bracket_syntax: false,
3789 no_parens: false,
3790 quoted: false,
3791 span: None,
3792 inferred_type: None,
3793 }));
3794
3795 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
3796 left: lower_left,
3797 right: lower_right,
3798 escape: ilike.escape,
3799 quantifier: ilike.quantifier,
3800 inferred_type: None,
3801 })))
3802 }
3803 other => Ok(other),
3804 }
3805}
3806
3807pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
3815 match expr {
3816 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
3817 other => Ok(other),
3818 }
3819}
3820
3821pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
3826 match expr {
3827 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
3828 other => Ok(other),
3829 }
3830}
3831
3832pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
3839 Ok(expr)
3841}
3842
3843pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
3857 match expr {
3860 Expression::Table(ref table) => {
3861 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
3864 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3866 this: expr.clone(),
3867 expressions: Vec::new(),
3868 with_ordinality: false,
3869 alias: None,
3870 offset_alias: None,
3871 inferred_type: None,
3872 }));
3873
3874 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
3876 this: unnest,
3877 alias: Identifier::new("_u".to_string()),
3878 column_aliases: vec![],
3879 alias_explicit_as: false,
3880 alias_keyword: None,
3881 pre_alias_comments: vec![],
3882 trailing_comments: vec![],
3883 inferred_type: None,
3884 })));
3885 }
3886 Ok(expr)
3887 }
3888 Expression::GenerateSeries(gs) => {
3889 let unnest = Expression::Unnest(Box::new(UnnestFunc {
3891 this: Expression::GenerateSeries(gs),
3892 expressions: Vec::new(),
3893 with_ordinality: false,
3894 alias: None,
3895 offset_alias: None,
3896 inferred_type: None,
3897 }));
3898 Ok(unnest)
3899 }
3900 other => Ok(other),
3901 }
3902}
3903
3904pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
3915 use crate::dialects::transform_recursive;
3916 transform_recursive(expr, &unwrap_unnest_generate_series_single)
3917}
3918
3919fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
3920 use crate::expressions::*;
3921 match expr {
3923 Expression::Select(mut select) => {
3924 if let Some(ref mut from) = select.from {
3926 for table_expr in &mut from.expressions {
3927 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
3928 *table_expr = replacement;
3929 }
3930 }
3931 }
3932 for join in &mut select.joins {
3934 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
3935 join.this = replacement;
3936 }
3937 }
3938 Ok(Expression::Select(select))
3939 }
3940 other => Ok(other),
3941 }
3942}
3943
3944fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
3947 use crate::expressions::*;
3948
3949 let gen_series = match expr {
3951 Expression::Unnest(unnest) => {
3952 if let Expression::GenerateSeries(ref gs) = unnest.this {
3953 Some(gs.as_ref().clone())
3954 } else {
3955 None
3956 }
3957 }
3958 Expression::Alias(alias) => {
3959 if let Expression::Unnest(ref unnest) = alias.this {
3960 if let Expression::GenerateSeries(ref gs) = unnest.this {
3961 Some(gs.as_ref().clone())
3962 } else {
3963 None
3964 }
3965 } else {
3966 None
3967 }
3968 }
3969 _ => None,
3970 };
3971
3972 let gs = gen_series?;
3973
3974 let value_col = Expression::boxed_column(Column {
3976 name: Identifier::new("value".to_string()),
3977 table: None,
3978 join_mark: false,
3979 trailing_comments: vec![],
3980 span: None,
3981 inferred_type: None,
3982 });
3983
3984 let cast_value = Expression::Cast(Box::new(Cast {
3985 this: value_col,
3986 to: DataType::Date,
3987 trailing_comments: vec![],
3988 double_colon_syntax: false,
3989 format: None,
3990 default: None,
3991 inferred_type: None,
3992 }));
3993
3994 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
3995
3996 let gen_series_aliased = Expression::Alias(Box::new(Alias {
3998 this: gen_series_expr,
3999 alias: Identifier::new("_t".to_string()),
4000 column_aliases: vec![Identifier::new("value".to_string())],
4001 alias_explicit_as: false,
4002 alias_keyword: None,
4003 pre_alias_comments: vec![],
4004 trailing_comments: vec![],
4005 inferred_type: None,
4006 }));
4007
4008 let mut inner_select = Select::new();
4009 inner_select.expressions = vec![cast_value];
4010 inner_select.from = Some(From {
4011 expressions: vec![gen_series_aliased],
4012 });
4013
4014 let inner_select_expr = Expression::Select(Box::new(inner_select));
4015
4016 let subquery = Expression::Subquery(Box::new(Subquery {
4017 this: inner_select_expr,
4018 alias: None,
4019 column_aliases: vec![],
4020 alias_explicit_as: false,
4021 alias_keyword: None,
4022 order_by: None,
4023 limit: None,
4024 offset: None,
4025 distribute_by: None,
4026 sort_by: None,
4027 cluster_by: None,
4028 lateral: false,
4029 modifiers_inside: false,
4030 trailing_comments: vec![],
4031 inferred_type: None,
4032 }));
4033
4034 Some(Expression::Alias(Box::new(Alias {
4036 this: subquery,
4037 alias: Identifier::new("_unnested_generate_series".to_string()),
4038 column_aliases: vec![],
4039 alias_explicit_as: false,
4040 alias_keyword: None,
4041 pre_alias_comments: vec![],
4042 trailing_comments: vec![],
4043 inferred_type: None,
4044 })))
4045}
4046
4047pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
4055 match expr {
4056 Expression::Delete(mut delete) => {
4057 if let Some(ref mut where_clause) = delete.where_clause {
4059 where_clause.this = expand_between_recursive(where_clause.this.clone());
4060 }
4061 Ok(Expression::Delete(delete))
4062 }
4063 other => Ok(other),
4064 }
4065}
4066
4067fn expand_between_recursive(expr: Expression) -> Expression {
4069 match expr {
4070 Expression::Between(between) => {
4073 let this = expand_between_recursive(between.this.clone());
4074 let low = expand_between_recursive(between.low);
4075 let high = expand_between_recursive(between.high);
4076
4077 if between.not {
4078 Expression::Or(Box::new(BinaryOp::new(
4080 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
4081 Expression::Gt(Box::new(BinaryOp::new(this, high))),
4082 )))
4083 } else {
4084 Expression::And(Box::new(BinaryOp::new(
4086 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
4087 Expression::Lte(Box::new(BinaryOp::new(this, high))),
4088 )))
4089 }
4090 }
4091
4092 Expression::And(mut op) => {
4094 op.left = expand_between_recursive(op.left);
4095 op.right = expand_between_recursive(op.right);
4096 Expression::And(op)
4097 }
4098 Expression::Or(mut op) => {
4099 op.left = expand_between_recursive(op.left);
4100 op.right = expand_between_recursive(op.right);
4101 Expression::Or(op)
4102 }
4103 Expression::Not(mut op) => {
4104 op.this = expand_between_recursive(op.this);
4105 Expression::Not(op)
4106 }
4107
4108 Expression::Paren(mut paren) => {
4110 paren.this = expand_between_recursive(paren.this);
4111 Expression::Paren(paren)
4112 }
4113
4114 other => other,
4116 }
4117}
4118
4119pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
4128 match expr {
4129 Expression::Select(mut select) => {
4130 if let Some(ref mut with) = select.with {
4131 for cte in &mut with.ctes {
4132 if !cte.columns.is_empty() {
4133 let is_star = matches!(&cte.this, Expression::Select(s) if
4135 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
4136
4137 if is_star {
4138 cte.columns.clear();
4140 continue;
4141 }
4142
4143 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
4145
4146 if let Expression::Select(ref mut inner_select) = cte.this {
4148 let new_exprs: Vec<Expression> = inner_select
4149 .expressions
4150 .drain(..)
4151 .zip(
4152 column_names
4153 .into_iter()
4154 .chain(std::iter::repeat_with(|| Identifier::new(""))),
4155 )
4156 .map(|(expr, col_name)| {
4157 if col_name.name.is_empty() {
4158 return expr;
4159 }
4160 match expr {
4162 Expression::Alias(mut a) => {
4163 a.alias = col_name;
4164 Expression::Alias(a)
4165 }
4166 other => {
4167 Expression::Alias(Box::new(crate::expressions::Alias {
4168 this: other,
4169 alias: col_name,
4170 column_aliases: Vec::new(),
4171 alias_explicit_as: false,
4172 alias_keyword: None,
4173 pre_alias_comments: Vec::new(),
4174 trailing_comments: Vec::new(),
4175 inferred_type: None,
4176 }))
4177 }
4178 }
4179 })
4180 .collect();
4181 inner_select.expressions = new_exprs;
4182 }
4183 }
4184 }
4185 }
4186 Ok(Expression::Select(select))
4187 }
4188 other => Ok(other),
4189 }
4190}
4191
4192pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
4196 match expr {
4197 Expression::Select(mut select) => {
4198 if let Some(ref mut from) = select.from {
4199 for from_item in from.expressions.iter_mut() {
4200 simplify_paren_values_in_from(from_item);
4201 }
4202 }
4203 Ok(Expression::Select(select))
4204 }
4205 other => Ok(other),
4206 }
4207}
4208
4209fn simplify_paren_values_in_from(expr: &mut Expression) {
4210 let replacement = match expr {
4212 Expression::Subquery(ref subquery) => {
4214 if let Expression::Paren(ref paren) = subquery.this {
4215 if matches!(&paren.this, Expression::Values(_)) {
4216 let mut new_sub = subquery.as_ref().clone();
4217 new_sub.this = paren.this.clone();
4218 Some(Expression::Subquery(Box::new(new_sub)))
4219 } else {
4220 None
4221 }
4222 } else {
4223 None
4224 }
4225 }
4226 Expression::Paren(ref outer_paren) => {
4229 if let Expression::Subquery(ref subquery) = outer_paren.this {
4230 if matches!(&subquery.this, Expression::Values(_)) {
4232 Some(outer_paren.this.clone())
4233 }
4234 else if let Expression::Paren(ref paren) = subquery.this {
4236 if matches!(&paren.this, Expression::Values(_)) {
4237 let mut new_sub = subquery.as_ref().clone();
4238 new_sub.this = paren.this.clone();
4239 Some(Expression::Subquery(Box::new(new_sub)))
4240 } else {
4241 None
4242 }
4243 } else {
4244 None
4245 }
4246 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
4247 if matches!(&inner_paren.this, Expression::Values(_)) {
4248 Some(outer_paren.this.clone())
4249 } else {
4250 None
4251 }
4252 } else {
4253 None
4254 }
4255 }
4256 _ => None,
4257 };
4258 if let Some(new_expr) = replacement {
4259 *expr = new_expr;
4260 }
4261}
4262
4263pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
4267 match expr {
4268 Expression::Select(mut select) => {
4269 if let Some(ref mut from) = select.from {
4271 let mut counter = 0usize;
4272 for from_item in from.expressions.iter_mut() {
4273 add_auto_alias_to_from_item(from_item, &mut counter);
4274 }
4275 }
4276 Ok(Expression::Select(select))
4277 }
4278 other => Ok(other),
4279 }
4280}
4281
4282fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
4283 use crate::expressions::Identifier;
4284
4285 match expr {
4286 Expression::Alias(ref mut alias) => {
4287 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
4289 alias.alias = Identifier::new(format!("_t{}", counter));
4290 *counter += 1;
4291 }
4292 }
4293 _ => {}
4294 }
4295}
4296
4297pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
4307 use crate::dialects::transform_recursive;
4308 transform_recursive(expr, &propagate_struct_names_in_expr)
4309}
4310
4311fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
4312 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
4313
4314 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
4316 if elements.len() <= 1 {
4317 return None;
4318 }
4319 if let Some(Expression::Function(ref first_struct)) = elements.first() {
4321 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
4322 let field_names: Vec<Option<String>> = first_struct
4324 .args
4325 .iter()
4326 .map(|arg| {
4327 if let Expression::Alias(a) = arg {
4328 Some(a.alias.name.clone())
4329 } else {
4330 None
4331 }
4332 })
4333 .collect();
4334
4335 if field_names.iter().any(|n| n.is_some()) {
4337 let mut new_elements = Vec::with_capacity(elements.len());
4338 new_elements.push(elements[0].clone());
4339
4340 for elem in &elements[1..] {
4341 if let Expression::Function(ref s) = elem {
4342 if s.name.eq_ignore_ascii_case("STRUCT")
4343 && s.args.len() == field_names.len()
4344 {
4345 let all_unnamed =
4347 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
4348 if all_unnamed {
4349 let new_args: Vec<Expression> = s
4351 .args
4352 .iter()
4353 .zip(field_names.iter())
4354 .map(|(val, name)| {
4355 if let Some(n) = name {
4356 Expression::Alias(Box::new(Alias::new(
4357 val.clone(),
4358 Identifier::new(n.clone()),
4359 )))
4360 } else {
4361 val.clone()
4362 }
4363 })
4364 .collect();
4365 new_elements.push(Expression::Function(Box::new(
4366 Function::new("STRUCT".to_string(), new_args),
4367 )));
4368 continue;
4369 }
4370 }
4371 }
4372 new_elements.push(elem.clone());
4373 }
4374
4375 return Some(new_elements);
4376 }
4377 }
4378 }
4379 None
4380 }
4381
4382 if let Expression::Array(ref arr) = expr {
4384 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
4385 return Ok(Expression::Array(Box::new(crate::expressions::Array {
4386 expressions: new_elements,
4387 inferred_type: arr.inferred_type.clone(),
4388 })));
4389 }
4390 }
4391
4392 if let Expression::ArrayFunc(ref arr) = expr {
4394 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
4395 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
4396 expressions: new_elements,
4397 bracket_notation: arr.bracket_notation,
4398 use_list_keyword: arr.use_list_keyword,
4399 inferred_type: arr.inferred_type.clone(),
4400 })));
4401 }
4402 }
4403
4404 Ok(expr)
4405}
4406
4407pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
4410 use crate::dialects::transform_recursive;
4411 transform_recursive(expr, &unnest_alias_transform_single_select)
4412}
4413
4414pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
4417 use crate::dialects::transform_recursive;
4418 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
4419}
4420
4421fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
4422 if let Expression::Select(mut select) = expr {
4423 if let Some(ref mut from) = select.from {
4424 if from.expressions.len() > 1 {
4425 let mut new_from_exprs = Vec::new();
4426 let mut new_cross_joins = Vec::new();
4427
4428 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4429 if idx == 0 {
4430 new_from_exprs.push(from_item);
4431 } else {
4432 let is_unnest = match &from_item {
4433 Expression::Unnest(_) => true,
4434 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4435 _ => false,
4436 };
4437
4438 if is_unnest {
4439 new_cross_joins.push(crate::expressions::Join {
4440 this: from_item,
4441 on: None,
4442 using: Vec::new(),
4443 kind: JoinKind::Cross,
4444 use_inner_keyword: false,
4445 use_outer_keyword: false,
4446 deferred_condition: false,
4447 join_hint: None,
4448 match_condition: None,
4449 pivots: Vec::new(),
4450 comments: Vec::new(),
4451 nesting_group: 0,
4452 directed: false,
4453 });
4454 } else {
4455 new_from_exprs.push(from_item);
4456 }
4457 }
4458 }
4459
4460 from.expressions = new_from_exprs;
4461 new_cross_joins.append(&mut select.joins);
4462 select.joins = new_cross_joins;
4463 }
4464 }
4465
4466 Ok(Expression::Select(select))
4467 } else {
4468 Ok(expr)
4469 }
4470}
4471
4472pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
4476 use crate::dialects::transform_recursive;
4477 transform_recursive(expr, &wrap_unnest_join_aliases_single)
4478}
4479
4480fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
4481 if let Expression::Select(mut select) = expr {
4482 for join in &mut select.joins {
4484 wrap_unnest_alias_in_join_item(&mut join.this);
4485 }
4486 Ok(Expression::Select(select))
4487 } else {
4488 Ok(expr)
4489 }
4490}
4491
4492fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
4494 use crate::expressions::Identifier;
4495 if let Expression::Alias(alias) = expr {
4496 let is_unnest = match &alias.this {
4498 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
4499 _ => false,
4500 };
4501
4502 if is_unnest && alias.column_aliases.is_empty() {
4503 let original_alias_name = alias.alias.name.clone();
4505 alias.alias = Identifier {
4506 name: "_u".to_string(),
4507 quoted: false,
4508 trailing_comments: Vec::new(),
4509 span: None,
4510 };
4511 alias.column_aliases = vec![Identifier {
4512 name: original_alias_name,
4513 quoted: false,
4514 trailing_comments: Vec::new(),
4515 span: None,
4516 }];
4517 }
4518 }
4519}
4520
4521fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
4522 if let Expression::Select(mut select) = expr {
4523 let mut counter = 0usize;
4524
4525 if let Some(ref mut from) = select.from {
4527 for from_item in from.expressions.iter_mut() {
4529 convert_unnest_alias_in_from(from_item, &mut counter);
4530 }
4531
4532 if from.expressions.len() > 1 {
4534 let mut new_from_exprs = Vec::new();
4535 let mut new_cross_joins = Vec::new();
4536
4537 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4538 if idx == 0 {
4539 new_from_exprs.push(from_item);
4541 } else {
4542 let is_unnest = match &from_item {
4544 Expression::Unnest(_) => true,
4545 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4546 _ => false,
4547 };
4548
4549 if is_unnest {
4550 new_cross_joins.push(crate::expressions::Join {
4552 this: from_item,
4553 on: None,
4554 using: Vec::new(),
4555 kind: JoinKind::Cross,
4556 use_inner_keyword: false,
4557 use_outer_keyword: false,
4558 deferred_condition: false,
4559 join_hint: None,
4560 match_condition: None,
4561 pivots: Vec::new(),
4562 comments: Vec::new(),
4563 nesting_group: 0,
4564 directed: false,
4565 });
4566 } else {
4567 new_from_exprs.push(from_item);
4569 }
4570 }
4571 }
4572
4573 from.expressions = new_from_exprs;
4574 new_cross_joins.append(&mut select.joins);
4576 select.joins = new_cross_joins;
4577 }
4578 }
4579
4580 for join in select.joins.iter_mut() {
4582 convert_unnest_alias_in_from(&mut join.this, &mut counter);
4583 }
4584
4585 Ok(Expression::Select(select))
4586 } else {
4587 Ok(expr)
4588 }
4589}
4590
4591fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
4592 use crate::expressions::Identifier;
4593
4594 if let Expression::Alias(ref mut alias) = expr {
4595 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
4597 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
4598
4599 if is_unnest && alias.column_aliases.is_empty() {
4600 let col_alias = alias.alias.clone();
4602 alias.column_aliases = vec![col_alias];
4603 alias.alias = Identifier::new(format!("_t{}", counter));
4604 *counter += 1;
4605 }
4606 }
4607}
4608
4609pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
4616 use crate::expressions::{Alias, Function};
4617
4618 match expr {
4619 Expression::Select(mut select) => {
4620 let mut new_expressions = Vec::new();
4622 let mut changed = false;
4623
4624 for sel_expr in select.expressions.drain(..) {
4625 if let Expression::Alias(ref alias_box) = sel_expr {
4627 if let Expression::Function(ref func) = alias_box.this {
4628 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4629 let arg = func.args[0].clone();
4630 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4632 (
4633 alias_box.column_aliases[0].name.clone(),
4634 alias_box.column_aliases[1].name.clone(),
4635 )
4636 } else if !alias_box.alias.is_empty() {
4637 ("pos".to_string(), alias_box.alias.name.clone())
4639 } else {
4640 ("pos".to_string(), "col".to_string())
4641 };
4642
4643 let gen_subscripts = Expression::Function(Box::new(Function::new(
4645 "GENERATE_SUBSCRIPTS".to_string(),
4646 vec![
4647 arg.clone(),
4648 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4649 ],
4650 )));
4651 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4652 gen_subscripts,
4653 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4654 )));
4655 let pos_alias = Expression::Alias(Box::new(Alias {
4656 this: sub_one,
4657 alias: Identifier::new(pos_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 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4668 this: arg,
4669 expressions: Vec::new(),
4670 with_ordinality: false,
4671 alias: None,
4672 offset_alias: None,
4673 inferred_type: None,
4674 }));
4675 let col_alias = Expression::Alias(Box::new(Alias {
4676 this: unnest,
4677 alias: Identifier::new(col_name),
4678 column_aliases: Vec::new(),
4679 alias_explicit_as: false,
4680 alias_keyword: None,
4681 pre_alias_comments: Vec::new(),
4682 trailing_comments: Vec::new(),
4683 inferred_type: None,
4684 }));
4685
4686 new_expressions.push(pos_alias);
4687 new_expressions.push(col_alias);
4688 changed = true;
4689 continue;
4690 }
4691 }
4692 }
4693
4694 if let Expression::Function(ref func) = sel_expr {
4696 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4697 let arg = func.args[0].clone();
4698 let pos_name = "pos";
4699 let col_name = "col";
4700
4701 let gen_subscripts = Expression::Function(Box::new(Function::new(
4703 "GENERATE_SUBSCRIPTS".to_string(),
4704 vec![
4705 arg.clone(),
4706 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4707 ],
4708 )));
4709 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4710 gen_subscripts,
4711 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4712 )));
4713 let pos_alias = Expression::Alias(Box::new(Alias {
4714 this: sub_one,
4715 alias: Identifier::new(pos_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 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4726 this: arg,
4727 expressions: Vec::new(),
4728 with_ordinality: false,
4729 alias: None,
4730 offset_alias: None,
4731 inferred_type: None,
4732 }));
4733 let col_alias = Expression::Alias(Box::new(Alias {
4734 this: unnest,
4735 alias: Identifier::new(col_name),
4736 column_aliases: Vec::new(),
4737 alias_explicit_as: false,
4738 alias_keyword: None,
4739 pre_alias_comments: Vec::new(),
4740 trailing_comments: Vec::new(),
4741 inferred_type: None,
4742 }));
4743
4744 new_expressions.push(pos_alias);
4745 new_expressions.push(col_alias);
4746 changed = true;
4747 continue;
4748 }
4749 }
4750
4751 new_expressions.push(sel_expr);
4753 }
4754
4755 if changed {
4756 select.expressions = new_expressions;
4757 } else {
4758 select.expressions = new_expressions;
4759 }
4760
4761 if let Some(ref mut from) = select.from {
4764 expand_posexplode_in_from_duckdb(from)?;
4765 }
4766
4767 Ok(Expression::Select(select))
4768 }
4769 other => Ok(other),
4770 }
4771}
4772
4773fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
4775 use crate::expressions::{Alias, Function};
4776
4777 let mut new_expressions = Vec::new();
4778 let mut _changed = false;
4779
4780 for table_expr in from.expressions.drain(..) {
4781 if let Expression::Alias(ref alias_box) = table_expr {
4783 if let Expression::Function(ref func) = alias_box.this {
4784 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4785 let arg = func.args[0].clone();
4786 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4787 (
4788 alias_box.column_aliases[0].name.clone(),
4789 alias_box.column_aliases[1].name.clone(),
4790 )
4791 } else {
4792 ("pos".to_string(), "col".to_string())
4793 };
4794
4795 let gen_subscripts = Expression::Function(Box::new(Function::new(
4797 "GENERATE_SUBSCRIPTS".to_string(),
4798 vec![
4799 arg.clone(),
4800 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4801 ],
4802 )));
4803 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4804 gen_subscripts,
4805 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4806 )));
4807 let pos_alias = Expression::Alias(Box::new(Alias {
4808 this: sub_one,
4809 alias: Identifier::new(&pos_name),
4810 column_aliases: Vec::new(),
4811 alias_explicit_as: false,
4812 alias_keyword: None,
4813 pre_alias_comments: Vec::new(),
4814 trailing_comments: Vec::new(),
4815 inferred_type: None,
4816 }));
4817 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4818 this: arg,
4819 expressions: Vec::new(),
4820 with_ordinality: false,
4821 alias: None,
4822 offset_alias: None,
4823 inferred_type: None,
4824 }));
4825 let col_alias = Expression::Alias(Box::new(Alias {
4826 this: unnest,
4827 alias: Identifier::new(&col_name),
4828 column_aliases: Vec::new(),
4829 alias_explicit_as: false,
4830 alias_keyword: None,
4831 pre_alias_comments: Vec::new(),
4832 trailing_comments: Vec::new(),
4833 inferred_type: None,
4834 }));
4835
4836 let mut inner_select = Select::new();
4837 inner_select.expressions = vec![pos_alias, col_alias];
4838
4839 let subquery = Expression::Subquery(Box::new(Subquery {
4840 this: Expression::Select(Box::new(inner_select)),
4841 alias: None,
4842 column_aliases: Vec::new(),
4843 alias_explicit_as: false,
4844 alias_keyword: None,
4845 order_by: None,
4846 limit: None,
4847 offset: None,
4848 distribute_by: None,
4849 sort_by: None,
4850 cluster_by: None,
4851 lateral: false,
4852 modifiers_inside: false,
4853 trailing_comments: Vec::new(),
4854 inferred_type: None,
4855 }));
4856 new_expressions.push(subquery);
4857 _changed = true;
4858 continue;
4859 }
4860 }
4861 }
4862
4863 if let Expression::Function(ref func) = table_expr {
4865 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4866 let arg = func.args[0].clone();
4867
4868 let gen_subscripts = Expression::Function(Box::new(Function::new(
4870 "GENERATE_SUBSCRIPTS".to_string(),
4871 vec![
4872 arg.clone(),
4873 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4874 ],
4875 )));
4876 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4877 gen_subscripts,
4878 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4879 )));
4880 let pos_alias = Expression::Alias(Box::new(Alias {
4881 this: sub_one,
4882 alias: Identifier::new("pos"),
4883 column_aliases: Vec::new(),
4884 alias_explicit_as: false,
4885 alias_keyword: None,
4886 pre_alias_comments: Vec::new(),
4887 trailing_comments: Vec::new(),
4888 inferred_type: None,
4889 }));
4890 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4891 this: arg,
4892 expressions: Vec::new(),
4893 with_ordinality: false,
4894 alias: None,
4895 offset_alias: None,
4896 inferred_type: None,
4897 }));
4898 let col_alias = Expression::Alias(Box::new(Alias {
4899 this: unnest,
4900 alias: Identifier::new("col"),
4901 column_aliases: Vec::new(),
4902 alias_explicit_as: false,
4903 alias_keyword: None,
4904 pre_alias_comments: Vec::new(),
4905 trailing_comments: Vec::new(),
4906 inferred_type: None,
4907 }));
4908
4909 let mut inner_select = Select::new();
4910 inner_select.expressions = vec![pos_alias, col_alias];
4911
4912 let subquery = Expression::Subquery(Box::new(Subquery {
4913 this: Expression::Select(Box::new(inner_select)),
4914 alias: None,
4915 column_aliases: Vec::new(),
4916 alias_explicit_as: false,
4917 alias_keyword: None,
4918 order_by: None,
4919 limit: None,
4920 offset: None,
4921 distribute_by: None,
4922 sort_by: None,
4923 cluster_by: None,
4924 lateral: false,
4925 modifiers_inside: false,
4926 trailing_comments: Vec::new(),
4927 inferred_type: None,
4928 }));
4929 new_expressions.push(subquery);
4930 _changed = true;
4931 continue;
4932 }
4933 }
4934
4935 new_expressions.push(table_expr);
4936 }
4937
4938 from.expressions = new_expressions;
4939 Ok(())
4940}
4941
4942pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
4957 match expr {
4958 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
4959 other => Ok(other),
4960 }
4961}
4962
4963pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
4973 match expr {
4974 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
4975 other => Ok(other),
4976 }
4977}
4978
4979fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
4980 let mut flattened_inputs: Vec<Expression> = Vec::new();
4981 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
4982
4983 for sel_expr in select.expressions.into_iter() {
4984 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
4985
4986 let rewritten = transform_recursive(sel_expr, &|e| {
4987 if let Expression::Lateral(lat) = e {
4988 if let Some(input_expr) = extract_flatten_input(&lat) {
4989 if found_input.borrow().is_none() {
4990 *found_input.borrow_mut() = Some(input_expr);
4991 }
4992 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
4993 }
4994 return Ok(Expression::Lateral(lat));
4995 }
4996 Ok(e)
4997 })?;
4998
4999 if let Some(input) = found_input.into_inner() {
5000 flattened_inputs.push(input);
5001 }
5002 new_selects.push(rewritten);
5003 }
5004
5005 if flattened_inputs.is_empty() {
5006 select.expressions = new_selects;
5007 return Ok(Expression::Select(Box::new(select)));
5008 }
5009
5010 select.expressions = new_selects;
5011
5012 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
5013 let is_first = idx == 0;
5015 let series_alias = if is_first {
5016 "pos".to_string()
5017 } else {
5018 format!("pos_{}", idx + 1)
5019 };
5020 let series_source_alias = if is_first {
5021 "_u".to_string()
5022 } else {
5023 format!("_u_{}", idx * 2 + 1)
5024 };
5025 let unnest_source_alias = if is_first {
5026 "_u_2".to_string()
5027 } else {
5028 format!("_u_{}", idx * 2 + 2)
5029 };
5030 let pos2_alias = if is_first {
5031 "pos_2".to_string()
5032 } else {
5033 format!("{}_2", series_alias)
5034 };
5035 let entity_alias = if is_first {
5036 "entity".to_string()
5037 } else {
5038 format!("entity_{}", idx + 1)
5039 };
5040
5041 let array_size_call = Expression::Function(Box::new(Function::new(
5042 "ARRAY_SIZE".to_string(),
5043 vec![Expression::NamedArgument(Box::new(NamedArgument {
5044 name: Identifier::new("INPUT"),
5045 value: input_expr.clone(),
5046 separator: NamedArgSeparator::DArrow,
5047 }))],
5048 )));
5049
5050 let greatest = Expression::Function(Box::new(Function::new(
5051 "GREATEST".to_string(),
5052 vec![array_size_call.clone()],
5053 )));
5054
5055 let series_end = Expression::Add(Box::new(BinaryOp::new(
5056 Expression::Paren(Box::new(crate::expressions::Paren {
5057 this: Expression::Sub(Box::new(BinaryOp::new(
5058 greatest,
5059 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5060 ))),
5061 trailing_comments: Vec::new(),
5062 })),
5063 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5064 )));
5065
5066 let series_range = Expression::Function(Box::new(Function::new(
5067 "ARRAY_GENERATE_RANGE".to_string(),
5068 vec![
5069 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
5070 series_end,
5071 ],
5072 )));
5073
5074 let series_flatten = Expression::Function(Box::new(Function::new(
5075 "FLATTEN".to_string(),
5076 vec![Expression::NamedArgument(Box::new(NamedArgument {
5077 name: Identifier::new("INPUT"),
5078 value: series_range,
5079 separator: NamedArgSeparator::DArrow,
5080 }))],
5081 )));
5082
5083 let series_table = Expression::Function(Box::new(Function::new(
5084 "TABLE".to_string(),
5085 vec![series_flatten],
5086 )));
5087
5088 let series_alias_expr = Expression::Alias(Box::new(Alias {
5089 this: series_table,
5090 alias: Identifier::new(series_source_alias.clone()),
5091 column_aliases: vec![
5092 Identifier::new("seq"),
5093 Identifier::new("key"),
5094 Identifier::new("path"),
5095 Identifier::new("index"),
5096 Identifier::new(series_alias.clone()),
5097 Identifier::new("this"),
5098 ],
5099 alias_explicit_as: false,
5100 alias_keyword: None,
5101 pre_alias_comments: Vec::new(),
5102 trailing_comments: Vec::new(),
5103 inferred_type: None,
5104 }));
5105
5106 select.joins.push(Join {
5107 this: series_alias_expr,
5108 on: None,
5109 using: Vec::new(),
5110 kind: JoinKind::Cross,
5111 use_inner_keyword: false,
5112 use_outer_keyword: false,
5113 deferred_condition: false,
5114 join_hint: None,
5115 match_condition: None,
5116 pivots: Vec::new(),
5117 comments: Vec::new(),
5118 nesting_group: 0,
5119 directed: false,
5120 });
5121
5122 let entity_flatten = Expression::Function(Box::new(Function::new(
5123 "FLATTEN".to_string(),
5124 vec![Expression::NamedArgument(Box::new(NamedArgument {
5125 name: Identifier::new("INPUT"),
5126 value: input_expr.clone(),
5127 separator: NamedArgSeparator::DArrow,
5128 }))],
5129 )));
5130
5131 let entity_table = Expression::Function(Box::new(Function::new(
5132 "TABLE".to_string(),
5133 vec![entity_flatten],
5134 )));
5135
5136 let entity_alias_expr = Expression::Alias(Box::new(Alias {
5137 this: entity_table,
5138 alias: Identifier::new(unnest_source_alias.clone()),
5139 column_aliases: vec![
5140 Identifier::new("seq"),
5141 Identifier::new("key"),
5142 Identifier::new("path"),
5143 Identifier::new(pos2_alias.clone()),
5144 Identifier::new(entity_alias.clone()),
5145 Identifier::new("this"),
5146 ],
5147 alias_explicit_as: false,
5148 alias_keyword: None,
5149 pre_alias_comments: Vec::new(),
5150 trailing_comments: Vec::new(),
5151 inferred_type: None,
5152 }));
5153
5154 select.joins.push(Join {
5155 this: entity_alias_expr,
5156 on: None,
5157 using: Vec::new(),
5158 kind: JoinKind::Cross,
5159 use_inner_keyword: false,
5160 use_outer_keyword: false,
5161 deferred_condition: false,
5162 join_hint: None,
5163 match_condition: None,
5164 pivots: Vec::new(),
5165 comments: Vec::new(),
5166 nesting_group: 0,
5167 directed: false,
5168 });
5169
5170 let pos_col =
5171 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
5172 let pos2_col =
5173 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
5174
5175 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
5176 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
5177 this: Expression::Sub(Box::new(BinaryOp::new(
5178 array_size_call,
5179 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5180 ))),
5181 trailing_comments: Vec::new(),
5182 }));
5183 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
5184 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
5185 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
5186 let or_cond = Expression::Or(Box::new(BinaryOp::new(
5187 eq,
5188 Expression::Paren(Box::new(crate::expressions::Paren {
5189 this: and_cond,
5190 trailing_comments: Vec::new(),
5191 })),
5192 )));
5193
5194 select.where_clause = Some(match select.where_clause.take() {
5195 Some(existing) => Where {
5196 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
5197 },
5198 None => Where { this: or_cond },
5199 });
5200 }
5201
5202 Ok(Expression::Select(Box::new(select)))
5203}
5204
5205fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
5206 let Expression::Function(f) = lat.this.as_ref() else {
5207 return None;
5208 };
5209 if !f.name.eq_ignore_ascii_case("FLATTEN") {
5210 return None;
5211 }
5212
5213 for arg in &f.args {
5214 if let Expression::NamedArgument(na) = arg {
5215 if na.name.name.eq_ignore_ascii_case("INPUT") {
5216 return Some(na.value.clone());
5217 }
5218 }
5219 }
5220 f.args.first().cloned()
5221}
5222
5223fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
5224 let cond = Expression::Eq(Box::new(BinaryOp::new(
5225 Expression::qualified_column("_u", "pos"),
5226 Expression::qualified_column("_u_2", "pos_2"),
5227 )));
5228 let true_expr = Expression::qualified_column("_u_2", "entity");
5229 let iff_expr = Expression::Function(Box::new(Function::new(
5230 "IFF".to_string(),
5231 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
5232 )));
5233
5234 lat.this = Box::new(iff_expr);
5235 if lat.column_aliases.is_empty() {
5236 lat.column_aliases = vec![
5237 "SEQ".to_string(),
5238 "KEY".to_string(),
5239 "PATH".to_string(),
5240 "INDEX".to_string(),
5241 "VALUE".to_string(),
5242 "THIS".to_string(),
5243 ];
5244 }
5245 lat
5246}
5247
5248struct ExplodeInfo {
5250 arg_sql: String,
5252 explode_alias: String,
5254 pos_alias: String,
5256 unnest_source_alias: String,
5258}
5259
5260fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
5261 let is_presto = matches!(
5262 target,
5263 DialectType::Presto | DialectType::Trino | DialectType::Athena
5264 );
5265 let is_bigquery = matches!(target, DialectType::BigQuery);
5266
5267 if !is_presto && !is_bigquery {
5268 return Ok(Expression::Select(Box::new(select)));
5269 }
5270
5271 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
5273 if !has_explode {
5274 return Ok(Expression::Select(Box::new(select)));
5275 }
5276
5277 let mut taken_select_names = std::collections::HashSet::new();
5279 let mut taken_source_names = std::collections::HashSet::new();
5280
5281 for sel in &select.expressions {
5283 if let Some(name) = get_output_name(sel) {
5284 taken_select_names.insert(name);
5285 }
5286 }
5287
5288 for sel in &select.expressions {
5290 let explode_expr = find_explode_in_expr(sel);
5291 if let Some(arg) = explode_expr {
5292 if let Some(name) = get_output_name(&arg) {
5293 taken_select_names.insert(name);
5294 }
5295 }
5296 }
5297
5298 if let Some(ref from) = select.from {
5300 for from_expr in &from.expressions {
5301 collect_source_names(from_expr, &mut taken_source_names);
5302 }
5303 }
5304 for join in &select.joins {
5306 collect_source_names(&join.this, &mut taken_source_names);
5307 }
5308
5309 let series_alias = new_name(&mut taken_select_names, "pos");
5311
5312 let series_source_alias = new_name(&mut taken_source_names, "_u");
5314
5315 let target_dialect = Dialect::get(target);
5317
5318 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
5320 let mut new_projections: Vec<String> = Vec::new();
5321
5322 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
5323 let explode_data = extract_explode_data(sel_expr);
5324
5325 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
5326 let arg_sql = target_dialect
5328 .generate(&arg_expr)
5329 .unwrap_or_else(|_| "NULL".to_string());
5330
5331 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
5332
5333 let explode_alias = if let Some(ref ea) = explicit_alias {
5334 taken_select_names.remove(ea.as_str());
5337 let name = new_name(&mut taken_select_names, ea);
5339 name
5340 } else {
5341 new_name(&mut taken_select_names, "col")
5342 };
5343
5344 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
5345 taken_select_names.remove(pa.as_str());
5347 let name = new_name(&mut taken_select_names, pa);
5348 name
5349 } else {
5350 new_name(&mut taken_select_names, "pos")
5351 };
5352
5353 if is_presto {
5355 let if_col = format!(
5357 "IF({}.{} = {}.{}, {}.{}) AS {}",
5358 series_source_alias,
5359 series_alias,
5360 unnest_source_alias,
5361 pos_alias,
5362 unnest_source_alias,
5363 explode_alias,
5364 explode_alias
5365 );
5366 new_projections.push(if_col);
5367
5368 if is_posexplode {
5370 let if_pos = format!(
5371 "IF({}.{} = {}.{}, {}.{}) AS {}",
5372 series_source_alias,
5373 series_alias,
5374 unnest_source_alias,
5375 pos_alias,
5376 unnest_source_alias,
5377 pos_alias,
5378 pos_alias
5379 );
5380 new_projections.push(if_pos);
5381 }
5382 } else {
5383 let if_col = format!(
5385 "IF({} = {}, {}, NULL) AS {}",
5386 series_alias, pos_alias, explode_alias, explode_alias
5387 );
5388 new_projections.push(if_col);
5389
5390 if is_posexplode {
5392 let if_pos = format!(
5393 "IF({} = {}, {}, NULL) AS {}",
5394 series_alias, pos_alias, pos_alias, pos_alias
5395 );
5396 new_projections.push(if_pos);
5397 }
5398 }
5399
5400 explode_infos.push(ExplodeInfo {
5401 arg_sql,
5402 explode_alias,
5403 pos_alias,
5404 unnest_source_alias,
5405 });
5406 } else {
5407 let sel_sql = target_dialect
5409 .generate(sel_expr)
5410 .unwrap_or_else(|_| "*".to_string());
5411 new_projections.push(sel_sql);
5412 }
5413 }
5414
5415 if explode_infos.is_empty() {
5416 return Ok(Expression::Select(Box::new(select)));
5417 }
5418
5419 let mut from_parts: Vec<String> = Vec::new();
5421
5422 if let Some(ref from) = select.from {
5424 for from_expr in &from.expressions {
5425 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
5426 from_parts.push(from_sql);
5427 }
5428 }
5429
5430 let size_exprs: Vec<String> = explode_infos
5432 .iter()
5433 .map(|info| {
5434 if is_presto {
5435 format!("CARDINALITY({})", info.arg_sql)
5436 } else {
5437 format!("ARRAY_LENGTH({})", info.arg_sql)
5438 }
5439 })
5440 .collect();
5441
5442 let greatest_arg = if size_exprs.len() == 1 {
5443 size_exprs[0].clone()
5444 } else {
5445 format!("GREATEST({})", size_exprs.join(", "))
5446 };
5447
5448 let series_sql = if is_presto {
5451 if size_exprs.len() == 1 {
5453 format!(
5454 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
5455 greatest_arg, series_source_alias, series_alias
5456 )
5457 } else {
5458 format!(
5460 "UNNEST(SEQUENCE(1, {})) AS {}({})",
5461 greatest_arg, series_source_alias, series_alias
5462 )
5463 }
5464 } else {
5465 if size_exprs.len() == 1 {
5467 format!(
5468 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
5469 greatest_arg, series_alias
5470 )
5471 } else {
5472 format!(
5474 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
5475 greatest_arg, series_alias
5476 )
5477 }
5478 };
5479
5480 let mut cross_joins: Vec<String> = Vec::new();
5484
5485 for info in &explode_infos {
5486 cross_joins.push(format!(
5488 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
5489 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
5490 ));
5491 }
5492
5493 let mut where_conditions: Vec<String> = Vec::new();
5495
5496 for info in &explode_infos {
5497 let size_expr = if is_presto {
5498 format!("CARDINALITY({})", info.arg_sql)
5499 } else {
5500 format!("ARRAY_LENGTH({})", info.arg_sql)
5501 };
5502
5503 let cond = if is_presto {
5504 format!(
5505 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
5506 series_src = series_source_alias,
5507 series_al = series_alias,
5508 unnest_src = info.unnest_source_alias,
5509 pos_al = info.pos_alias,
5510 size = size_expr
5511 )
5512 } else {
5513 format!(
5514 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
5515 series_al = series_alias,
5516 pos_al = info.pos_alias,
5517 size = size_expr
5518 )
5519 };
5520
5521 where_conditions.push(cond);
5522 }
5523
5524 let where_sql = if where_conditions.len() == 1 {
5526 where_conditions[0].clone()
5527 } else {
5528 where_conditions
5529 .iter()
5530 .map(|c| format!("({})", c))
5531 .collect::<Vec<_>>()
5532 .join(" AND ")
5533 };
5534
5535 let select_part = new_projections.join(", ");
5537
5538 let from_and_joins = if from_parts.is_empty() {
5540 format!("FROM {} {}", series_sql, cross_joins.join(" "))
5542 } else {
5543 format!(
5544 "FROM {} {} {}",
5545 from_parts.join(", "),
5546 format!("CROSS JOIN {}", series_sql),
5547 cross_joins.join(" ")
5548 )
5549 };
5550
5551 let full_sql = format!(
5552 "SELECT {} {} WHERE {}",
5553 select_part, from_and_joins, where_sql
5554 );
5555
5556 let generic_dialect = Dialect::get(DialectType::Generic);
5559 let parsed = generic_dialect.parse(&full_sql);
5560 match parsed {
5561 Ok(mut stmts) if !stmts.is_empty() => {
5562 let mut result = stmts.remove(0);
5563
5564 if is_bigquery {
5568 convert_unnest_presto_to_bigquery(&mut result);
5569 }
5570
5571 Ok(result)
5572 }
5573 _ => {
5574 Ok(Expression::Select(Box::new(select)))
5576 }
5577 }
5578}
5579
5580fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
5584 match expr {
5585 Expression::Select(ref mut select) => {
5586 if let Some(ref mut from) = select.from {
5588 for from_item in from.expressions.iter_mut() {
5589 convert_unnest_presto_to_bigquery(from_item);
5590 }
5591 }
5592 for join in select.joins.iter_mut() {
5594 convert_unnest_presto_to_bigquery(&mut join.this);
5595 }
5596 }
5597 Expression::Alias(ref alias) => {
5598 if let Expression::Unnest(ref unnest) = alias.this {
5600 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
5601 let col_alias = alias.column_aliases[0].clone();
5602 let pos_alias = alias.column_aliases[1].clone();
5603 let mut new_unnest = unnest.as_ref().clone();
5604 new_unnest.alias = Some(col_alias);
5605 new_unnest.offset_alias = Some(pos_alias);
5606 *expr = Expression::Unnest(Box::new(new_unnest));
5608 }
5609 }
5610 }
5611 _ => {}
5612 }
5613}
5614
5615fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
5618 if !names.contains(base) {
5619 names.insert(base.to_string());
5620 return base.to_string();
5621 }
5622 let mut i = 2;
5623 loop {
5624 let candidate = format!("{}_{}", base, i);
5625 if !names.contains(&candidate) {
5626 names.insert(candidate.clone());
5627 return candidate;
5628 }
5629 i += 1;
5630 }
5631}
5632
5633fn expr_contains_explode(expr: &Expression) -> bool {
5635 match expr {
5636 Expression::Explode(_) => true,
5637 Expression::ExplodeOuter(_) => true,
5638 Expression::Function(f) => {
5639 let name = f.name.to_uppercase();
5640 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
5641 }
5642 Expression::Alias(a) => expr_contains_explode(&a.this),
5643 _ => false,
5644 }
5645}
5646
5647fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
5649 match expr {
5650 Expression::Explode(uf) => Some(uf.this.clone()),
5651 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
5652 Expression::Function(f) => {
5653 let name = f.name.to_uppercase();
5654 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5655 Some(f.args[0].clone())
5656 } else {
5657 None
5658 }
5659 }
5660 Expression::Alias(a) => find_explode_in_expr(&a.this),
5661 _ => None,
5662 }
5663}
5664
5665fn extract_explode_data(
5668 expr: &Expression,
5669) -> Option<(bool, Expression, Option<String>, Option<String>)> {
5670 match expr {
5671 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
5673 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
5674 Expression::Function(f) => {
5676 let name = f.name.to_uppercase();
5677 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5678 Some((true, f.args[0].clone(), None, None))
5679 } else {
5680 None
5681 }
5682 }
5683 Expression::Alias(a) => {
5685 match &a.this {
5686 Expression::Explode(uf) => {
5687 let alias = if !a.alias.is_empty() {
5688 Some(a.alias.name.clone())
5689 } else {
5690 None
5691 };
5692 Some((false, uf.this.clone(), alias, None))
5693 }
5694 Expression::ExplodeOuter(uf) => {
5695 let alias = if !a.alias.is_empty() {
5696 Some(a.alias.name.clone())
5697 } else {
5698 None
5699 };
5700 Some((false, uf.this.clone(), alias, None))
5701 }
5702 Expression::Function(f) => {
5703 let name = f.name.to_uppercase();
5704 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5705 if a.column_aliases.len() == 2 {
5707 let pos_alias = a.column_aliases[0].name.clone();
5708 let col_alias = a.column_aliases[1].name.clone();
5709 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
5710 } else if !a.alias.is_empty() {
5711 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
5713 } else {
5714 Some((true, f.args[0].clone(), None, None))
5715 }
5716 } else {
5717 None
5718 }
5719 }
5720 _ => None,
5721 }
5722 }
5723 _ => None,
5724 }
5725}
5726
5727fn get_output_name(expr: &Expression) -> Option<String> {
5729 match expr {
5730 Expression::Alias(a) => {
5731 if !a.alias.is_empty() {
5732 Some(a.alias.name.clone())
5733 } else {
5734 None
5735 }
5736 }
5737 Expression::Column(c) => Some(c.name.name.clone()),
5738 Expression::Identifier(id) => Some(id.name.clone()),
5739 _ => None,
5740 }
5741}
5742
5743fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
5745 match expr {
5746 Expression::Alias(a) => {
5747 if !a.alias.is_empty() {
5748 names.insert(a.alias.name.clone());
5749 }
5750 }
5751 Expression::Subquery(s) => {
5752 if let Some(ref alias) = s.alias {
5753 names.insert(alias.name.clone());
5754 }
5755 }
5756 Expression::Table(t) => {
5757 if let Some(ref alias) = t.alias {
5758 names.insert(alias.name.clone());
5759 } else {
5760 names.insert(t.name.name.clone());
5761 }
5762 }
5763 Expression::Column(c) => {
5764 names.insert(c.name.name.clone());
5765 }
5766 Expression::Identifier(id) => {
5767 names.insert(id.name.clone());
5768 }
5769 _ => {}
5770 }
5771}
5772
5773pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
5776 use crate::dialects::transform_recursive;
5777 transform_recursive(expr, &strip_unnest_column_refs_single)
5778}
5779
5780fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
5781 if let Expression::Select(mut select) = expr {
5782 for join in select.joins.iter_mut() {
5784 strip_unnest_from_expr(&mut join.this);
5785 }
5786 if let Some(ref mut from) = select.from {
5788 for from_item in from.expressions.iter_mut() {
5789 strip_unnest_from_expr(from_item);
5790 }
5791 }
5792 Ok(Expression::Select(select))
5793 } else {
5794 Ok(expr)
5795 }
5796}
5797
5798fn strip_unnest_from_expr(expr: &mut Expression) {
5801 if let Expression::Alias(ref mut alias) = expr {
5802 if let Expression::Unnest(ref unnest) = alias.this {
5803 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
5804 if is_column_ref {
5805 let inner = unnest.this.clone();
5807 alias.this = inner;
5808 }
5809 }
5810 }
5811}
5812
5813pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
5816 use crate::dialects::transform_recursive;
5817 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
5818}
5819
5820fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
5821 if let Expression::Select(mut select) = expr {
5822 if let Some(ref mut from) = select.from {
5824 for from_item in from.expressions.iter_mut() {
5825 try_wrap_unnest_in_subquery(from_item);
5826 }
5827 }
5828
5829 for join in select.joins.iter_mut() {
5831 try_wrap_unnest_in_subquery(&mut join.this);
5832 }
5833
5834 Ok(Expression::Select(select))
5835 } else {
5836 Ok(expr)
5837 }
5838}
5839
5840fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
5842 match expr {
5843 Expression::Array(arr) => arr
5845 .expressions
5846 .iter()
5847 .any(|e| matches!(e, Expression::Struct(_))),
5848 Expression::ArrayFunc(arr) => arr
5849 .expressions
5850 .iter()
5851 .any(|e| matches!(e, Expression::Struct(_))),
5852 Expression::Cast(c) => {
5854 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
5855 }
5856 _ => false,
5857 }
5858}
5859
5860fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
5863 if let Expression::Alias(ref alias) = expr {
5865 if let Expression::Unnest(ref unnest) = alias.this {
5866 if is_struct_array_unnest_arg(&unnest.this) {
5867 let unnest_clone = (**unnest).clone();
5868 let alias_name = alias.alias.clone();
5869 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
5870 *expr = new_expr;
5871 return;
5872 }
5873 }
5874 }
5875
5876 if let Expression::Unnest(ref unnest) = expr {
5878 if is_struct_array_unnest_arg(&unnest.this) {
5879 let unnest_clone = (**unnest).clone();
5880 let new_expr = make_unnest_subquery(unnest_clone, None);
5881 *expr = new_expr;
5882 }
5883 }
5884}
5885
5886fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
5888 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
5890 name: Identifier::new("max_depth".to_string()),
5891 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
5892 separator: NamedArgSeparator::DArrow,
5893 }));
5894
5895 let mut unnest_args = vec![unnest.this];
5896 unnest_args.extend(unnest.expressions);
5897 unnest_args.push(max_depth_arg);
5898
5899 let unnest_func =
5900 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
5901
5902 let mut inner_select = Select::new();
5904 inner_select.expressions = vec![unnest_func];
5905 let inner_select = Expression::Select(Box::new(inner_select));
5906
5907 let subquery = Subquery {
5909 this: inner_select,
5910 alias,
5911 column_aliases: Vec::new(),
5912 alias_explicit_as: false,
5913 alias_keyword: None,
5914 order_by: None,
5915 limit: None,
5916 offset: None,
5917 distribute_by: None,
5918 sort_by: None,
5919 cluster_by: None,
5920 lateral: false,
5921 modifiers_inside: false,
5922 trailing_comments: Vec::new(),
5923 inferred_type: None,
5924 };
5925
5926 Expression::Subquery(Box::new(subquery))
5927}
5928
5929pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
5941 use crate::expressions::{split_set_limit, Limit, Offset as OffsetClause, OrderBy, Star};
5942
5943 match expr {
5944 Expression::Union(mut u) => {
5945 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
5948 if let Expression::Select(ref mut right_select) = u.right {
5950 if right_select.order_by.is_some()
5951 || right_select.limit.is_some()
5952 || right_select.offset.is_some()
5953 {
5954 u.order_by = right_select.order_by.take();
5956 u.limit = right_select.limit.take().map(Limit::into_set_limit);
5957 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
5958 }
5959 }
5960 }
5961
5962 let has_order_or_limit =
5963 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
5964 if has_order_or_limit {
5965 let order_by: Option<OrderBy> = u.order_by.take();
5967 let union_limit: Option<Box<Expression>> = u.limit.take();
5968 let union_offset: Option<Box<Expression>> = u.offset.take();
5969
5970 let (select_limit, select_fetch) = split_set_limit(union_limit);
5971
5972 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
5974 this: *o,
5975 rows: None,
5976 });
5977
5978 let subquery = Subquery {
5980 this: Expression::Union(u),
5981 alias: Some(Identifier::new("_l_0")),
5982 column_aliases: Vec::new(),
5983 alias_explicit_as: true,
5984 alias_keyword: None,
5985 lateral: false,
5986 modifiers_inside: false,
5987 order_by: None,
5988 limit: None,
5989 offset: None,
5990 distribute_by: None,
5991 sort_by: None,
5992 cluster_by: None,
5993 trailing_comments: Vec::new(),
5994 inferred_type: None,
5995 };
5996
5997 let mut select = Select::default();
5999 select.expressions = vec![Expression::Star(Star {
6000 table: None,
6001 except: None,
6002 replace: None,
6003 rename: None,
6004 trailing_comments: Vec::new(),
6005 span: None,
6006 })];
6007 select.from = Some(From {
6008 expressions: vec![Expression::Subquery(Box::new(subquery))],
6009 });
6010 select.order_by = order_by;
6011 select.limit = select_limit;
6012 select.fetch = select_fetch;
6013 select.offset = select_offset;
6014
6015 Ok(Expression::Select(Box::new(select)))
6016 } else {
6017 Ok(Expression::Union(u))
6018 }
6019 }
6020 _ => Ok(expr),
6021 }
6022}
6023
6024pub fn expand_like_any(expr: Expression) -> Result<Expression> {
6032 use crate::expressions::{BinaryOp, LikeOp, Paren};
6033
6034 const LIKE_ALL_MARKER: &str = "__LIKE_ALL_EXPANSION__";
6037
6038 fn unwrap_parens(e: &Expression) -> &Expression {
6039 match e {
6040 Expression::Paren(p) => unwrap_parens(&p.this),
6041 _ => e,
6042 }
6043 }
6044
6045 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
6046 let inner = unwrap_parens(e);
6047 match inner {
6048 Expression::Tuple(t) => Some(t.expressions.clone()),
6049 _ if !matches!(e, Expression::Tuple(_)) => Some(vec![inner.clone()]),
6051 _ => None,
6052 }
6053 }
6054
6055 fn expand_like_quantifier(
6057 op: &LikeOp,
6058 values: Vec<Expression>,
6059 is_ilike: bool,
6060 combiner: fn(Expression, Expression) -> Expression,
6061 wrap_marker: bool,
6062 ) -> Expression {
6063 let num_values = values.len();
6064 let mut result: Option<Expression> = None;
6065 for val in values {
6066 let like = if is_ilike {
6067 Expression::ILike(Box::new(LikeOp {
6068 left: op.left.clone(),
6069 right: val,
6070 escape: op.escape.clone(),
6071 quantifier: None,
6072 inferred_type: None,
6073 }))
6074 } else {
6075 Expression::Like(Box::new(LikeOp {
6076 left: op.left.clone(),
6077 right: val,
6078 escape: op.escape.clone(),
6079 quantifier: None,
6080 inferred_type: None,
6081 }))
6082 };
6083 result = Some(match result {
6084 None => like,
6085 Some(prev) => combiner(prev, like),
6086 });
6087 }
6088 let expanded = result.unwrap_or_else(|| unreachable!("values is non-empty"));
6089 if wrap_marker && num_values > 1 {
6093 Expression::Paren(Box::new(Paren {
6094 this: expanded,
6095 trailing_comments: vec![LIKE_ALL_MARKER.to_string()],
6096 }))
6097 } else {
6098 expanded
6099 }
6100 }
6101
6102 fn or_combiner(a: Expression, b: Expression) -> Expression {
6103 Expression::Or(Box::new(BinaryOp::new(a, b)))
6104 }
6105
6106 fn and_combiner(a: Expression, b: Expression) -> Expression {
6107 Expression::And(Box::new(BinaryOp::new(a, b)))
6108 }
6109
6110 fn is_like_all_marker(p: &Paren) -> bool {
6111 p.trailing_comments.len() == 1 && p.trailing_comments[0] == LIKE_ALL_MARKER
6112 }
6113
6114 let result = transform_recursive(expr, &|e| {
6122 match e {
6123 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6125 if let Some(values) = extract_tuple_values(&op.right) {
6126 if values.is_empty() {
6127 return Ok(e);
6128 }
6129 Ok(expand_like_quantifier(
6130 op,
6131 values,
6132 false,
6133 or_combiner,
6134 false,
6135 ))
6136 } else {
6137 Ok(e)
6138 }
6139 }
6140 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6142 if let Some(values) = extract_tuple_values(&op.right) {
6143 if values.is_empty() {
6144 return Ok(e);
6145 }
6146 Ok(expand_like_quantifier(
6147 op,
6148 values,
6149 false,
6150 and_combiner,
6151 true,
6152 ))
6153 } else {
6154 Ok(e)
6155 }
6156 }
6157 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6159 if let Some(values) = extract_tuple_values(&op.right) {
6160 if values.is_empty() {
6161 return Ok(e);
6162 }
6163 Ok(expand_like_quantifier(op, values, true, or_combiner, false))
6164 } else {
6165 Ok(e)
6166 }
6167 }
6168 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6170 if let Some(values) = extract_tuple_values(&op.right) {
6171 if values.is_empty() {
6172 return Ok(e);
6173 }
6174 Ok(expand_like_quantifier(op, values, true, and_combiner, true))
6175 } else {
6176 Ok(e)
6177 }
6178 }
6179 Expression::And(mut op) => {
6184 if matches!(&op.left, Expression::Or(_)) {
6185 op.left = Expression::Paren(Box::new(Paren {
6186 this: op.left,
6187 trailing_comments: vec![],
6188 }));
6189 }
6190 if matches!(&op.right, Expression::Or(_)) {
6191 op.right = Expression::Paren(Box::new(Paren {
6192 this: op.right,
6193 trailing_comments: vec![],
6194 }));
6195 }
6196 Ok(Expression::And(op))
6197 }
6198 Expression::Or(mut op) => {
6201 if let Expression::Paren(ref mut p) = op.left {
6202 if is_like_all_marker(p) {
6203 p.trailing_comments.clear();
6204 }
6205 }
6206 if let Expression::Paren(ref mut p) = op.right {
6207 if is_like_all_marker(p) {
6208 p.trailing_comments.clear();
6209 }
6210 }
6211 Ok(Expression::Or(op))
6212 }
6213 _ => Ok(e),
6214 }
6215 })?;
6216
6217 transform_recursive(result, &|e| {
6221 if let Expression::Paren(p) = &e {
6222 if is_like_all_marker(p) {
6223 let Expression::Paren(p) = e else {
6224 unreachable!()
6225 };
6226 return Ok(p.this);
6227 }
6228 }
6229 Ok(e)
6230 })
6231}
6232
6233pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
6241 use crate::expressions::Alias;
6242
6243 fn add_self_aliases_to_select(select: &mut Select) {
6244 let new_expressions: Vec<Expression> = select
6245 .expressions
6246 .iter()
6247 .map(|e| {
6248 match e {
6249 Expression::Column(col) => {
6251 let alias_name = col.name.clone();
6252 Expression::Alias(Box::new(Alias {
6253 this: e.clone(),
6254 alias: alias_name,
6255 column_aliases: Vec::new(),
6256 alias_explicit_as: false,
6257 alias_keyword: None,
6258 pre_alias_comments: Vec::new(),
6259 trailing_comments: Vec::new(),
6260 inferred_type: None,
6261 }))
6262 }
6263 _ => e.clone(),
6265 }
6266 })
6267 .collect();
6268 select.expressions = new_expressions;
6269 }
6270
6271 fn walk_and_qualify(expr: &mut Expression) {
6272 match expr {
6273 Expression::Select(ref mut select) => {
6274 if let Some(ref mut from) = select.from {
6276 for e in from.expressions.iter_mut() {
6277 qualify_subquery_expr(e);
6278 walk_and_qualify(e);
6279 }
6280 }
6281 for join in select.joins.iter_mut() {
6283 qualify_subquery_expr(&mut join.this);
6284 walk_and_qualify(&mut join.this);
6285 }
6286 for e in select.expressions.iter_mut() {
6288 walk_and_qualify(e);
6289 }
6290 if let Some(ref mut w) = select.where_clause {
6292 walk_and_qualify(&mut w.this);
6293 }
6294 }
6295 Expression::Subquery(ref mut subquery) => {
6296 walk_and_qualify(&mut subquery.this);
6297 }
6298 Expression::Union(ref mut u) => {
6299 walk_and_qualify(&mut u.left);
6300 walk_and_qualify(&mut u.right);
6301 }
6302 Expression::Intersect(ref mut i) => {
6303 walk_and_qualify(&mut i.left);
6304 walk_and_qualify(&mut i.right);
6305 }
6306 Expression::Except(ref mut e) => {
6307 walk_and_qualify(&mut e.left);
6308 walk_and_qualify(&mut e.right);
6309 }
6310 Expression::Cte(ref mut cte) => {
6311 walk_and_qualify(&mut cte.this);
6312 }
6313 _ => {}
6314 }
6315 }
6316
6317 fn qualify_subquery_expr(expr: &mut Expression) {
6318 match expr {
6319 Expression::Subquery(ref mut subquery) => {
6320 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
6322 if let Expression::Select(ref mut inner_select) = subquery.this {
6323 let has_star = inner_select
6325 .expressions
6326 .iter()
6327 .any(|e| matches!(e, Expression::Star(_)));
6328 if !has_star {
6329 add_self_aliases_to_select(inner_select);
6330 }
6331 }
6332 }
6333 walk_and_qualify(&mut subquery.this);
6335 }
6336 Expression::Alias(ref mut alias) => {
6337 qualify_subquery_expr(&mut alias.this);
6338 }
6339 _ => {}
6340 }
6341 }
6342
6343 let mut result = expr;
6344 walk_and_qualify(&mut result);
6345
6346 if let Expression::Select(ref mut select) = result {
6348 if let Some(ref mut with) = select.with {
6349 for cte in with.ctes.iter_mut() {
6350 if cte.columns.is_empty() {
6352 walk_and_qualify(&mut cte.this);
6354 }
6355 }
6356 }
6357 }
6358
6359 Ok(result)
6360}
6361
6362#[cfg(test)]
6363mod tests {
6364 use super::*;
6365 use crate::dialects::{Dialect, DialectType};
6366 use crate::expressions::Column;
6367
6368 fn gen(expr: &Expression) -> String {
6369 let dialect = Dialect::get(DialectType::Generic);
6370 dialect.generate(expr).unwrap()
6371 }
6372
6373 #[test]
6374 fn test_preprocess() {
6375 let expr = Expression::Boolean(BooleanLiteral { value: true });
6376 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
6377 assert!(
6378 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6379 );
6380 }
6381
6382 #[test]
6383 fn test_preprocess_chain() {
6384 let expr = Expression::Boolean(BooleanLiteral { value: true });
6386 let transforms: Vec<fn(Expression) -> Result<Expression>> =
6388 vec![replace_bool_with_int, replace_int_with_bool];
6389 let result = preprocess(expr, &transforms).unwrap();
6390 if let Expression::Boolean(b) = result {
6393 assert!(b.value);
6394 } else {
6395 panic!("Expected boolean literal");
6396 }
6397 }
6398
6399 #[test]
6400 fn test_unnest_to_explode() {
6401 let unnest = Expression::Unnest(Box::new(UnnestFunc {
6402 this: Expression::boxed_column(Column {
6403 name: Identifier::new("arr".to_string()),
6404 table: None,
6405 join_mark: false,
6406 trailing_comments: vec![],
6407 span: None,
6408 inferred_type: None,
6409 }),
6410 expressions: Vec::new(),
6411 with_ordinality: false,
6412 alias: None,
6413 offset_alias: None,
6414 inferred_type: None,
6415 }));
6416
6417 let result = unnest_to_explode(unnest).unwrap();
6418 assert!(matches!(result, Expression::Explode(_)));
6419 }
6420
6421 #[test]
6422 fn test_explode_to_unnest() {
6423 let explode = Expression::Explode(Box::new(UnaryFunc {
6424 this: Expression::boxed_column(Column {
6425 name: Identifier::new("arr".to_string()),
6426 table: None,
6427 join_mark: false,
6428 trailing_comments: vec![],
6429 span: None,
6430 inferred_type: None,
6431 }),
6432 original_name: None,
6433 inferred_type: None,
6434 }));
6435
6436 let result = explode_to_unnest(explode).unwrap();
6437 assert!(matches!(result, Expression::Unnest(_)));
6438 }
6439
6440 #[test]
6441 fn test_replace_bool_with_int() {
6442 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
6443 let result = replace_bool_with_int(true_expr).unwrap();
6444 if let Expression::Literal(lit) = result {
6445 if let Literal::Number(n) = lit.as_ref() {
6446 assert_eq!(n, "1");
6447 }
6448 } else {
6449 panic!("Expected number literal");
6450 }
6451
6452 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
6453 let result = replace_bool_with_int(false_expr).unwrap();
6454 if let Expression::Literal(lit) = result {
6455 if let Literal::Number(n) = lit.as_ref() {
6456 assert_eq!(n, "0");
6457 }
6458 } else {
6459 panic!("Expected number literal");
6460 }
6461 }
6462
6463 #[test]
6464 fn test_replace_int_with_bool() {
6465 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
6466 let result = replace_int_with_bool(one_expr).unwrap();
6467 if let Expression::Boolean(b) = result {
6468 assert!(b.value);
6469 } else {
6470 panic!("Expected boolean true");
6471 }
6472
6473 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
6474 let result = replace_int_with_bool(zero_expr).unwrap();
6475 if let Expression::Boolean(b) = result {
6476 assert!(!b.value);
6477 } else {
6478 panic!("Expected boolean false");
6479 }
6480
6481 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
6483 let result = replace_int_with_bool(two_expr).unwrap();
6484 assert!(
6485 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6486 );
6487 }
6488
6489 #[test]
6490 fn test_strip_data_type_params() {
6491 let decimal = DataType::Decimal {
6493 precision: Some(10),
6494 scale: Some(2),
6495 };
6496 let stripped = strip_data_type_params(decimal);
6497 assert_eq!(
6498 stripped,
6499 DataType::Decimal {
6500 precision: None,
6501 scale: None
6502 }
6503 );
6504
6505 let varchar = DataType::VarChar {
6507 length: Some(255),
6508 parenthesized_length: false,
6509 };
6510 let stripped = strip_data_type_params(varchar);
6511 assert_eq!(
6512 stripped,
6513 DataType::VarChar {
6514 length: None,
6515 parenthesized_length: false
6516 }
6517 );
6518
6519 let char_type = DataType::Char { length: Some(10) };
6521 let stripped = strip_data_type_params(char_type);
6522 assert_eq!(stripped, DataType::Char { length: None });
6523
6524 let timestamp = DataType::Timestamp {
6526 precision: Some(6),
6527 timezone: true,
6528 };
6529 let stripped = strip_data_type_params(timestamp);
6530 assert_eq!(
6531 stripped,
6532 DataType::Timestamp {
6533 precision: None,
6534 timezone: true
6535 }
6536 );
6537
6538 let array = DataType::Array {
6540 element_type: Box::new(DataType::VarChar {
6541 length: Some(100),
6542 parenthesized_length: false,
6543 }),
6544 dimension: None,
6545 };
6546 let stripped = strip_data_type_params(array);
6547 assert_eq!(
6548 stripped,
6549 DataType::Array {
6550 element_type: Box::new(DataType::VarChar {
6551 length: None,
6552 parenthesized_length: false
6553 }),
6554 dimension: None,
6555 }
6556 );
6557
6558 let text = DataType::Text;
6560 let stripped = strip_data_type_params(text);
6561 assert_eq!(stripped, DataType::Text);
6562 }
6563
6564 #[test]
6565 fn test_remove_precision_parameterized_types_cast() {
6566 let cast_expr = Expression::Cast(Box::new(Cast {
6568 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6569 to: DataType::Decimal {
6570 precision: Some(10),
6571 scale: Some(2),
6572 },
6573 trailing_comments: vec![],
6574 double_colon_syntax: false,
6575 format: None,
6576 default: None,
6577 inferred_type: None,
6578 }));
6579
6580 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6581 if let Expression::Cast(cast) = result {
6582 assert_eq!(
6583 cast.to,
6584 DataType::Decimal {
6585 precision: None,
6586 scale: None
6587 }
6588 );
6589 } else {
6590 panic!("Expected Cast expression");
6591 }
6592 }
6593
6594 #[test]
6595 fn test_remove_precision_parameterized_types_varchar() {
6596 let cast_expr = Expression::Cast(Box::new(Cast {
6598 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
6599 to: DataType::VarChar {
6600 length: Some(10),
6601 parenthesized_length: false,
6602 },
6603 trailing_comments: vec![],
6604 double_colon_syntax: false,
6605 format: None,
6606 default: None,
6607 inferred_type: None,
6608 }));
6609
6610 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6611 if let Expression::Cast(cast) = result {
6612 assert_eq!(
6613 cast.to,
6614 DataType::VarChar {
6615 length: None,
6616 parenthesized_length: false
6617 }
6618 );
6619 } else {
6620 panic!("Expected Cast expression");
6621 }
6622 }
6623
6624 #[test]
6625 fn test_remove_precision_direct_cast() {
6626 let cast = Expression::Cast(Box::new(Cast {
6630 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6631 to: DataType::Decimal {
6632 precision: Some(10),
6633 scale: Some(2),
6634 },
6635 trailing_comments: vec![],
6636 double_colon_syntax: false,
6637 format: None,
6638 default: None,
6639 inferred_type: None,
6640 }));
6641
6642 let transformed = remove_precision_parameterized_types(cast).unwrap();
6643 let generated = gen(&transformed);
6644
6645 assert!(generated.contains("DECIMAL"));
6647 assert!(!generated.contains("(10"));
6648 }
6649
6650 #[test]
6651 fn test_epoch_cast_to_ts() {
6652 let cast_expr = Expression::Cast(Box::new(Cast {
6654 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
6655 to: DataType::Timestamp {
6656 precision: None,
6657 timezone: false,
6658 },
6659 trailing_comments: vec![],
6660 double_colon_syntax: false,
6661 format: None,
6662 default: None,
6663 inferred_type: None,
6664 }));
6665
6666 let result = epoch_cast_to_ts(cast_expr).unwrap();
6667 if let Expression::Cast(cast) = result {
6668 if let Expression::Literal(lit) = cast.this {
6669 if let Literal::String(s) = lit.as_ref() {
6670 assert_eq!(s, "1970-01-01 00:00:00");
6671 }
6672 } else {
6673 panic!("Expected string literal");
6674 }
6675 } else {
6676 panic!("Expected Cast expression");
6677 }
6678 }
6679
6680 #[test]
6681 fn test_epoch_cast_to_ts_preserves_non_epoch() {
6682 let cast_expr = Expression::Cast(Box::new(Cast {
6684 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
6685 to: DataType::Timestamp {
6686 precision: None,
6687 timezone: false,
6688 },
6689 trailing_comments: vec![],
6690 double_colon_syntax: false,
6691 format: None,
6692 default: None,
6693 inferred_type: None,
6694 }));
6695
6696 let result = epoch_cast_to_ts(cast_expr).unwrap();
6697 if let Expression::Cast(cast) = result {
6698 if let Expression::Literal(lit) = cast.this {
6699 if let Literal::String(s) = lit.as_ref() {
6700 assert_eq!(s, "2024-01-15");
6701 }
6702 } else {
6703 panic!("Expected string literal");
6704 }
6705 } else {
6706 panic!("Expected Cast expression");
6707 }
6708 }
6709
6710 #[test]
6711 fn test_unqualify_columns() {
6712 let col = Expression::boxed_column(Column {
6714 name: Identifier::new("id".to_string()),
6715 table: Some(Identifier::new("users".to_string())),
6716 join_mark: false,
6717 trailing_comments: vec![],
6718 span: None,
6719 inferred_type: None,
6720 });
6721
6722 let result = unqualify_columns(col).unwrap();
6723 if let Expression::Column(c) = result {
6724 assert!(c.table.is_none());
6725 assert_eq!(c.name.name, "id");
6726 } else {
6727 panic!("Expected Column expression");
6728 }
6729 }
6730
6731 #[test]
6732 fn test_is_temporal_type() {
6733 assert!(is_temporal_type(&DataType::Date));
6734 assert!(is_temporal_type(&DataType::Timestamp {
6735 precision: None,
6736 timezone: false
6737 }));
6738 assert!(is_temporal_type(&DataType::Time {
6739 precision: None,
6740 timezone: false
6741 }));
6742 assert!(!is_temporal_type(&DataType::Int {
6743 length: None,
6744 integer_spelling: false
6745 }));
6746 assert!(!is_temporal_type(&DataType::VarChar {
6747 length: None,
6748 parenthesized_length: false
6749 }));
6750 }
6751
6752 #[test]
6753 fn test_eliminate_semi_join_basic() {
6754 use crate::expressions::{Join, TableRef};
6755
6756 let select = Expression::Select(Box::new(Select {
6758 vertica: None,
6759 expressions: vec![Expression::boxed_column(Column {
6760 name: Identifier::new("a".to_string()),
6761 table: None,
6762 join_mark: false,
6763 trailing_comments: vec![],
6764 span: None,
6765 inferred_type: None,
6766 })],
6767 from: Some(From {
6768 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
6769 }),
6770 joins: vec![Join {
6771 this: Expression::Table(Box::new(TableRef::new("t2"))),
6772 kind: JoinKind::Semi,
6773 on: Some(Expression::Eq(Box::new(BinaryOp {
6774 left: Expression::boxed_column(Column {
6775 name: Identifier::new("x".to_string()),
6776 table: None,
6777 join_mark: false,
6778 trailing_comments: vec![],
6779 span: None,
6780 inferred_type: None,
6781 }),
6782 right: Expression::boxed_column(Column {
6783 name: Identifier::new("y".to_string()),
6784 table: None,
6785 join_mark: false,
6786 trailing_comments: vec![],
6787 span: None,
6788 inferred_type: None,
6789 }),
6790 left_comments: vec![],
6791 operator_comments: vec![],
6792 trailing_comments: vec![],
6793 inferred_type: None,
6794 }))),
6795 using: vec![],
6796 use_inner_keyword: false,
6797 use_outer_keyword: false,
6798 deferred_condition: false,
6799 join_hint: None,
6800 match_condition: None,
6801 pivots: Vec::new(),
6802 comments: Vec::new(),
6803 nesting_group: 0,
6804 directed: false,
6805 }],
6806 ..Select::new()
6807 }));
6808
6809 let result = eliminate_semi_and_anti_joins(select).unwrap();
6810 if let Expression::Select(s) = result {
6811 assert!(s.joins.is_empty());
6813 assert!(s.where_clause.is_some());
6815 } else {
6816 panic!("Expected Select expression");
6817 }
6818 }
6819
6820 #[test]
6821 fn test_no_ilike_sql() {
6822 use crate::expressions::LikeOp;
6823
6824 let ilike_expr = Expression::ILike(Box::new(LikeOp {
6826 left: Expression::boxed_column(Column {
6827 name: Identifier::new("name".to_string()),
6828 table: None,
6829 join_mark: false,
6830 trailing_comments: vec![],
6831 span: None,
6832 inferred_type: None,
6833 }),
6834 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
6835 escape: None,
6836 quantifier: None,
6837 inferred_type: None,
6838 }));
6839
6840 let result = no_ilike_sql(ilike_expr).unwrap();
6841 if let Expression::Like(like) = result {
6842 if let Expression::Function(f) = &like.left {
6844 assert_eq!(f.name, "LOWER");
6845 } else {
6846 panic!("Expected LOWER function on left");
6847 }
6848 if let Expression::Function(f) = &like.right {
6850 assert_eq!(f.name, "LOWER");
6851 } else {
6852 panic!("Expected LOWER function on right");
6853 }
6854 } else {
6855 panic!("Expected Like expression");
6856 }
6857 }
6858
6859 #[test]
6860 fn test_no_trycast_sql() {
6861 let trycast_expr = Expression::TryCast(Box::new(Cast {
6863 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6864 to: DataType::Int {
6865 length: None,
6866 integer_spelling: false,
6867 },
6868 trailing_comments: vec![],
6869 double_colon_syntax: false,
6870 format: None,
6871 default: None,
6872 inferred_type: None,
6873 }));
6874
6875 let result = no_trycast_sql(trycast_expr).unwrap();
6876 assert!(matches!(result, Expression::Cast(_)));
6877 }
6878
6879 #[test]
6880 fn test_no_safe_cast_sql() {
6881 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
6883 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
6884 to: DataType::Int {
6885 length: None,
6886 integer_spelling: false,
6887 },
6888 trailing_comments: vec![],
6889 double_colon_syntax: false,
6890 format: None,
6891 default: None,
6892 inferred_type: None,
6893 }));
6894
6895 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
6896 assert!(matches!(result, Expression::Cast(_)));
6897 }
6898
6899 #[test]
6900 fn test_explode_to_unnest_presto() {
6901 let spark = Dialect::get(DialectType::Spark);
6902 let result = spark
6903 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
6904 .unwrap();
6905 assert_eq!(
6906 result[0],
6907 "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))"
6908 );
6909 }
6910
6911 #[test]
6912 fn test_explode_to_unnest_bigquery() {
6913 let spark = Dialect::get(DialectType::Spark);
6914 let result = spark
6915 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
6916 .unwrap();
6917 assert_eq!(
6918 result[0],
6919 "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))"
6920 );
6921 }
6922}