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> {
1208 crate::traversal::transform_all(expr, &eliminate_qualify_select)
1209}
1210
1211fn query_boundary(expr: &Expression) -> bool {
1212 matches!(
1213 expr,
1214 Expression::Select(_)
1215 | Expression::Subquery(_)
1216 | Expression::Union(_)
1217 | Expression::Intersect(_)
1218 | Expression::Except(_)
1219 )
1220}
1221
1222fn named_column(name: Identifier) -> Expression {
1223 Expression::Column(Box::new(crate::expressions::Column {
1224 name,
1225 table: None,
1226 join_mark: false,
1227 trailing_comments: vec![],
1228 span: None,
1229 inferred_type: None,
1230 }))
1231}
1232
1233fn derived_query(query: Expression, alias: Identifier) -> Expression {
1234 Expression::Subquery(Box::new(Subquery {
1235 this: query,
1236 alias: Some(alias),
1237 column_aliases: vec![],
1238 alias_explicit_as: false,
1239 alias_keyword: None,
1240 order_by: None,
1241 limit: None,
1242 offset: None,
1243 distribute_by: None,
1244 sort_by: None,
1245 cluster_by: None,
1246 lateral: false,
1247 modifiers_inside: false,
1248 trailing_comments: vec![],
1249 inferred_type: None,
1250 }))
1251}
1252
1253fn output_identifier(expr: &Expression) -> Option<Identifier> {
1254 match expr {
1255 Expression::Alias(a) => Some(a.alias.clone()),
1256 Expression::Column(c) if c.name.name != "*" => Some(c.name.clone()),
1257 Expression::Identifier(i) => Some(i.clone()),
1258 _ => None,
1259 }
1260}
1261
1262fn same_identifier(a: &Identifier, b: &Identifier) -> bool {
1263 if a.quoted || b.quoted {
1264 a.name == b.name
1265 } else {
1266 a.name.eq_ignore_ascii_case(&b.name)
1267 }
1268}
1269
1270struct QualifyProjection {
1271 expressions: Vec<Expression>,
1272 bindings: Vec<(Expression, Identifier)>,
1273 used_names: Vec<String>,
1274 source_names: Vec<Identifier>,
1275 derived_alias: Identifier,
1276}
1277
1278fn select_relation_names(select: &Select) -> Vec<Identifier> {
1279 fn collect(source: &Expression, names: &mut Vec<Identifier>) {
1280 match source {
1281 Expression::Table(table) => {
1282 names.push(table.alias.clone().unwrap_or_else(|| table.name.clone()))
1283 }
1284 Expression::Subquery(query) => names.extend(query.alias.iter().cloned()),
1285 Expression::Alias(alias) => names.push(alias.alias.clone()),
1286 other => {
1288 crate::ast_children::for_each_child_untracked(other, |child| collect(child, names))
1289 }
1290 }
1291 }
1292 let mut names = Vec::new();
1293 if let Some(from) = &select.from {
1294 for source in &from.expressions {
1295 collect(source, &mut names);
1296 }
1297 }
1298 for join in &select.joins {
1299 collect(&join.this, &mut names);
1300 }
1301 names
1302}
1303
1304impl QualifyProjection {
1305 fn fresh(&mut self, prefix: &str) -> Identifier {
1306 Identifier::new(fresh_grouped_percentile_name(&mut self.used_names, prefix))
1307 }
1308
1309 fn reference(&mut self, expression: Expression) -> Result<Expression> {
1310 if matches!(
1314 expression,
1315 Expression::Literal(_)
1316 | Expression::Boolean(_)
1317 | Expression::Null(_)
1318 | Expression::Parameter(_)
1319 | Expression::Placeholder(_)
1320 | Expression::SessionParameter(_)
1321 ) {
1322 return Ok(expression);
1323 }
1324 if query_boundary(&expression) {
1327 let mut expression = expression;
1328 self.rebind_correlated_columns(&mut expression, &[])?;
1329 return Ok(expression);
1330 }
1331 if let Some((_, name)) = self.bindings.iter().find(|(bound, _)| bound == &expression) {
1332 return Ok(named_column(name.clone()));
1333 }
1334 if let Expression::Column(column) = &expression {
1335 if column.table.is_none() {
1336 if let Some((_, name)) = self
1337 .bindings
1338 .iter()
1339 .find(|(_, name)| same_identifier(&column.name, name))
1340 {
1341 return Ok(named_column(name.clone()));
1342 }
1343 }
1344 }
1345 if matches!(
1346 expression,
1347 Expression::Column(_) | Expression::Identifier(_)
1348 ) || is_window_expr(&expression)
1349 || crate::traversal::is_aggregate(&expression)
1350 {
1351 let mut value = expression.clone();
1352 if is_window_expr(&value) {
1353 self.resolve_window_aliases(&mut value)?;
1354 }
1355 let name = match output_identifier(&expression) {
1356 Some(name)
1357 if !self
1358 .used_names
1359 .iter()
1360 .any(|used| used.eq_ignore_ascii_case(&name.name)) =>
1361 {
1362 self.used_names.push(name.name.clone());
1363 name
1364 }
1365 _ => self.fresh(if is_window_expr(&expression) {
1366 "_w"
1367 } else {
1368 "_c"
1369 }),
1370 };
1371 self.expressions
1372 .push(Expression::Alias(Box::new(Alias::new(value, name.clone()))));
1373 self.bindings.push((expression, name.clone()));
1374 return Ok(named_column(name));
1375 }
1376 let mut expression = expression;
1377 let mut result = Ok(());
1378 crate::ast_children::for_each_child_mut(&mut expression, |child| {
1379 if result.is_ok() {
1380 let old = std::mem::replace(child, Expression::null());
1381 match self.reference(old) {
1382 Ok(rewritten) => *child = rewritten,
1383 Err(error) => result = Err(error),
1384 }
1385 }
1386 });
1387 result?;
1388 Ok(expression)
1389 }
1390
1391 fn rebind_correlated_columns(
1392 &mut self,
1393 expression: &mut Expression,
1394 shadowed: &[Identifier],
1395 ) -> Result<()> {
1396 let mut local = shadowed.to_vec();
1397 if let Expression::Select(select) = expression {
1398 local.extend(select_relation_names(select));
1399 }
1400 if let Expression::Column(column) = expression {
1401 if column.table.as_ref().is_some_and(|table| {
1402 self.source_names
1403 .iter()
1404 .any(|name| same_identifier(table, name))
1405 && !local.iter().any(|name| same_identifier(table, name))
1406 }) {
1407 let mut reference = self.reference(expression.clone())?;
1408 if let Expression::Column(column) = &mut reference {
1409 column.table = Some(self.derived_alias.clone());
1410 }
1411 *expression = reference;
1412 return Ok(());
1413 }
1414 }
1415 let mut result = Ok(());
1416 crate::ast_children::for_each_child_mut(expression, |child| {
1417 if result.is_ok() {
1418 result = self.rebind_correlated_columns(child, &local);
1419 }
1420 });
1421 result
1422 }
1423
1424 fn resolve_window_aliases(&self, expression: &mut Expression) -> Result<()> {
1425 if query_boundary(expression) {
1426 return Ok(());
1427 }
1428 if let Expression::Column(column) = expression {
1429 if column.table.is_none() {
1430 if let Some((value, _)) = self
1431 .bindings
1432 .iter()
1433 .find(|(_, name)| same_identifier(&column.name, name))
1434 {
1435 if is_window_expr(value) {
1436 return Err(Error::unsupported(
1437 "QUALIFY window depending on another window alias",
1438 "derived-table rewrite",
1439 ));
1440 }
1441 *expression = value.clone();
1442 return Ok(());
1443 }
1444 }
1445 }
1446 let mut result = Ok(());
1447 crate::ast_children::for_each_child_mut(expression, |child| {
1448 if result.is_ok() {
1449 result = self.resolve_window_aliases(child);
1450 }
1451 });
1452 result
1453 }
1454}
1455
1456fn eliminate_qualify_select(expr: Expression) -> Result<Expression> {
1457 let Expression::Select(mut inner) = expr else {
1458 return Ok(expr);
1459 };
1460 let Some(qualify) = inner.qualify.take() else {
1461 return Ok(Expression::Select(inner));
1462 };
1463 let mut projection = QualifyProjection {
1464 expressions: vec![],
1465 bindings: vec![],
1466 used_names: vec![],
1467 source_names: select_relation_names(&inner),
1468 derived_alias: Identifier::new("_t"),
1469 };
1470 use crate::traversal::ExpressionWalk;
1472 for node in Expression::Select(inner.clone()).dfs() {
1473 if let Some(name) = output_identifier(node) {
1474 projection.used_names.push(name.name);
1475 }
1476 }
1477 projection
1478 .used_names
1479 .extend(projection.source_names.iter().map(|name| name.name.clone()));
1480 projection.derived_alias = projection.fresh("_t");
1481 if inner
1484 .expressions
1485 .iter()
1486 .any(|expr| matches!(expr, Expression::Star(_)))
1487 {
1488 let source = inner
1489 .from
1490 .as_ref()
1491 .filter(|from| from.expressions.len() == 1 && inner.joins.is_empty())
1492 .and_then(|from| from.expressions.first());
1493 if let Some(source) = source {
1494 if let Ok(names) =
1495 crate::set_operation::query_output_identifiers(source, inner.source_dialect)
1496 {
1497 let mut expanded = Vec::new();
1498 for expr in std::mem::take(&mut inner.expressions) {
1499 if matches!(&expr, Expression::Star(star) if star.except.is_none() && star.replace.is_none() && star.rename.is_none())
1500 {
1501 expanded.extend(names.iter().cloned().map(named_column));
1502 } else {
1503 expanded.push(expr);
1504 }
1505 }
1506 inner.expressions = expanded;
1507 }
1508 }
1509 }
1510 let mut outer = Select::new();
1511 for expr in std::mem::take(&mut inner.expressions) {
1512 if matches!(&expr, Expression::Star(_))
1513 || matches!(&expr, Expression::Column(c) if c.name.name == "*")
1514 {
1515 return Err(Error::unsupported("QUALIFY with an unresolved wildcard projection; explicit output columns are required to hide helper columns", "derived-table rewrite"));
1516 }
1517 let name = output_identifier(&expr).unwrap_or_else(|| projection.fresh("_c"));
1518 if projection
1519 .bindings
1520 .iter()
1521 .any(|(_, other)| same_identifier(&name, other))
1522 {
1523 return Err(Error::unsupported(
1524 "QUALIFY with duplicate output names",
1525 "derived-table rewrite",
1526 ));
1527 }
1528 let value = unalias_expression(&expr).clone();
1529 projection.bindings.push((value, name.clone()));
1530 projection
1531 .expressions
1532 .push(if output_identifier(&expr).is_some() {
1533 expr
1534 } else {
1535 Expression::Alias(Box::new(Alias::new(expr, name.clone())))
1536 });
1537 outer.expressions.push(named_column(name));
1538 }
1539 outer.where_clause = Some(Where {
1540 this: projection.reference(qualify.this)?,
1541 });
1542 outer.order_by = inner.order_by.take();
1543 if let Some(order) = &mut outer.order_by {
1544 for key in &mut order.expressions {
1545 if !matches!(&key.this, Expression::Literal(literal)
1547 if matches!(literal.as_ref(), Literal::Number(number) if number.parse::<usize>().is_ok()))
1548 {
1549 key.this = projection.reference(key.this.clone())?;
1550 }
1551 }
1552 }
1553 outer.distinct = std::mem::take(&mut inner.distinct);
1554 outer.distinct_on = inner
1555 .distinct_on
1556 .take()
1557 .map(|expressions| {
1558 expressions
1559 .into_iter()
1560 .map(|expr| projection.reference(expr))
1561 .collect::<Result<Vec<_>>>()
1562 })
1563 .transpose()?;
1564 outer.limit = inner.limit.take();
1565 outer.offset = inner.offset.take();
1566 outer.fetch = inner.fetch.take();
1567 outer.top = inner.top.take();
1568 outer.with = inner.with.take();
1569 outer.into = inner.into.take();
1570 outer.leading_comments = std::mem::take(&mut inner.leading_comments);
1571 outer.post_select_comments = std::mem::take(&mut inner.post_select_comments);
1572 outer.source_dialect = inner.source_dialect;
1573 inner.expressions = projection.expressions;
1574 let alias = projection.derived_alias;
1575 outer.from = Some(From {
1576 expressions: vec![derived_query(Expression::Select(inner), alias)],
1577 });
1578 Ok(Expression::Select(Box::new(outer)))
1579}
1580
1581fn is_window_expr(expr: &Expression) -> bool {
1582 matches!(expr, Expression::Window(_) | Expression::WindowFunction(_))
1583}
1584
1585pub(crate) fn lower_set_operations_by_name(
1588 expr: Expression,
1589 source: DialectType,
1590 target: DialectType,
1591) -> Result<Expression> {
1592 if matches!(
1593 target,
1594 DialectType::DuckDB | DialectType::Snowflake | DialectType::BigQuery
1595 ) {
1596 return Ok(expr);
1597 }
1598 crate::traversal::transform_all(expr, &|mut expr| {
1599 let source = if source == DialectType::Generic {
1600 DialectType::BigQuery
1601 } else {
1602 source
1603 };
1604 let Ok(Some(layout)) = crate::set_operation::set_operation_layout(&expr, Some(source))
1605 else {
1606 return Ok(expr);
1607 };
1608 if layout.outputs.is_empty() {
1609 return Ok(expr);
1610 }
1611 macro_rules! lower {
1612 ($set:expr) => {{
1613 let set = $set;
1614 let left = align_set_operand(&set.left, &layout.outputs, true, source)?;
1615 let right = align_set_operand(&set.right, &layout.outputs, false, source)?;
1616 set.left = left;
1617 set.right = right;
1618 set.by_name = false;
1619 set.corresponding = false;
1620 set.strict = false;
1621 set.side = None;
1622 set.kind = None;
1623 set.on_columns.clear();
1624 }};
1625 }
1626 match &mut expr {
1627 Expression::Union(set) => lower!(set),
1628 Expression::Intersect(set) => lower!(set),
1629 Expression::Except(set) => lower!(set),
1630 _ => {}
1631 }
1632 Ok(expr)
1633 })
1634}
1635
1636fn align_set_operand(
1637 expr: &Expression,
1638 outputs: &[crate::set_operation::SetOperationOutput],
1639 left: bool,
1640 source: DialectType,
1641) -> Result<Expression> {
1642 let names = crate::set_operation::query_output_identifiers(expr, Some(source))
1643 .map_err(|error| Error::unsupported(error.to_string(), "positional set operation"))?;
1644 use crate::traversal::ExpressionWalk;
1648 let has_parameters =
1649 expr.contains(|node| matches!(node, Expression::Parameter(_) | Expression::Placeholder(_)));
1650 let plain = match expr {
1653 Expression::Select(select)
1654 if !has_parameters
1655 && select.order_by.is_none()
1656 && select.limit.is_none()
1657 && select.offset.is_none()
1658 && select.fetch.is_none()
1659 && select.top.is_none()
1660 && !select.distinct
1661 && select.distinct_on.is_none() =>
1662 {
1663 Some(select)
1664 }
1665 _ => None,
1666 };
1667 let mut select = plain.map_or_else(Select::new, |select| (**select).clone());
1668 select.expressions = outputs
1669 .iter()
1670 .map(|output| {
1671 let ordinal = if left {
1672 output.left_ordinal
1673 } else {
1674 output.right_ordinal
1675 };
1676 let expression = ordinal.map_or_else(Expression::null, |index| {
1677 plain.map_or_else(
1678 || named_column(names[index].clone()),
1679 |select| unalias_expression(&select.expressions[index]).clone(),
1680 )
1681 });
1682 if output_identifier(&expression).as_ref() == Some(&output.identifier) {
1683 expression
1684 } else {
1685 Expression::Alias(Box::new(Alias::new(expression, output.identifier.clone())))
1686 }
1687 })
1688 .collect();
1689 if plain.is_none() {
1690 select.from = Some(From {
1691 expressions: vec![derived_query(expr.clone(), Identifier::new("_by_name"))],
1692 });
1693 }
1694 Ok(Expression::Select(Box::new(select)))
1695}
1696
1697pub fn eliminate_distinct_on(expr: Expression) -> Result<Expression> {
1716 eliminate_distinct_on_for_dialect(expr, None, None)
1717}
1718
1719pub fn strip_cte_materialization(expr: Expression) -> Result<Expression> {
1722 transform_recursive(expr, &strip_cte_materialization_single)
1723}
1724
1725fn strip_cte_materialization_single(expr: Expression) -> Result<Expression> {
1726 Ok(match expr {
1727 Expression::Select(mut select) => {
1728 strip_with_cte_materialization(&mut select.with);
1729 Expression::Select(select)
1730 }
1731 Expression::Union(mut union) => {
1732 strip_with_cte_materialization(&mut union.with);
1733 Expression::Union(union)
1734 }
1735 Expression::Intersect(mut intersect) => {
1736 strip_with_cte_materialization(&mut intersect.with);
1737 Expression::Intersect(intersect)
1738 }
1739 Expression::Except(mut except) => {
1740 strip_with_cte_materialization(&mut except.with);
1741 Expression::Except(except)
1742 }
1743 Expression::Pivot(mut pivot) => {
1744 strip_with_cte_materialization(&mut pivot.with);
1745 Expression::Pivot(pivot)
1746 }
1747 Expression::Insert(mut insert) => {
1748 strip_with_cte_materialization(&mut insert.with);
1749 Expression::Insert(insert)
1750 }
1751 Expression::Update(mut update) => {
1752 strip_with_cte_materialization(&mut update.with);
1753 Expression::Update(update)
1754 }
1755 Expression::Delete(mut delete) => {
1756 strip_with_cte_materialization(&mut delete.with);
1757 Expression::Delete(delete)
1758 }
1759 Expression::CreateTable(mut create_table) => {
1760 strip_with_cte_materialization(&mut create_table.with_cte);
1761 Expression::CreateTable(create_table)
1762 }
1763 Expression::With(mut with) => {
1764 strip_cte_materialization_in_with(&mut with);
1765 Expression::With(with)
1766 }
1767 Expression::Cte(mut cte) => {
1768 cte.materialized = None;
1769 Expression::Cte(cte)
1770 }
1771 _ => expr,
1772 })
1773}
1774
1775fn strip_with_cte_materialization(with: &mut Option<With>) {
1776 if let Some(with) = with {
1777 strip_cte_materialization_in_with(with);
1778 }
1779}
1780
1781fn strip_cte_materialization_in_with(with: &mut With) {
1782 for cte in &mut with.ctes {
1783 cte.materialized = None;
1784 }
1785}
1786
1787#[derive(Clone, Copy)]
1788enum DistinctOnNullsMode {
1789 None,
1790 NullsFirst,
1791 CaseExpr,
1792}
1793
1794pub fn eliminate_distinct_on_for_dialect(
1799 expr: Expression,
1800 target: Option<DialectType>,
1801 source: Option<DialectType>,
1802) -> Result<Expression> {
1803 if matches!(
1805 target,
1806 Some(DialectType::PostgreSQL) | Some(DialectType::DuckDB)
1807 ) {
1808 return Ok(expr);
1809 }
1810
1811 let nulls_mode = match target {
1816 Some(DialectType::MySQL)
1817 | Some(DialectType::SingleStore)
1818 | Some(DialectType::TSQL)
1819 | Some(DialectType::Fabric) => DistinctOnNullsMode::CaseExpr,
1820 Some(DialectType::Oracle) | Some(DialectType::Redshift) | Some(DialectType::Snowflake) => {
1821 DistinctOnNullsMode::None
1822 }
1823 Some(DialectType::StarRocks) => {
1824 if matches!(source, Some(DialectType::Redshift)) {
1825 DistinctOnNullsMode::CaseExpr
1826 } else {
1827 DistinctOnNullsMode::None
1828 }
1829 }
1830 _ => DistinctOnNullsMode::NullsFirst,
1832 };
1833
1834 transform_recursive(expr, &|expr| {
1835 eliminate_distinct_on_select(expr, nulls_mode, target)
1836 })
1837}
1838
1839fn resolve_positional_order_by(
1843 exprs: Vec<crate::expressions::Ordered>,
1844 select_exprs: &[Expression],
1845 target: Option<DialectType>,
1846) -> Result<Vec<crate::expressions::Ordered>> {
1847 exprs
1848 .into_iter()
1849 .map(|mut ord| {
1850 if let Expression::Literal(lit) = &ord.this {
1851 if let Literal::Number(n) = lit.as_ref() {
1852 if let Ok(idx) = n.parse::<usize>() {
1853 if idx >= 1 && idx <= select_exprs.len() {
1854 ord.this = match select_exprs[idx - 1].clone() {
1855 Expression::Alias(alias) => alias.this,
1856 other => other,
1857 };
1858 }
1859 }
1860 }
1861 }
1862 if crate::dialects::contains_in_projection(&ord.this, |e| matches!(e, Expression::WindowFunction(_))) {
1863 return Err(Error::unsupported(
1864 "DISTINCT ON ordering by a window expression requires an additional query layer",
1865 format!("{target:?}"),
1866 ));
1867 }
1868 Ok(ord)
1869 })
1870 .collect()
1871}
1872
1873fn eliminate_distinct_on_select(
1874 expr: Expression,
1875 nulls_mode: DistinctOnNullsMode,
1876 target: Option<DialectType>,
1877) -> Result<Expression> {
1878 use crate::expressions::Case;
1879
1880 let expr = if matches!(&expr, Expression::Select(select)
1883 if select.qualify.is_some() && select.distinct_on.is_some())
1884 {
1885 eliminate_qualify_select(expr)?
1886 } else {
1887 expr
1888 };
1889
1890 match expr {
1891 Expression::Select(mut select) => {
1892 if let Some(distinct_cols) = select.distinct_on.take() {
1893 if !distinct_cols.is_empty() {
1894 let row_number_alias = Identifier::new("_row_number".to_string());
1896
1897 let order_exprs = if let Some(ref order_by) = select.order_by {
1899 let mut exprs = resolve_positional_order_by(
1905 order_by.expressions.clone(),
1906 &select.expressions,
1907 target,
1908 )?;
1909 match nulls_mode {
1911 DistinctOnNullsMode::NullsFirst => {
1912 for ord in &mut exprs {
1913 if ord.desc && ord.nulls_first.is_none() {
1914 ord.nulls_first = Some(true);
1915 }
1916 }
1917 }
1918 DistinctOnNullsMode::CaseExpr => {
1919 let mut new_exprs = Vec::new();
1922 for ord in &exprs {
1923 if ord.desc && ord.nulls_first != Some(false) {
1924 let null_check = Expression::Case(Box::new(Case {
1926 operand: None,
1927 whens: vec![(
1928 Expression::IsNull(Box::new(
1929 crate::expressions::IsNull {
1930 this: ord.this.clone(),
1931 not: false,
1932 postfix_form: false,
1933 },
1934 )),
1935 Expression::Literal(Box::new(Literal::Number(
1936 "1".to_string(),
1937 ))),
1938 )],
1939 else_: Some(Expression::Literal(Box::new(
1940 Literal::Number("0".to_string()),
1941 ))),
1942 comments: Vec::new(),
1943 inferred_type: None,
1944 }));
1945 new_exprs.push(crate::expressions::Ordered {
1946 nulls_auto: false,
1947 this: null_check,
1948 desc: true,
1949 nulls_first: None,
1950 explicit_asc: false,
1951 with_fill: None,
1952 });
1953 }
1954 let mut key = ord.clone();
1955 if key.desc && key.nulls_first == Some(true) {
1956 key.nulls_first = None;
1957 }
1958 new_exprs.push(key);
1959 }
1960 exprs = new_exprs;
1961 }
1962 DistinctOnNullsMode::None => {}
1963 }
1964 exprs
1965 } else {
1966 distinct_cols
1967 .iter()
1968 .map(|e| crate::expressions::Ordered {
1969 nulls_auto: false,
1970 this: e.clone(),
1971 desc: false,
1972 nulls_first: None,
1973 explicit_asc: false,
1974 with_fill: None,
1975 })
1976 .collect()
1977 };
1978
1979 let row_number_func =
1981 Expression::WindowFunction(Box::new(crate::expressions::WindowFunction {
1982 this: Expression::RowNumber(crate::expressions::RowNumber),
1983 over: Over {
1984 partition_by: distinct_cols,
1985 order_by: order_exprs,
1986 frame: None,
1987 window_name: None,
1988 alias: None,
1989 },
1990 keep: None,
1991 inferred_type: None,
1992 }));
1993
1994 let mut inner_aliased_exprs = Vec::new();
1998 let mut outer_select_exprs = Vec::new();
1999 for orig_expr in &select.expressions {
2000 match orig_expr {
2001 Expression::Alias(alias) => {
2002 inner_aliased_exprs.push(orig_expr.clone());
2004 outer_select_exprs.push(Expression::Column(Box::new(
2005 crate::expressions::Column {
2006 name: alias.alias.clone(),
2007 table: None,
2008 join_mark: false,
2009 trailing_comments: vec![],
2010 span: None,
2011 inferred_type: None,
2012 },
2013 )));
2014 }
2015 Expression::Column(col) => {
2016 inner_aliased_exprs.push(Expression::Alias(Box::new(
2018 crate::expressions::Alias {
2019 this: orig_expr.clone(),
2020 alias: col.name.clone(),
2021 column_aliases: vec![],
2022 alias_explicit_as: false,
2023 alias_keyword: None,
2024 pre_alias_comments: vec![],
2025 trailing_comments: vec![],
2026 inferred_type: None,
2027 },
2028 )));
2029 outer_select_exprs.push(Expression::Column(Box::new(
2030 crate::expressions::Column {
2031 name: col.name.clone(),
2032 table: None,
2033 join_mark: false,
2034 trailing_comments: vec![],
2035 span: None,
2036 inferred_type: None,
2037 },
2038 )));
2039 }
2040 _ => {
2041 inner_aliased_exprs.push(orig_expr.clone());
2043 outer_select_exprs.push(orig_expr.clone());
2044 }
2045 }
2046 }
2047
2048 let row_number_alias_expr =
2050 Expression::Alias(Box::new(crate::expressions::Alias {
2051 this: row_number_func,
2052 alias: row_number_alias.clone(),
2053 column_aliases: vec![],
2054 alias_explicit_as: false,
2055 alias_keyword: None,
2056 pre_alias_comments: vec![],
2057 trailing_comments: vec![],
2058 inferred_type: None,
2059 }));
2060 inner_aliased_exprs.push(row_number_alias_expr);
2061
2062 select.expressions = inner_aliased_exprs;
2064
2065 let _inner_order_by = select.order_by.take();
2067
2068 select.distinct = false;
2070
2071 let inner_select = Expression::Select(select);
2073 let subquery = Subquery {
2074 this: inner_select,
2075 alias: Some(Identifier::new("_t".to_string())),
2076 column_aliases: vec![],
2077 alias_explicit_as: false,
2078 alias_keyword: None,
2079 order_by: None,
2080 limit: None,
2081 offset: None,
2082 distribute_by: None,
2083 sort_by: None,
2084 cluster_by: None,
2085 lateral: false,
2086 modifiers_inside: false,
2087 trailing_comments: vec![],
2088 inferred_type: None,
2089 };
2090
2091 let outer_select = Select {
2094 vertica: None,
2095 expressions: outer_select_exprs,
2096 from: Some(From {
2097 expressions: vec![Expression::Subquery(Box::new(subquery))],
2098 }),
2099 where_clause: Some(Where {
2100 this: Expression::Eq(Box::new(BinaryOp {
2101 left: Expression::Column(Box::new(crate::expressions::Column {
2102 name: row_number_alias,
2103 table: None,
2104 join_mark: false,
2105 trailing_comments: vec![],
2106 span: None,
2107 inferred_type: None,
2108 })),
2109 right: Expression::Literal(Box::new(Literal::Number(
2110 "1".to_string(),
2111 ))),
2112 left_comments: vec![],
2113 operator_comments: vec![],
2114 trailing_comments: vec![],
2115 inferred_type: None,
2116 })),
2117 }),
2118 ..Select::new()
2119 };
2120
2121 return Ok(Expression::Select(Box::new(outer_select)));
2122 }
2123 }
2124 Ok(Expression::Select(select))
2125 }
2126 other => Ok(other),
2127 }
2128}
2129
2130pub fn eliminate_semi_and_anti_joins(expr: Expression) -> Result<Expression> {
2138 match expr {
2139 Expression::Select(mut select) => {
2140 let mut new_joins = Vec::new();
2141 let mut extra_where_conditions = Vec::new();
2142
2143 for join in select.joins.drain(..) {
2144 match join.kind {
2145 JoinKind::Semi | JoinKind::LeftSemi => {
2146 if let Some(on_condition) = join.on {
2147 let subquery_select = Select {
2149 vertica: None,
2150 expressions: vec![Expression::Literal(Box::new(Literal::Number(
2151 "1".to_string(),
2152 )))],
2153 from: Some(From {
2154 expressions: vec![join.this],
2155 }),
2156 where_clause: Some(Where { this: on_condition }),
2157 ..Select::new()
2158 };
2159
2160 let exists = Expression::Exists(Box::new(Exists {
2161 this: Expression::Subquery(Box::new(Subquery {
2162 this: Expression::Select(Box::new(subquery_select)),
2163 alias: None,
2164 column_aliases: vec![],
2165 alias_explicit_as: false,
2166 alias_keyword: None,
2167 order_by: None,
2168 limit: None,
2169 offset: None,
2170 distribute_by: None,
2171 sort_by: None,
2172 cluster_by: None,
2173 lateral: false,
2174 modifiers_inside: false,
2175 trailing_comments: vec![],
2176 inferred_type: None,
2177 })),
2178 not: false,
2179 }));
2180
2181 extra_where_conditions.push(exists);
2182 }
2183 }
2184 JoinKind::Anti | JoinKind::LeftAnti => {
2185 if let Some(on_condition) = join.on {
2186 let subquery_select = Select {
2188 vertica: None,
2189 expressions: vec![Expression::Literal(Box::new(Literal::Number(
2190 "1".to_string(),
2191 )))],
2192 from: Some(From {
2193 expressions: vec![join.this],
2194 }),
2195 where_clause: Some(Where { this: on_condition }),
2196 ..Select::new()
2197 };
2198
2199 let not_exists = Expression::Exists(Box::new(Exists {
2201 this: Expression::Subquery(Box::new(Subquery {
2202 this: Expression::Select(Box::new(subquery_select)),
2203 alias: None,
2204 column_aliases: vec![],
2205 alias_explicit_as: false,
2206 alias_keyword: None,
2207 order_by: None,
2208 limit: None,
2209 offset: None,
2210 distribute_by: None,
2211 sort_by: None,
2212 cluster_by: None,
2213 lateral: false,
2214 modifiers_inside: false,
2215 trailing_comments: vec![],
2216 inferred_type: None,
2217 })),
2218 not: true,
2219 }));
2220
2221 extra_where_conditions.push(not_exists);
2222 }
2223 }
2224 _ => {
2225 new_joins.push(join);
2227 }
2228 }
2229 }
2230
2231 select.joins = new_joins;
2232
2233 if !extra_where_conditions.is_empty() {
2235 let combined = extra_where_conditions
2236 .into_iter()
2237 .reduce(|acc, cond| {
2238 Expression::And(Box::new(BinaryOp {
2239 left: acc,
2240 right: cond,
2241 left_comments: vec![],
2242 operator_comments: vec![],
2243 trailing_comments: vec![],
2244 inferred_type: None,
2245 }))
2246 })
2247 .unwrap();
2248
2249 select.where_clause = match select.where_clause {
2250 Some(Where { this: existing }) => Some(Where {
2251 this: Expression::And(Box::new(BinaryOp {
2252 left: existing,
2253 right: combined,
2254 left_comments: vec![],
2255 operator_comments: vec![],
2256 trailing_comments: vec![],
2257 inferred_type: None,
2258 })),
2259 }),
2260 None => Some(Where { this: combined }),
2261 };
2262 }
2263
2264 Ok(Expression::Select(select))
2265 }
2266 other => Ok(other),
2267 }
2268}
2269
2270pub fn eliminate_full_outer_join(expr: Expression) -> Result<Expression> {
2288 match expr {
2289 Expression::Select(mut select) => {
2290 let full_outer_join_idx = select.joins.iter().position(|j| j.kind == JoinKind::Full);
2292
2293 if let Some(idx) = full_outer_join_idx {
2294 let full_join_count = select
2296 .joins
2297 .iter()
2298 .filter(|j| j.kind == JoinKind::Full)
2299 .count();
2300 if full_join_count != 1 {
2301 return Ok(Expression::Select(select));
2302 }
2303
2304 let mut right_select = select.clone();
2306
2307 let full_join = &select.joins[idx];
2309 let join_condition = full_join.on.clone();
2310
2311 select.joins[idx].kind = JoinKind::Left;
2313
2314 right_select.joins[idx].kind = JoinKind::Right;
2316
2317 if let (Some(ref from), Some(ref join_cond)) = (&select.from, &join_condition) {
2319 if !from.expressions.is_empty() {
2320 let anti_subquery = Expression::Select(Box::new(Select {
2321 vertica: None,
2322 expressions: vec![Expression::Literal(Box::new(Literal::Number(
2323 "1".to_string(),
2324 )))],
2325 from: Some(from.clone()),
2326 where_clause: Some(Where {
2327 this: join_cond.clone(),
2328 }),
2329 ..Select::new()
2330 }));
2331
2332 let not_exists = Expression::Not(Box::new(crate::expressions::UnaryOp {
2333 inferred_type: None,
2334 this: Expression::Exists(Box::new(Exists {
2335 this: Expression::Subquery(Box::new(Subquery {
2336 this: anti_subquery,
2337 alias: None,
2338 column_aliases: vec![],
2339 alias_explicit_as: false,
2340 alias_keyword: None,
2341 order_by: None,
2342 limit: None,
2343 offset: None,
2344 distribute_by: None,
2345 sort_by: None,
2346 cluster_by: None,
2347 lateral: false,
2348 modifiers_inside: false,
2349 trailing_comments: vec![],
2350 inferred_type: None,
2351 })),
2352 not: false,
2353 })),
2354 }));
2355
2356 right_select.where_clause = Some(Where {
2358 this: match right_select.where_clause {
2359 Some(w) => Expression::And(Box::new(BinaryOp {
2360 left: w.this,
2361 right: not_exists,
2362 left_comments: vec![],
2363 operator_comments: vec![],
2364 trailing_comments: vec![],
2365 inferred_type: None,
2366 })),
2367 None => not_exists,
2368 },
2369 });
2370 }
2371 }
2372
2373 right_select.with = None;
2375
2376 let order_by = select.order_by.take();
2378
2379 let union = crate::expressions::Union {
2381 left: Expression::Select(select),
2382 right: Expression::Select(right_select),
2383 all: true, distinct: false,
2385 with: None,
2386 order_by,
2387 limit: None,
2388 offset: None,
2389 distribute_by: None,
2390 sort_by: None,
2391 cluster_by: None,
2392 by_name: false,
2393 side: None,
2394 kind: None,
2395 corresponding: false,
2396 strict: false,
2397 on_columns: Vec::new(),
2398 };
2399
2400 return Ok(Expression::Union(Box::new(union)));
2401 }
2402
2403 Ok(Expression::Select(select))
2404 }
2405 other => Ok(other),
2406 }
2407}
2408
2409pub fn move_ctes_to_top_level(expr: Expression) -> Result<Expression> {
2422 match expr {
2423 Expression::Select(mut select) => {
2424 let mut collected_ctes: Vec<crate::expressions::Cte> = Vec::new();
2426 let mut has_recursive = false;
2427
2428 collect_nested_ctes(
2429 &Expression::Select(select.clone()),
2430 &mut collected_ctes,
2431 &mut has_recursive,
2432 true,
2433 );
2434
2435 let mut cte_body_collected: Vec<(String, Vec<crate::expressions::Cte>)> = Vec::new();
2438 if let Some(ref with) = select.with {
2439 for cte in &with.ctes {
2440 let mut body_ctes: Vec<crate::expressions::Cte> = Vec::new();
2441 collect_ctes_from_cte_body(&cte.this, &mut body_ctes, &mut has_recursive);
2442 if !body_ctes.is_empty() {
2443 cte_body_collected.push((cte.alias.name.clone(), body_ctes));
2444 }
2445 }
2446 }
2447
2448 let has_subquery_ctes = !collected_ctes.is_empty();
2449 let has_body_ctes = !cte_body_collected.is_empty();
2450
2451 if has_subquery_ctes || has_body_ctes {
2452 strip_nested_with_clauses(&mut select, true);
2454
2455 if has_body_ctes {
2457 if let Some(ref mut with) = select.with {
2458 for cte in with.ctes.iter_mut() {
2459 strip_with_from_cte_body(&mut cte.this);
2460 }
2461 }
2462 }
2463
2464 let top_with = select.with.get_or_insert_with(|| crate::expressions::With {
2465 ctes: Vec::new(),
2466 recursive: false,
2467 leading_comments: vec![],
2468 search: None,
2469 });
2470
2471 if has_recursive {
2472 top_with.recursive = true;
2473 }
2474
2475 if has_body_ctes {
2477 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
2478 for mut cte in top_with.ctes.drain(..) {
2479 if let Some(pos) = cte_body_collected
2481 .iter()
2482 .position(|(name, _)| *name == cte.alias.name)
2483 {
2484 let (_, mut nested) = cte_body_collected.remove(pos);
2485 for nested_cte in nested.iter_mut() {
2487 strip_with_from_cte_body(&mut nested_cte.this);
2488 }
2489 new_ctes.extend(nested);
2490 }
2491 strip_with_from_cte_body(&mut cte.this);
2493 new_ctes.push(cte);
2494 }
2495 top_with.ctes = new_ctes;
2496 }
2497
2498 top_with.ctes.extend(collected_ctes);
2500 }
2501
2502 Ok(Expression::Select(select))
2503 }
2504 other => Ok(other),
2505 }
2506}
2507
2508fn collect_ctes_from_cte_body(
2510 expr: &Expression,
2511 collected: &mut Vec<crate::expressions::Cte>,
2512 has_recursive: &mut bool,
2513) {
2514 if let Expression::Select(select) = expr {
2515 if let Some(ref with) = select.with {
2516 if with.recursive {
2517 *has_recursive = true;
2518 }
2519 for cte in &with.ctes {
2520 collect_ctes_from_cte_body(&cte.this, collected, has_recursive);
2522 collected.push(cte.clone());
2524 }
2525 }
2526 }
2527}
2528
2529fn strip_with_from_cte_body(expr: &mut Expression) {
2531 if let Expression::Select(ref mut select) = expr {
2532 select.with = None;
2533 }
2534}
2535
2536fn strip_nested_with_clauses(select: &mut Select, _is_top_level: bool) {
2538 if let Some(ref mut from) = select.from {
2540 for expr in from.expressions.iter_mut() {
2541 strip_with_from_expr(expr);
2542 }
2543 }
2544 for join in select.joins.iter_mut() {
2546 strip_with_from_expr(&mut join.this);
2547 }
2548 for expr in select.expressions.iter_mut() {
2550 strip_with_from_expr(expr);
2551 }
2552 if let Some(ref mut w) = select.where_clause {
2554 strip_with_from_expr(&mut w.this);
2555 }
2556}
2557
2558fn strip_with_from_expr(expr: &mut Expression) {
2559 match expr {
2560 Expression::Subquery(ref mut subquery) => {
2561 strip_with_from_inner_query(&mut subquery.this);
2562 }
2563 Expression::Alias(ref mut alias) => {
2564 strip_with_from_expr(&mut alias.this);
2565 }
2566 Expression::Select(ref mut select) => {
2567 select.with = None;
2569 strip_nested_with_clauses(select, false);
2571 }
2572 _ => {}
2573 }
2574}
2575
2576fn strip_with_from_inner_query(expr: &mut Expression) {
2577 if let Expression::Select(ref mut select) = expr {
2578 select.with = None;
2579 strip_nested_with_clauses(select, false);
2580 }
2581}
2582
2583fn collect_nested_ctes(
2585 expr: &Expression,
2586 collected: &mut Vec<crate::expressions::Cte>,
2587 has_recursive: &mut bool,
2588 is_top_level: bool,
2589) {
2590 match expr {
2591 Expression::Select(select) => {
2592 if !is_top_level {
2594 if let Some(ref with) = select.with {
2595 if with.recursive {
2596 *has_recursive = true;
2597 }
2598 collected.extend(with.ctes.clone());
2599 }
2600 }
2601
2602 if let Some(ref from) = select.from {
2604 for expr in &from.expressions {
2605 collect_nested_ctes(expr, collected, has_recursive, false);
2606 }
2607 }
2608
2609 for join in &select.joins {
2611 collect_nested_ctes(&join.this, collected, has_recursive, false);
2612 }
2613
2614 for sel_expr in &select.expressions {
2616 collect_nested_ctes(sel_expr, collected, has_recursive, false);
2617 }
2618
2619 if let Some(ref where_clause) = select.where_clause {
2621 collect_nested_ctes(&where_clause.this, collected, has_recursive, false);
2622 }
2623 }
2624 Expression::Subquery(subquery) => {
2625 collect_nested_ctes(&subquery.this, collected, has_recursive, false);
2627 }
2628 Expression::Alias(alias) => {
2629 collect_nested_ctes(&alias.this, collected, has_recursive, false);
2630 }
2631 _ => {}
2633 }
2634}
2635
2636pub fn eliminate_window_clause(expr: Expression) -> Result<Expression> {
2652 match expr {
2653 Expression::Select(mut select) => {
2654 if let Some(named_windows) = select.windows.take() {
2655 let window_map: std::collections::HashMap<String, &Over> = named_windows
2657 .iter()
2658 .map(|nw| (nw.name.name.to_lowercase(), &nw.spec))
2659 .collect();
2660
2661 select.expressions = select
2663 .expressions
2664 .into_iter()
2665 .map(|e| inline_window_refs(e, &window_map))
2666 .collect();
2667 }
2668 Ok(Expression::Select(select))
2669 }
2670 other => Ok(other),
2671 }
2672}
2673
2674fn inline_window_refs(
2676 expr: Expression,
2677 window_map: &std::collections::HashMap<String, &Over>,
2678) -> Expression {
2679 match expr {
2680 Expression::WindowFunction(mut wf) => {
2681 if let Some(ref name) = wf.over.window_name {
2683 let key = name.name.to_lowercase();
2684 if let Some(named_spec) = window_map.get(&key) {
2685 if wf.over.partition_by.is_empty() && !named_spec.partition_by.is_empty() {
2687 wf.over.partition_by = named_spec.partition_by.clone();
2688 }
2689 if wf.over.order_by.is_empty() && !named_spec.order_by.is_empty() {
2690 wf.over.order_by = named_spec.order_by.clone();
2691 }
2692 if wf.over.frame.is_none() && named_spec.frame.is_some() {
2693 wf.over.frame = named_spec.frame.clone();
2694 }
2695 wf.over.window_name = None;
2697 }
2698 }
2699 Expression::WindowFunction(wf)
2700 }
2701 Expression::Alias(mut alias) => {
2702 alias.this = inline_window_refs(alias.this, window_map);
2704 Expression::Alias(alias)
2705 }
2706 other => other,
2709 }
2710}
2711
2712pub fn eliminate_join_marks(expr: Expression) -> Result<Expression> {
2726 match expr {
2727 Expression::Select(mut select) => {
2728 let has_join_marks = select
2730 .where_clause
2731 .as_ref()
2732 .map_or(false, |w| contains_join_mark(&w.this));
2733
2734 if !has_join_marks {
2735 return Ok(Expression::Select(select));
2736 }
2737
2738 let from_tables: Vec<String> = select
2740 .from
2741 .as_ref()
2742 .map(|f| {
2743 f.expressions
2744 .iter()
2745 .filter_map(|e| get_table_name(e))
2746 .collect()
2747 })
2748 .unwrap_or_default();
2749
2750 let mut join_conditions: std::collections::HashMap<String, Vec<Expression>> =
2752 std::collections::HashMap::new();
2753 let mut remaining_conditions: Vec<Expression> = Vec::new();
2754
2755 if let Some(ref where_clause) = select.where_clause {
2756 extract_join_mark_conditions(
2757 &where_clause.this,
2758 &mut join_conditions,
2759 &mut remaining_conditions,
2760 );
2761 }
2762
2763 let mut new_joins = select.joins.clone();
2765 for (table_name, conditions) in join_conditions {
2766 let table_in_from = from_tables.contains(&table_name);
2768
2769 if table_in_from && !conditions.is_empty() {
2770 let combined_condition = conditions.into_iter().reduce(|a, b| {
2772 Expression::And(Box::new(BinaryOp {
2773 left: a,
2774 right: b,
2775 left_comments: vec![],
2776 operator_comments: vec![],
2777 trailing_comments: vec![],
2778 inferred_type: None,
2779 }))
2780 });
2781
2782 if let Some(ref mut from) = select.from {
2784 if let Some(pos) = from
2785 .expressions
2786 .iter()
2787 .position(|e| get_table_name(e).map_or(false, |n| n == table_name))
2788 {
2789 if from.expressions.len() > 1 {
2790 let join_table = from.expressions.remove(pos);
2791 new_joins.push(crate::expressions::Join {
2792 this: join_table,
2793 kind: JoinKind::Left,
2794 on: combined_condition,
2795 using: vec![],
2796 use_inner_keyword: false,
2797 use_outer_keyword: true,
2798 deferred_condition: false,
2799 join_hint: None,
2800 match_condition: None,
2801 pivots: Vec::new(),
2802 comments: Vec::new(),
2803 nesting_group: 0,
2804 directed: false,
2805 });
2806 }
2807 }
2808 }
2809 }
2810 }
2811
2812 select.joins = new_joins;
2813
2814 if remaining_conditions.is_empty() {
2816 select.where_clause = None;
2817 } else {
2818 let combined = remaining_conditions.into_iter().reduce(|a, b| {
2819 Expression::And(Box::new(BinaryOp {
2820 left: a,
2821 right: b,
2822 left_comments: vec![],
2823 operator_comments: vec![],
2824 trailing_comments: vec![],
2825 inferred_type: None,
2826 }))
2827 });
2828 select.where_clause = combined.map(|c| Where { this: c });
2829 }
2830
2831 clear_join_marks(&mut Expression::Select(select.clone()));
2833
2834 Ok(Expression::Select(select))
2835 }
2836 other => Ok(other),
2837 }
2838}
2839
2840fn contains_join_mark(expr: &Expression) -> bool {
2842 match expr {
2843 Expression::Column(col) => col.join_mark,
2844 Expression::And(op) | Expression::Or(op) => {
2845 contains_join_mark(&op.left) || contains_join_mark(&op.right)
2846 }
2847 Expression::Eq(op)
2848 | Expression::Neq(op)
2849 | Expression::Lt(op)
2850 | Expression::Lte(op)
2851 | Expression::Gt(op)
2852 | Expression::Gte(op) => contains_join_mark(&op.left) || contains_join_mark(&op.right),
2853 Expression::Not(op) => contains_join_mark(&op.this),
2854 _ => false,
2855 }
2856}
2857
2858fn get_table_name(expr: &Expression) -> Option<String> {
2860 match expr {
2861 Expression::Table(t) => Some(t.name.name.clone()),
2862 Expression::Alias(a) => Some(a.alias.name.clone()),
2863 _ => None,
2864 }
2865}
2866
2867fn extract_join_mark_conditions(
2869 expr: &Expression,
2870 join_conditions: &mut std::collections::HashMap<String, Vec<Expression>>,
2871 remaining: &mut Vec<Expression>,
2872) {
2873 match expr {
2874 Expression::And(op) => {
2875 extract_join_mark_conditions(&op.left, join_conditions, remaining);
2876 extract_join_mark_conditions(&op.right, join_conditions, remaining);
2877 }
2878 _ => {
2879 if let Some(table) = get_join_mark_table(expr) {
2880 join_conditions
2881 .entry(table)
2882 .or_insert_with(Vec::new)
2883 .push(expr.clone());
2884 } else {
2885 remaining.push(expr.clone());
2886 }
2887 }
2888 }
2889}
2890
2891fn get_join_mark_table(expr: &Expression) -> Option<String> {
2893 match expr {
2894 Expression::Eq(op)
2895 | Expression::Neq(op)
2896 | Expression::Lt(op)
2897 | Expression::Lte(op)
2898 | Expression::Gt(op)
2899 | Expression::Gte(op) => {
2900 if let Expression::Column(col) = &op.left {
2902 if col.join_mark {
2903 return col.table.as_ref().map(|t| t.name.clone());
2904 }
2905 }
2906 if let Expression::Column(col) = &op.right {
2907 if col.join_mark {
2908 return col.table.as_ref().map(|t| t.name.clone());
2909 }
2910 }
2911 None
2912 }
2913 _ => None,
2914 }
2915}
2916
2917fn clear_join_marks(expr: &mut Expression) {
2919 match expr {
2920 Expression::Column(col) => col.join_mark = false,
2921 Expression::Select(select) => {
2922 if let Some(ref mut w) = select.where_clause {
2923 clear_join_marks(&mut w.this);
2924 }
2925 for sel_expr in &mut select.expressions {
2926 clear_join_marks(sel_expr);
2927 }
2928 }
2929 Expression::And(op) | Expression::Or(op) => {
2930 clear_join_marks(&mut op.left);
2931 clear_join_marks(&mut op.right);
2932 }
2933 Expression::Eq(op)
2934 | Expression::Neq(op)
2935 | Expression::Lt(op)
2936 | Expression::Lte(op)
2937 | Expression::Gt(op)
2938 | Expression::Gte(op) => {
2939 clear_join_marks(&mut op.left);
2940 clear_join_marks(&mut op.right);
2941 }
2942 _ => {}
2943 }
2944}
2945
2946pub fn add_recursive_cte_column_names(expr: Expression) -> Result<Expression> {
2953 match expr {
2954 Expression::Select(mut select) => {
2955 if let Some(ref mut with) = select.with {
2956 if with.recursive {
2957 let mut counter = 0;
2958 for cte in &mut with.ctes {
2959 if cte.columns.is_empty() {
2960 if let Expression::Select(ref cte_select) = cte.this {
2962 let names: Vec<Identifier> = cte_select
2963 .expressions
2964 .iter()
2965 .map(|e| match e {
2966 Expression::Alias(a) => a.alias.clone(),
2967 Expression::Column(c) => c.name.clone(),
2968 _ => {
2969 counter += 1;
2970 Identifier::new(format!("_c_{}", counter))
2971 }
2972 })
2973 .collect();
2974 cte.columns = names;
2975 }
2976 }
2977 }
2978 }
2979 }
2980 Ok(Expression::Select(select))
2981 }
2982 other => Ok(other),
2983 }
2984}
2985
2986pub fn epoch_cast_to_ts(expr: Expression) -> Result<Expression> {
2993 match expr {
2994 Expression::Cast(mut cast) => {
2995 if let Expression::Literal(ref lit) = cast.this {
2996 if let Literal::String(ref s) = lit.as_ref() {
2997 if s.to_lowercase() == "epoch" {
2998 if is_temporal_type(&cast.to) {
2999 cast.this = Expression::Literal(Box::new(Literal::String(
3000 "1970-01-01 00:00:00".to_string(),
3001 )));
3002 }
3003 }
3004 }
3005 }
3006 Ok(Expression::Cast(cast))
3007 }
3008 Expression::TryCast(mut try_cast) => {
3009 if let Expression::Literal(ref lit) = try_cast.this {
3010 if let Literal::String(ref s) = lit.as_ref() {
3011 if s.to_lowercase() == "epoch" {
3012 if is_temporal_type(&try_cast.to) {
3013 try_cast.this = Expression::Literal(Box::new(Literal::String(
3014 "1970-01-01 00:00:00".to_string(),
3015 )));
3016 }
3017 }
3018 }
3019 }
3020 Ok(Expression::TryCast(try_cast))
3021 }
3022 other => Ok(other),
3023 }
3024}
3025
3026fn is_temporal_type(dt: &DataType) -> bool {
3028 matches!(
3029 dt,
3030 DataType::Date | DataType::Timestamp { .. } | DataType::Time { .. }
3031 )
3032}
3033
3034pub fn ensure_bools(expr: Expression) -> Result<Expression> {
3059 let expr = ensure_bools_in_value_context(expr);
3060
3061 Ok(match expr {
3062 Expression::And(_) | Expression::Or(_) | Expression::Not(_) => ensure_bool_condition(expr),
3064 other => other,
3065 })
3066}
3067
3068fn ensure_bools_in_value_context(expr: Expression) -> Expression {
3072 match expr {
3073 Expression::Case(mut case) => {
3074 let is_simple_case = case.operand.is_some();
3075 if let Some(operand) = case.operand.take() {
3076 case.operand = Some(ensure_bools_in_value_context(operand));
3077 }
3078 case.whens = case
3079 .whens
3080 .into_iter()
3081 .map(|(condition, result)| {
3082 let new_condition = if is_simple_case {
3083 ensure_bools_in_value_context(condition)
3084 } else {
3085 ensure_bool_condition(ensure_bools_in_value_context(condition))
3086 };
3087 let new_result = ensure_bools_in_value_context(result);
3088 (new_condition, new_result)
3089 })
3090 .collect();
3091 if let Some(else_expr) = case.else_ {
3092 case.else_ = Some(ensure_bools_in_value_context(else_expr));
3093 }
3094 Expression::Case(Box::new(*case))
3095 }
3096 Expression::Select(select) => Expression::Select(Box::new(ensure_bools_in_select(*select))),
3097 Expression::Subquery(mut subquery) => {
3098 subquery.this = ensure_bools_in_value_context(subquery.this);
3099 Expression::Subquery(subquery)
3100 }
3101 Expression::JoinedTable(mut joined_table) => {
3102 joined_table.left = ensure_bools_in_value_context(joined_table.left);
3103 joined_table.joins = joined_table
3104 .joins
3105 .into_iter()
3106 .map(ensure_bools_in_join)
3107 .collect();
3108 joined_table.lateral_views = joined_table
3109 .lateral_views
3110 .into_iter()
3111 .map(|mut lateral_view| {
3112 lateral_view.this = ensure_bools_in_value_context(lateral_view.this);
3113 lateral_view
3114 })
3115 .collect();
3116 Expression::JoinedTable(joined_table)
3117 }
3118 Expression::Union(mut union) => {
3119 let left = std::mem::replace(&mut union.left, Expression::null());
3120 let right = std::mem::replace(&mut union.right, Expression::null());
3121 union.left = ensure_bools_in_value_context(left);
3122 union.right = ensure_bools_in_value_context(right);
3123 if let Some(with) = union.with.take() {
3124 union.with = Some(ensure_bools_in_with(with));
3125 }
3126 Expression::Union(union)
3127 }
3128 Expression::Intersect(mut intersect) => {
3129 let left = std::mem::replace(&mut intersect.left, Expression::null());
3130 let right = std::mem::replace(&mut intersect.right, Expression::null());
3131 intersect.left = ensure_bools_in_value_context(left);
3132 intersect.right = ensure_bools_in_value_context(right);
3133 if let Some(with) = intersect.with.take() {
3134 intersect.with = Some(ensure_bools_in_with(with));
3135 }
3136 Expression::Intersect(intersect)
3137 }
3138 Expression::Except(mut except) => {
3139 let left = std::mem::replace(&mut except.left, Expression::null());
3140 let right = std::mem::replace(&mut except.right, Expression::null());
3141 except.left = ensure_bools_in_value_context(left);
3142 except.right = ensure_bools_in_value_context(right);
3143 if let Some(with) = except.with.take() {
3144 except.with = Some(ensure_bools_in_with(with));
3145 }
3146 Expression::Except(except)
3147 }
3148 Expression::Alias(mut alias) => {
3149 alias.this = ensure_bools_in_value_context(alias.this);
3150 Expression::Alias(alias)
3151 }
3152 Expression::Paren(mut paren) => {
3153 paren.this = ensure_bools_in_value_context(paren.this);
3154 Expression::Paren(paren)
3155 }
3156 other => other,
3157 }
3158}
3159
3160fn ensure_bools_in_select(mut select: Select) -> Select {
3161 select.expressions = select
3162 .expressions
3163 .into_iter()
3164 .map(ensure_bools_in_value_context)
3165 .collect();
3166
3167 if let Some(from) = select.from.take() {
3168 select.from = Some(crate::expressions::From {
3169 expressions: from
3170 .expressions
3171 .into_iter()
3172 .map(ensure_bools_in_value_context)
3173 .collect(),
3174 });
3175 }
3176
3177 select.joins = select.joins.into_iter().map(ensure_bools_in_join).collect();
3178
3179 if let Some(mut where_clause) = select.where_clause.take() {
3180 where_clause.this = ensure_bool_condition(ensure_bools_in_value_context(where_clause.this));
3181 select.where_clause = Some(where_clause);
3182 }
3183
3184 if let Some(mut having) = select.having.take() {
3185 having.this = ensure_bool_condition(ensure_bools_in_value_context(having.this));
3186 select.having = Some(having);
3187 }
3188
3189 if let Some(with) = select.with.take() {
3190 select.with = Some(ensure_bools_in_with(with));
3191 }
3192
3193 select
3194}
3195
3196fn ensure_bools_in_join(mut join: Join) -> Join {
3197 join.this = ensure_bools_in_value_context(join.this);
3198
3199 if let Some(on) = join.on.take() {
3200 join.on = Some(ensure_bool_condition(ensure_bools_in_value_context(on)));
3201 }
3202
3203 if let Some(match_condition) = join.match_condition.take() {
3204 join.match_condition = Some(ensure_bool_condition(ensure_bools_in_value_context(
3205 match_condition,
3206 )));
3207 }
3208
3209 join.pivots = join
3210 .pivots
3211 .into_iter()
3212 .map(ensure_bools_in_value_context)
3213 .collect();
3214
3215 join
3216}
3217
3218fn ensure_bools_in_with(mut with: With) -> With {
3219 with.ctes = with
3220 .ctes
3221 .into_iter()
3222 .map(|mut cte| {
3223 cte.this = ensure_bools_in_value_context(cte.this);
3224 cte
3225 })
3226 .collect();
3227 with
3228}
3229
3230fn is_boolean_expression(expr: &Expression) -> bool {
3233 matches!(
3234 expr,
3235 Expression::Eq(_)
3236 | Expression::Neq(_)
3237 | Expression::Lt(_)
3238 | Expression::Lte(_)
3239 | Expression::Gt(_)
3240 | Expression::Gte(_)
3241 | Expression::Is(_)
3242 | Expression::IsNull(_)
3243 | Expression::IsTrue(_)
3244 | Expression::IsFalse(_)
3245 | Expression::Like(_)
3246 | Expression::ILike(_)
3247 | Expression::StartsWith(_)
3248 | Expression::SimilarTo(_)
3249 | Expression::Glob(_)
3250 | Expression::RegexpLike(_)
3251 | Expression::In(_)
3252 | Expression::Between(_)
3253 | Expression::Exists(_)
3254 | Expression::And(_)
3255 | Expression::Or(_)
3256 | Expression::Not(_)
3257 | Expression::Any(_)
3258 | Expression::All(_)
3259 | Expression::NullSafeEq(_)
3260 | Expression::NullSafeNeq(_)
3261 | Expression::EqualNull(_)
3262 )
3263}
3264
3265fn wrap_neq_zero(expr: Expression) -> Expression {
3267 Expression::Neq(Box::new(BinaryOp {
3268 left: expr,
3269 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
3270 left_comments: vec![],
3271 operator_comments: vec![],
3272 trailing_comments: vec![],
3273 inferred_type: None,
3274 }))
3275}
3276
3277pub(crate) fn ensure_bool_condition(expr: Expression) -> Expression {
3283 match expr {
3284 Expression::And(op) => {
3286 let new_op = BinaryOp {
3287 left: ensure_bool_condition(op.left.clone()),
3288 right: ensure_bool_condition(op.right.clone()),
3289 left_comments: op.left_comments.clone(),
3290 operator_comments: op.operator_comments.clone(),
3291 trailing_comments: op.trailing_comments.clone(),
3292 inferred_type: None,
3293 };
3294 Expression::And(Box::new(new_op))
3295 }
3296 Expression::Or(op) => {
3297 let new_op = BinaryOp {
3298 left: ensure_bool_condition(op.left.clone()),
3299 right: ensure_bool_condition(op.right.clone()),
3300 left_comments: op.left_comments.clone(),
3301 operator_comments: op.operator_comments.clone(),
3302 trailing_comments: op.trailing_comments.clone(),
3303 inferred_type: None,
3304 };
3305 Expression::Or(Box::new(new_op))
3306 }
3307 Expression::Not(op) => Expression::Not(Box::new(crate::expressions::UnaryOp {
3309 this: ensure_bool_condition(op.this.clone()),
3310 inferred_type: None,
3311 })),
3312 Expression::Paren(paren) => Expression::Paren(Box::new(crate::expressions::Paren {
3314 this: ensure_bool_condition(paren.this.clone()),
3315 trailing_comments: paren.trailing_comments.clone(),
3316 })),
3317 Expression::Boolean(BooleanLiteral { value: true }) => {
3319 Expression::Paren(Box::new(crate::expressions::Paren {
3320 this: Expression::Eq(Box::new(BinaryOp {
3321 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3322 right: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3323 left_comments: vec![],
3324 operator_comments: vec![],
3325 trailing_comments: vec![],
3326 inferred_type: None,
3327 })),
3328 trailing_comments: vec![],
3329 }))
3330 }
3331 Expression::Boolean(BooleanLiteral { value: false }) => {
3332 Expression::Paren(Box::new(crate::expressions::Paren {
3333 this: Expression::Eq(Box::new(BinaryOp {
3334 left: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3335 right: Expression::Literal(Box::new(Literal::Number("0".to_string()))),
3336 left_comments: vec![],
3337 operator_comments: vec![],
3338 trailing_comments: vec![],
3339 inferred_type: None,
3340 })),
3341 trailing_comments: vec![],
3342 }))
3343 }
3344 ref e if is_boolean_expression(e) => expr,
3346 _ => wrap_neq_zero(expr),
3349 }
3350}
3351
3352pub fn unqualify_columns(expr: Expression) -> Result<Expression> {
3358 Ok(unqualify_columns_recursive(expr))
3359}
3360
3361fn unqualify_columns_recursive(expr: Expression) -> Expression {
3363 match expr {
3364 Expression::Column(mut col) => {
3365 col.table = None;
3366 Expression::Column(col)
3367 }
3368 Expression::Select(mut select) => {
3369 select.expressions = select
3370 .expressions
3371 .into_iter()
3372 .map(unqualify_columns_recursive)
3373 .collect();
3374 if let Some(ref mut where_clause) = select.where_clause {
3375 where_clause.this = unqualify_columns_recursive(where_clause.this.clone());
3376 }
3377 if let Some(ref mut having) = select.having {
3378 having.this = unqualify_columns_recursive(having.this.clone());
3379 }
3380 if let Some(ref mut group_by) = select.group_by {
3381 group_by.expressions = group_by
3382 .expressions
3383 .iter()
3384 .cloned()
3385 .map(unqualify_columns_recursive)
3386 .collect();
3387 }
3388 if let Some(ref mut order_by) = select.order_by {
3389 order_by.expressions = order_by
3390 .expressions
3391 .iter()
3392 .map(|o| crate::expressions::Ordered {
3393 nulls_auto: o.nulls_auto,
3394 this: unqualify_columns_recursive(o.this.clone()),
3395 desc: o.desc,
3396 nulls_first: o.nulls_first,
3397 explicit_asc: o.explicit_asc,
3398 with_fill: o.with_fill.clone(),
3399 })
3400 .collect();
3401 }
3402 for join in &mut select.joins {
3403 if let Some(ref mut on) = join.on {
3404 *on = unqualify_columns_recursive(on.clone());
3405 }
3406 }
3407 Expression::Select(select)
3408 }
3409 Expression::Alias(mut alias) => {
3410 alias.this = unqualify_columns_recursive(alias.this);
3411 Expression::Alias(alias)
3412 }
3413 Expression::And(op) => Expression::And(Box::new(unqualify_binary_op(*op))),
3415 Expression::Or(op) => Expression::Or(Box::new(unqualify_binary_op(*op))),
3416 Expression::Eq(op) => Expression::Eq(Box::new(unqualify_binary_op(*op))),
3417 Expression::Neq(op) => Expression::Neq(Box::new(unqualify_binary_op(*op))),
3418 Expression::Lt(op) => Expression::Lt(Box::new(unqualify_binary_op(*op))),
3419 Expression::Lte(op) => Expression::Lte(Box::new(unqualify_binary_op(*op))),
3420 Expression::Gt(op) => Expression::Gt(Box::new(unqualify_binary_op(*op))),
3421 Expression::Gte(op) => Expression::Gte(Box::new(unqualify_binary_op(*op))),
3422 Expression::Add(op) => Expression::Add(Box::new(unqualify_binary_op(*op))),
3423 Expression::Sub(op) => Expression::Sub(Box::new(unqualify_binary_op(*op))),
3424 Expression::Mul(op) => Expression::Mul(Box::new(unqualify_binary_op(*op))),
3425 Expression::Div(op) => Expression::Div(Box::new(unqualify_binary_op(*op))),
3426 Expression::Function(mut func) => {
3428 func.args = func
3429 .args
3430 .into_iter()
3431 .map(unqualify_columns_recursive)
3432 .collect();
3433 Expression::Function(func)
3434 }
3435 Expression::AggregateFunction(mut func) => {
3436 func.args = func
3437 .args
3438 .into_iter()
3439 .map(unqualify_columns_recursive)
3440 .collect();
3441 Expression::AggregateFunction(func)
3442 }
3443 Expression::Case(mut case) => {
3444 case.whens = case
3445 .whens
3446 .into_iter()
3447 .map(|(cond, result)| {
3448 (
3449 unqualify_columns_recursive(cond),
3450 unqualify_columns_recursive(result),
3451 )
3452 })
3453 .collect();
3454 if let Some(else_expr) = case.else_ {
3455 case.else_ = Some(unqualify_columns_recursive(else_expr));
3456 }
3457 Expression::Case(case)
3458 }
3459 other => other,
3461 }
3462}
3463
3464fn unqualify_binary_op(mut op: BinaryOp) -> BinaryOp {
3466 op.left = unqualify_columns_recursive(op.left);
3467 op.right = unqualify_columns_recursive(op.right);
3468 op
3469}
3470
3471pub fn unnest_generate_date_array_using_recursive_cte(expr: Expression) -> Result<Expression> {
3491 match expr {
3492 Expression::Select(mut select) => {
3493 let mut cte_count = 0;
3494 let mut new_ctes: Vec<crate::expressions::Cte> = Vec::new();
3495
3496 if let Some(ref mut with) = select.with {
3498 for cte in &mut with.ctes {
3499 process_expression_for_gda(&mut cte.this, &mut cte_count, &mut new_ctes);
3500 }
3501 }
3502
3503 if let Some(ref mut from) = select.from {
3505 for table_expr in &mut from.expressions {
3506 if let Some((cte, replacement)) =
3507 try_convert_generate_date_array(table_expr, &mut cte_count)
3508 {
3509 new_ctes.push(cte);
3510 *table_expr = replacement;
3511 }
3512 }
3513 }
3514
3515 for join in &mut select.joins {
3517 if let Some((cte, replacement)) =
3518 try_convert_generate_date_array(&join.this, &mut cte_count)
3519 {
3520 new_ctes.push(cte);
3521 join.this = replacement;
3522 }
3523 }
3524
3525 if !new_ctes.is_empty() {
3527 let with_clause = select.with.get_or_insert_with(|| crate::expressions::With {
3528 ctes: Vec::new(),
3529 recursive: true, leading_comments: vec![],
3531 search: None,
3532 });
3533 with_clause.recursive = true;
3534
3535 let mut all_ctes = new_ctes;
3537 all_ctes.append(&mut with_clause.ctes);
3538 with_clause.ctes = all_ctes;
3539 }
3540
3541 Ok(Expression::Select(select))
3542 }
3543 other => Ok(other),
3544 }
3545}
3546
3547fn process_expression_for_gda(
3550 expr: &mut Expression,
3551 cte_count: &mut usize,
3552 new_ctes: &mut Vec<crate::expressions::Cte>,
3553) {
3554 match expr {
3555 Expression::Select(ref mut select) => {
3556 if let Some(ref mut from) = select.from {
3558 for table_expr in &mut from.expressions {
3559 if let Some((cte, replacement)) =
3560 try_convert_generate_date_array(table_expr, cte_count)
3561 {
3562 new_ctes.push(cte);
3563 *table_expr = replacement;
3564 }
3565 }
3566 }
3567 for join in &mut select.joins {
3569 if let Some((cte, replacement)) =
3570 try_convert_generate_date_array(&join.this, cte_count)
3571 {
3572 new_ctes.push(cte);
3573 join.this = replacement;
3574 }
3575 }
3576 }
3577 Expression::Union(ref mut u) => {
3578 process_expression_for_gda(&mut u.left, cte_count, new_ctes);
3579 process_expression_for_gda(&mut u.right, cte_count, new_ctes);
3580 }
3581 Expression::Subquery(ref mut sq) => {
3582 process_expression_for_gda(&mut sq.this, cte_count, new_ctes);
3583 }
3584 _ => {}
3585 }
3586}
3587
3588fn try_convert_generate_date_array(
3591 expr: &Expression,
3592 cte_count: &mut usize,
3593) -> Option<(crate::expressions::Cte, Expression)> {
3594 try_convert_generate_date_array_with_name(expr, cte_count, None)
3595}
3596
3597fn try_convert_generate_date_array_with_name(
3598 expr: &Expression,
3599 cte_count: &mut usize,
3600 column_name_override: Option<&str>,
3601) -> Option<(crate::expressions::Cte, Expression)> {
3602 fn extract_gda_args(
3604 inner: &Expression,
3605 ) -> Option<(&Expression, &Expression, Option<&Expression>)> {
3606 match inner {
3607 Expression::GenerateDateArray(gda) => {
3608 let start = gda.start.as_ref()?;
3609 let end = gda.end.as_ref()?;
3610 let step = gda.step.as_deref();
3611 Some((start, end, step))
3612 }
3613 Expression::GenerateSeries(gs) => {
3614 let start = gs.start.as_deref()?;
3615 let end = gs.end.as_deref()?;
3616 let step = gs.step.as_deref();
3617 Some((start, end, step))
3618 }
3619 Expression::Function(f) if f.name.eq_ignore_ascii_case("GENERATE_DATE_ARRAY") => {
3620 if f.args.len() >= 2 {
3621 let start = &f.args[0];
3622 let end = &f.args[1];
3623 let step = f.args.get(2);
3624 Some((start, end, step))
3625 } else {
3626 None
3627 }
3628 }
3629 _ => None,
3630 }
3631 }
3632
3633 if let Expression::Unnest(unnest) = expr {
3635 if let Some((start, end, step_opt)) = extract_gda_args(&unnest.this) {
3636 let start = start;
3637 let end = end;
3638 let step: Option<&Expression> = step_opt;
3639
3640 let cte_name = if *cte_count == 0 {
3642 "_generated_dates".to_string()
3643 } else {
3644 format!("_generated_dates_{}", cte_count)
3645 };
3646 *cte_count += 1;
3647
3648 let column_name =
3649 Identifier::new(column_name_override.unwrap_or("date_value").to_string());
3650
3651 let cast_to_date = |expr: &Expression| -> Expression {
3653 match expr {
3654 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Date(_)) => {
3655 if let Expression::Literal(lit) = expr {
3657 if let Literal::Date(d) = lit.as_ref() {
3658 Expression::Cast(Box::new(Cast {
3659 this: Expression::Literal(Box::new(Literal::String(d.clone()))),
3660 to: DataType::Date,
3661 trailing_comments: vec![],
3662 double_colon_syntax: false,
3663 format: None,
3664 default: None,
3665 inferred_type: None,
3666 }))
3667 } else {
3668 expr.clone()
3669 }
3670 } else {
3671 unreachable!()
3672 }
3673 }
3674 Expression::Cast(c) if matches!(c.to, DataType::Date) => expr.clone(),
3675 _ => Expression::Cast(Box::new(Cast {
3676 this: expr.clone(),
3677 to: DataType::Date,
3678 trailing_comments: vec![],
3679 double_colon_syntax: false,
3680 format: None,
3681 default: None,
3682 inferred_type: None,
3683 })),
3684 }
3685 };
3686
3687 let base_select = Select {
3689 vertica: None,
3690 expressions: vec![Expression::Alias(Box::new(crate::expressions::Alias {
3691 this: cast_to_date(start),
3692 alias: column_name.clone(),
3693 column_aliases: vec![],
3694 alias_explicit_as: false,
3695 alias_keyword: None,
3696 pre_alias_comments: vec![],
3697 trailing_comments: vec![],
3698 inferred_type: None,
3699 }))],
3700 ..Select::new()
3701 };
3702
3703 let normalize_interval = |expr: &Expression| -> Expression {
3705 if let Expression::Interval(ref iv) = expr {
3706 let mut iv_clone = iv.as_ref().clone();
3707 if let Some(Expression::Literal(ref lit)) = iv_clone.this {
3708 if let Literal::String(ref s) = lit.as_ref() {
3709 if s.parse::<f64>().is_ok() {
3711 iv_clone.this =
3712 Some(Expression::Literal(Box::new(Literal::Number(s.clone()))));
3713 }
3714 }
3715 }
3716 Expression::Interval(Box::new(iv_clone))
3717 } else {
3718 expr.clone()
3719 }
3720 };
3721
3722 let normalized_step = step.map(|s| normalize_interval(s)).unwrap_or_else(|| {
3725 Expression::Interval(Box::new(crate::expressions::Interval {
3726 this: Some(Expression::Literal(Box::new(Literal::Number(
3727 "1".to_string(),
3728 )))),
3729 unit: Some(crate::expressions::IntervalUnitSpec::Simple {
3730 unit: crate::expressions::IntervalUnit::Day,
3731 use_plural: false,
3732 }),
3733 }))
3734 });
3735
3736 let (add_unit, add_count) = extract_interval_unit_and_count(&normalized_step);
3738
3739 let date_add_expr = Expression::DateAdd(Box::new(crate::expressions::DateAddFunc {
3740 this: Expression::Column(Box::new(crate::expressions::Column {
3741 name: column_name.clone(),
3742 table: None,
3743 join_mark: false,
3744 trailing_comments: vec![],
3745 span: None,
3746 inferred_type: None,
3747 })),
3748 interval: add_count,
3749 unit: add_unit,
3750 }));
3751
3752 let cast_date_add = Expression::Cast(Box::new(Cast {
3753 this: date_add_expr.clone(),
3754 to: DataType::Date,
3755 trailing_comments: vec![],
3756 double_colon_syntax: false,
3757 format: None,
3758 default: None,
3759 inferred_type: None,
3760 }));
3761
3762 let recursive_select = Select {
3763 vertica: None,
3764 expressions: vec![cast_date_add.clone()],
3765 from: Some(From {
3766 expressions: vec![Expression::Table(Box::new(
3767 crate::expressions::TableRef::new(&cte_name),
3768 ))],
3769 }),
3770 where_clause: Some(Where {
3771 this: Expression::Lte(Box::new(BinaryOp {
3772 left: cast_date_add,
3773 right: cast_to_date(end),
3774 left_comments: vec![],
3775 operator_comments: vec![],
3776 trailing_comments: vec![],
3777 inferred_type: None,
3778 })),
3779 }),
3780 ..Select::new()
3781 };
3782
3783 let union = crate::expressions::Union {
3785 left: Expression::Select(Box::new(base_select)),
3786 right: Expression::Select(Box::new(recursive_select)),
3787 all: true, distinct: false,
3789 with: None,
3790 order_by: None,
3791 limit: None,
3792 offset: None,
3793 distribute_by: None,
3794 sort_by: None,
3795 cluster_by: None,
3796 by_name: false,
3797 side: None,
3798 kind: None,
3799 corresponding: false,
3800 strict: false,
3801 on_columns: Vec::new(),
3802 };
3803
3804 let cte = crate::expressions::Cte {
3806 this: Expression::Union(Box::new(union)),
3807 alias: Identifier::new(cte_name.clone()),
3808 columns: vec![column_name.clone()],
3809 materialized: None,
3810 key_expressions: Vec::new(),
3811 alias_first: true,
3812 comments: Vec::new(),
3813 };
3814
3815 let replacement_select = Select {
3817 vertica: None,
3818 expressions: vec![Expression::Column(Box::new(crate::expressions::Column {
3819 name: column_name,
3820 table: None,
3821 join_mark: false,
3822 trailing_comments: vec![],
3823 span: None,
3824 inferred_type: None,
3825 }))],
3826 from: Some(From {
3827 expressions: vec![Expression::Table(Box::new(
3828 crate::expressions::TableRef::new(&cte_name),
3829 ))],
3830 }),
3831 ..Select::new()
3832 };
3833
3834 let replacement = Expression::Subquery(Box::new(Subquery {
3835 this: Expression::Select(Box::new(replacement_select)),
3836 alias: Some(Identifier::new(cte_name)),
3837 column_aliases: vec![],
3838 alias_explicit_as: false,
3839 alias_keyword: None,
3840 order_by: None,
3841 limit: None,
3842 offset: None,
3843 distribute_by: None,
3844 sort_by: None,
3845 cluster_by: None,
3846 lateral: false,
3847 modifiers_inside: false,
3848 trailing_comments: vec![],
3849 inferred_type: None,
3850 }));
3851
3852 return Some((cte, replacement));
3853 }
3854 }
3855
3856 if let Expression::Alias(alias) = expr {
3858 let col_name = alias.column_aliases.first().map(|id| id.name.as_str());
3860 if let Some((cte, replacement)) =
3861 try_convert_generate_date_array_with_name(&alias.this, cte_count, col_name)
3862 {
3863 if col_name.is_some() {
3866 return Some((cte, replacement));
3867 }
3868 let new_alias = Expression::Alias(Box::new(crate::expressions::Alias {
3869 this: replacement,
3870 alias: alias.alias.clone(),
3871 column_aliases: alias.column_aliases.clone(),
3872 alias_explicit_as: false,
3873 alias_keyword: None,
3874 pre_alias_comments: alias.pre_alias_comments.clone(),
3875 trailing_comments: alias.trailing_comments.clone(),
3876 inferred_type: None,
3877 }));
3878 return Some((cte, new_alias));
3879 }
3880 }
3881
3882 None
3883}
3884
3885fn extract_interval_unit_and_count(
3890 expr: &Expression,
3891) -> (crate::expressions::IntervalUnit, Expression) {
3892 use crate::expressions::{IntervalUnit, IntervalUnitSpec, Literal};
3893
3894 if let Expression::Interval(ref iv) = expr {
3895 if let Some(ref unit_spec) = iv.unit {
3897 if let IntervalUnitSpec::Simple { unit, .. } = unit_spec {
3898 let count = match &iv.this {
3899 Some(e) => e.clone(),
3900 None => Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3901 };
3902 return (unit.clone(), count);
3903 }
3904 }
3905
3906 if let Some(ref val_expr) = iv.this {
3908 match val_expr {
3909 Expression::Literal(lit)
3910 if matches!(lit.as_ref(), Literal::String(_) | Literal::Number(_)) =>
3911 {
3912 let s = match lit.as_ref() {
3913 Literal::String(s) | Literal::Number(s) => s,
3914 _ => unreachable!(),
3915 };
3916 let parts: Vec<&str> = s.trim().splitn(2, char::is_whitespace).collect();
3918 if parts.len() == 2 {
3919 let count_str = parts[0].trim();
3920 let unit_str = parts[1].trim().to_uppercase();
3921 let unit = match unit_str.as_str() {
3922 "YEAR" | "YEARS" => IntervalUnit::Year,
3923 "QUARTER" | "QUARTERS" => IntervalUnit::Quarter,
3924 "MONTH" | "MONTHS" => IntervalUnit::Month,
3925 "WEEK" | "WEEKS" => IntervalUnit::Week,
3926 "DAY" | "DAYS" => IntervalUnit::Day,
3927 "HOUR" | "HOURS" => IntervalUnit::Hour,
3928 "MINUTE" | "MINUTES" => IntervalUnit::Minute,
3929 "SECOND" | "SECONDS" => IntervalUnit::Second,
3930 "MILLISECOND" | "MILLISECONDS" => IntervalUnit::Millisecond,
3931 "MICROSECOND" | "MICROSECONDS" => IntervalUnit::Microsecond,
3932 _ => IntervalUnit::Day,
3933 };
3934 return (
3935 unit,
3936 Expression::Literal(Box::new(Literal::Number(count_str.to_string()))),
3937 );
3938 }
3939 if s.parse::<f64>().is_ok() {
3941 return (
3942 IntervalUnit::Day,
3943 Expression::Literal(Box::new(Literal::Number(s.clone()))),
3944 );
3945 }
3946 }
3947 _ => {}
3948 }
3949 }
3950
3951 (
3953 IntervalUnit::Day,
3954 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3955 )
3956 } else {
3957 (
3958 IntervalUnit::Day,
3959 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
3960 )
3961 }
3962}
3963
3964pub fn no_ilike_sql(expr: Expression) -> Result<Expression> {
3977 match expr {
3978 Expression::ILike(ilike) => {
3979 let lower_left = Expression::Function(Box::new(crate::expressions::Function {
3981 on_error: None,
3982 qualified_name: Vec::new(),
3983 source_dialect: None,
3984
3985 name: "LOWER".to_string(),
3986 args: vec![ilike.left],
3987 distinct: false,
3988 trailing_comments: vec![],
3989 use_bracket_syntax: false,
3990 no_parens: false,
3991 quoted: false,
3992 span: None,
3993 inferred_type: None,
3994 }));
3995
3996 let lower_right = Expression::Function(Box::new(crate::expressions::Function {
3997 on_error: None,
3998 qualified_name: Vec::new(),
3999 source_dialect: None,
4000
4001 name: "LOWER".to_string(),
4002 args: vec![ilike.right],
4003 distinct: false,
4004 trailing_comments: vec![],
4005 use_bracket_syntax: false,
4006 no_parens: false,
4007 quoted: false,
4008 span: None,
4009 inferred_type: None,
4010 }));
4011
4012 Ok(Expression::Like(Box::new(crate::expressions::LikeOp {
4013 left: lower_left,
4014 right: lower_right,
4015 escape: ilike.escape,
4016 quantifier: ilike.quantifier,
4017 inferred_type: None,
4018 })))
4019 }
4020 other => Ok(other),
4021 }
4022}
4023
4024pub fn no_trycast_sql(expr: Expression) -> Result<Expression> {
4032 match expr {
4033 Expression::TryCast(try_cast) => Ok(Expression::Cast(try_cast)),
4034 other => Ok(other),
4035 }
4036}
4037
4038pub fn no_safe_cast_sql(expr: Expression) -> Result<Expression> {
4043 match expr {
4044 Expression::SafeCast(safe_cast) => Ok(Expression::Cast(safe_cast)),
4045 other => Ok(other),
4046 }
4047}
4048
4049pub fn no_comment_column_constraint(expr: Expression) -> Result<Expression> {
4056 Ok(expr)
4058}
4059
4060pub fn unnest_generate_series(expr: Expression) -> Result<Expression> {
4074 match expr {
4077 Expression::Table(ref table) => {
4078 if table.name.name.to_uppercase() == "GENERATE_SERIES" {
4081 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4083 this: expr.clone(),
4084 expressions: Vec::new(),
4085 with_ordinality: false,
4086 alias: None,
4087 offset_alias: None,
4088 inferred_type: None,
4089 }));
4090
4091 return Ok(Expression::Alias(Box::new(crate::expressions::Alias {
4093 this: unnest,
4094 alias: Identifier::new("_u".to_string()),
4095 column_aliases: vec![],
4096 alias_explicit_as: false,
4097 alias_keyword: None,
4098 pre_alias_comments: vec![],
4099 trailing_comments: vec![],
4100 inferred_type: None,
4101 })));
4102 }
4103 Ok(expr)
4104 }
4105 Expression::GenerateSeries(gs) => {
4106 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4108 this: Expression::GenerateSeries(gs),
4109 expressions: Vec::new(),
4110 with_ordinality: false,
4111 alias: None,
4112 offset_alias: None,
4113 inferred_type: None,
4114 }));
4115 Ok(unnest)
4116 }
4117 other => Ok(other),
4118 }
4119}
4120
4121pub fn unwrap_unnest_generate_series_for_postgres(expr: Expression) -> Result<Expression> {
4132 use crate::dialects::transform_recursive;
4133 transform_recursive(expr, &unwrap_unnest_generate_series_single)
4134}
4135
4136fn unwrap_unnest_generate_series_single(expr: Expression) -> Result<Expression> {
4137 use crate::expressions::*;
4138 match expr {
4140 Expression::Select(mut select) => {
4141 if let Some(ref mut from) = select.from {
4143 for table_expr in &mut from.expressions {
4144 if let Some(replacement) = try_unwrap_unnest_gen_series(table_expr) {
4145 *table_expr = replacement;
4146 }
4147 }
4148 }
4149 for join in &mut select.joins {
4151 if let Some(replacement) = try_unwrap_unnest_gen_series(&join.this) {
4152 join.this = replacement;
4153 }
4154 }
4155 Ok(Expression::Select(select))
4156 }
4157 other => Ok(other),
4158 }
4159}
4160
4161fn try_unwrap_unnest_gen_series(expr: &Expression) -> Option<Expression> {
4164 use crate::expressions::*;
4165
4166 let gen_series = match expr {
4168 Expression::Unnest(unnest) => {
4169 if let Expression::GenerateSeries(ref gs) = unnest.this {
4170 Some(gs.as_ref().clone())
4171 } else {
4172 None
4173 }
4174 }
4175 Expression::Alias(alias) => {
4176 if let Expression::Unnest(ref unnest) = alias.this {
4177 if let Expression::GenerateSeries(ref gs) = unnest.this {
4178 Some(gs.as_ref().clone())
4179 } else {
4180 None
4181 }
4182 } else {
4183 None
4184 }
4185 }
4186 _ => None,
4187 };
4188
4189 let gs = gen_series?;
4190
4191 let value_col = Expression::boxed_column(Column {
4193 name: Identifier::new("value".to_string()),
4194 table: None,
4195 join_mark: false,
4196 trailing_comments: vec![],
4197 span: None,
4198 inferred_type: None,
4199 });
4200
4201 let cast_value = Expression::Cast(Box::new(Cast {
4202 this: value_col,
4203 to: DataType::Date,
4204 trailing_comments: vec![],
4205 double_colon_syntax: false,
4206 format: None,
4207 default: None,
4208 inferred_type: None,
4209 }));
4210
4211 let gen_series_expr = Expression::GenerateSeries(Box::new(gs));
4212
4213 let gen_series_aliased = Expression::Alias(Box::new(Alias {
4215 this: gen_series_expr,
4216 alias: Identifier::new("_t".to_string()),
4217 column_aliases: vec![Identifier::new("value".to_string())],
4218 alias_explicit_as: false,
4219 alias_keyword: None,
4220 pre_alias_comments: vec![],
4221 trailing_comments: vec![],
4222 inferred_type: None,
4223 }));
4224
4225 let mut inner_select = Select::new();
4226 inner_select.expressions = vec![cast_value];
4227 inner_select.from = Some(From {
4228 expressions: vec![gen_series_aliased],
4229 });
4230
4231 let inner_select_expr = Expression::Select(Box::new(inner_select));
4232
4233 let subquery = Expression::Subquery(Box::new(Subquery {
4234 this: inner_select_expr,
4235 alias: None,
4236 column_aliases: vec![],
4237 alias_explicit_as: false,
4238 alias_keyword: None,
4239 order_by: None,
4240 limit: None,
4241 offset: None,
4242 distribute_by: None,
4243 sort_by: None,
4244 cluster_by: None,
4245 lateral: false,
4246 modifiers_inside: false,
4247 trailing_comments: vec![],
4248 inferred_type: None,
4249 }));
4250
4251 Some(Expression::Alias(Box::new(Alias {
4253 this: subquery,
4254 alias: Identifier::new("_unnested_generate_series".to_string()),
4255 column_aliases: vec![],
4256 alias_explicit_as: false,
4257 alias_keyword: None,
4258 pre_alias_comments: vec![],
4259 trailing_comments: vec![],
4260 inferred_type: None,
4261 })))
4262}
4263
4264pub fn expand_between_in_delete(expr: Expression) -> Result<Expression> {
4272 match expr {
4273 Expression::Delete(mut delete) => {
4274 if let Some(ref mut where_clause) = delete.where_clause {
4276 where_clause.this = expand_between_recursive(where_clause.this.clone());
4277 }
4278 Ok(Expression::Delete(delete))
4279 }
4280 other => Ok(other),
4281 }
4282}
4283
4284fn expand_between_recursive(expr: Expression) -> Expression {
4286 match expr {
4287 Expression::Between(between) => {
4290 let this = expand_between_recursive(between.this.clone());
4291 let low = expand_between_recursive(between.low);
4292 let high = expand_between_recursive(between.high);
4293
4294 if between.not {
4295 Expression::Or(Box::new(BinaryOp::new(
4297 Expression::Lt(Box::new(BinaryOp::new(this.clone(), low))),
4298 Expression::Gt(Box::new(BinaryOp::new(this, high))),
4299 )))
4300 } else {
4301 Expression::And(Box::new(BinaryOp::new(
4303 Expression::Gte(Box::new(BinaryOp::new(this.clone(), low))),
4304 Expression::Lte(Box::new(BinaryOp::new(this, high))),
4305 )))
4306 }
4307 }
4308
4309 Expression::And(mut op) => {
4311 op.left = expand_between_recursive(op.left);
4312 op.right = expand_between_recursive(op.right);
4313 Expression::And(op)
4314 }
4315 Expression::Or(mut op) => {
4316 op.left = expand_between_recursive(op.left);
4317 op.right = expand_between_recursive(op.right);
4318 Expression::Or(op)
4319 }
4320 Expression::Not(mut op) => {
4321 op.this = expand_between_recursive(op.this);
4322 Expression::Not(op)
4323 }
4324
4325 Expression::Paren(mut paren) => {
4327 paren.this = expand_between_recursive(paren.this);
4328 Expression::Paren(paren)
4329 }
4330
4331 other => other,
4333 }
4334}
4335
4336pub fn pushdown_cte_column_names(expr: Expression) -> Result<Expression> {
4345 match expr {
4346 Expression::Select(mut select) => {
4347 if let Some(ref mut with) = select.with {
4348 for cte in &mut with.ctes {
4349 if !cte.columns.is_empty() {
4350 let is_star = matches!(&cte.this, Expression::Select(s) if
4352 s.expressions.len() == 1 && matches!(&s.expressions[0], Expression::Star(_)));
4353
4354 if is_star {
4355 cte.columns.clear();
4357 continue;
4358 }
4359
4360 let column_names: Vec<Identifier> = cte.columns.drain(..).collect();
4362
4363 if let Expression::Select(ref mut inner_select) = cte.this {
4365 let new_exprs: Vec<Expression> = inner_select
4366 .expressions
4367 .drain(..)
4368 .zip(
4369 column_names
4370 .into_iter()
4371 .chain(std::iter::repeat_with(|| Identifier::new(""))),
4372 )
4373 .map(|(expr, col_name)| {
4374 if col_name.name.is_empty() {
4375 return expr;
4376 }
4377 match expr {
4379 Expression::Alias(mut a) => {
4380 a.alias = col_name;
4381 Expression::Alias(a)
4382 }
4383 other => {
4384 Expression::Alias(Box::new(crate::expressions::Alias {
4385 this: other,
4386 alias: col_name,
4387 column_aliases: Vec::new(),
4388 alias_explicit_as: false,
4389 alias_keyword: None,
4390 pre_alias_comments: Vec::new(),
4391 trailing_comments: Vec::new(),
4392 inferred_type: None,
4393 }))
4394 }
4395 }
4396 })
4397 .collect();
4398 inner_select.expressions = new_exprs;
4399 }
4400 }
4401 }
4402 }
4403 Ok(Expression::Select(select))
4404 }
4405 other => Ok(other),
4406 }
4407}
4408
4409pub fn simplify_nested_paren_values(expr: Expression) -> Result<Expression> {
4413 match expr {
4414 Expression::Select(mut select) => {
4415 if let Some(ref mut from) = select.from {
4416 for from_item in from.expressions.iter_mut() {
4417 simplify_paren_values_in_from(from_item);
4418 }
4419 }
4420 Ok(Expression::Select(select))
4421 }
4422 other => Ok(other),
4423 }
4424}
4425
4426fn simplify_paren_values_in_from(expr: &mut Expression) {
4427 let replacement = match expr {
4429 Expression::Subquery(ref subquery) => {
4431 if let Expression::Paren(ref paren) = subquery.this {
4432 if matches!(&paren.this, Expression::Values(_)) {
4433 let mut new_sub = subquery.as_ref().clone();
4434 new_sub.this = paren.this.clone();
4435 Some(Expression::Subquery(Box::new(new_sub)))
4436 } else {
4437 None
4438 }
4439 } else {
4440 None
4441 }
4442 }
4443 Expression::Paren(ref outer_paren) => {
4446 if let Expression::Subquery(ref subquery) = outer_paren.this {
4447 if matches!(&subquery.this, Expression::Values(_)) {
4449 Some(outer_paren.this.clone())
4450 }
4451 else if let Expression::Paren(ref paren) = subquery.this {
4453 if matches!(&paren.this, Expression::Values(_)) {
4454 let mut new_sub = subquery.as_ref().clone();
4455 new_sub.this = paren.this.clone();
4456 Some(Expression::Subquery(Box::new(new_sub)))
4457 } else {
4458 None
4459 }
4460 } else {
4461 None
4462 }
4463 } else if let Expression::Paren(ref inner_paren) = outer_paren.this {
4464 if matches!(&inner_paren.this, Expression::Values(_)) {
4465 Some(outer_paren.this.clone())
4466 } else {
4467 None
4468 }
4469 } else {
4470 None
4471 }
4472 }
4473 _ => None,
4474 };
4475 if let Some(new_expr) = replacement {
4476 *expr = new_expr;
4477 }
4478}
4479
4480pub fn add_auto_table_alias(expr: Expression) -> Result<Expression> {
4484 match expr {
4485 Expression::Select(mut select) => {
4486 if let Some(ref mut from) = select.from {
4488 let mut counter = 0usize;
4489 for from_item in from.expressions.iter_mut() {
4490 add_auto_alias_to_from_item(from_item, &mut counter);
4491 }
4492 }
4493 Ok(Expression::Select(select))
4494 }
4495 other => Ok(other),
4496 }
4497}
4498
4499fn add_auto_alias_to_from_item(expr: &mut Expression, counter: &mut usize) {
4500 use crate::expressions::Identifier;
4501
4502 match expr {
4503 Expression::Alias(ref mut alias) => {
4504 if alias.alias.name.is_empty() && !alias.column_aliases.is_empty() {
4506 alias.alias = Identifier::new(format!("_t{}", counter));
4507 *counter += 1;
4508 }
4509 }
4510 _ => {}
4511 }
4512}
4513
4514pub fn propagate_struct_field_names(expr: Expression) -> Result<Expression> {
4524 use crate::dialects::transform_recursive;
4525 transform_recursive(expr, &propagate_struct_names_in_expr)
4526}
4527
4528fn propagate_struct_names_in_expr(expr: Expression) -> Result<Expression> {
4529 use crate::expressions::{Alias, ArrayConstructor, Function, Identifier};
4530
4531 fn propagate_in_elements(elements: &[Expression]) -> Option<Vec<Expression>> {
4533 if elements.len() <= 1 {
4534 return None;
4535 }
4536 if let Some(Expression::Function(ref first_struct)) = elements.first() {
4538 if first_struct.name.eq_ignore_ascii_case("STRUCT") {
4539 let field_names: Vec<Option<String>> = first_struct
4541 .args
4542 .iter()
4543 .map(|arg| {
4544 if let Expression::Alias(a) = arg {
4545 Some(a.alias.name.clone())
4546 } else {
4547 None
4548 }
4549 })
4550 .collect();
4551
4552 if field_names.iter().any(|n| n.is_some()) {
4554 let mut new_elements = Vec::with_capacity(elements.len());
4555 new_elements.push(elements[0].clone());
4556
4557 for elem in &elements[1..] {
4558 if let Expression::Function(ref s) = elem {
4559 if s.name.eq_ignore_ascii_case("STRUCT")
4560 && s.args.len() == field_names.len()
4561 {
4562 let all_unnamed =
4564 s.args.iter().all(|a| !matches!(a, Expression::Alias(_)));
4565 if all_unnamed {
4566 let new_args: Vec<Expression> = s
4568 .args
4569 .iter()
4570 .zip(field_names.iter())
4571 .map(|(val, name)| {
4572 if let Some(n) = name {
4573 Expression::Alias(Box::new(Alias::new(
4574 val.clone(),
4575 Identifier::new(n.clone()),
4576 )))
4577 } else {
4578 val.clone()
4579 }
4580 })
4581 .collect();
4582 new_elements.push(Expression::Function(Box::new(
4583 Function::new("STRUCT".to_string(), new_args),
4584 )));
4585 continue;
4586 }
4587 }
4588 }
4589 new_elements.push(elem.clone());
4590 }
4591
4592 return Some(new_elements);
4593 }
4594 }
4595 }
4596 None
4597 }
4598
4599 if let Expression::Array(ref arr) = expr {
4601 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
4602 return Ok(Expression::Array(Box::new(crate::expressions::Array {
4603 expressions: new_elements,
4604 inferred_type: arr.inferred_type.clone(),
4605 })));
4606 }
4607 }
4608
4609 if let Expression::ArrayFunc(ref arr) = expr {
4611 if let Some(new_elements) = propagate_in_elements(&arr.expressions) {
4612 return Ok(Expression::ArrayFunc(Box::new(ArrayConstructor {
4613 expressions: new_elements,
4614 bracket_notation: arr.bracket_notation,
4615 use_list_keyword: arr.use_list_keyword,
4616 inferred_type: arr.inferred_type.clone(),
4617 })));
4618 }
4619 }
4620
4621 Ok(expr)
4622}
4623
4624pub fn unnest_alias_to_column_alias(expr: Expression) -> Result<Expression> {
4627 use crate::dialects::transform_recursive;
4628 transform_recursive(expr, &unnest_alias_transform_single_select)
4629}
4630
4631pub fn unnest_from_to_cross_join(expr: Expression) -> Result<Expression> {
4634 use crate::dialects::transform_recursive;
4635 transform_recursive(expr, &unnest_from_to_cross_join_single_select)
4636}
4637
4638fn unnest_from_to_cross_join_single_select(expr: Expression) -> Result<Expression> {
4639 if let Expression::Select(mut select) = expr {
4640 if let Some(ref mut from) = select.from {
4641 if from.expressions.len() > 1 {
4642 let mut new_from_exprs = Vec::new();
4643 let mut new_cross_joins = Vec::new();
4644
4645 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4646 if idx == 0 {
4647 new_from_exprs.push(from_item);
4648 } else {
4649 let is_unnest = match &from_item {
4650 Expression::Unnest(_) => true,
4651 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4652 _ => false,
4653 };
4654
4655 if is_unnest {
4656 new_cross_joins.push(crate::expressions::Join {
4657 this: from_item,
4658 on: None,
4659 using: Vec::new(),
4660 kind: JoinKind::Cross,
4661 use_inner_keyword: false,
4662 use_outer_keyword: false,
4663 deferred_condition: false,
4664 join_hint: None,
4665 match_condition: None,
4666 pivots: Vec::new(),
4667 comments: Vec::new(),
4668 nesting_group: 0,
4669 directed: false,
4670 });
4671 } else {
4672 new_from_exprs.push(from_item);
4673 }
4674 }
4675 }
4676
4677 from.expressions = new_from_exprs;
4678 new_cross_joins.append(&mut select.joins);
4679 select.joins = new_cross_joins;
4680 }
4681 }
4682
4683 Ok(Expression::Select(select))
4684 } else {
4685 Ok(expr)
4686 }
4687}
4688
4689pub fn wrap_unnest_join_aliases(expr: Expression) -> Result<Expression> {
4693 use crate::dialects::transform_recursive;
4694 transform_recursive(expr, &wrap_unnest_join_aliases_single)
4695}
4696
4697fn wrap_unnest_join_aliases_single(expr: Expression) -> Result<Expression> {
4698 if let Expression::Select(mut select) = expr {
4699 for join in &mut select.joins {
4701 wrap_unnest_alias_in_join_item(&mut join.this);
4702 }
4703 Ok(Expression::Select(select))
4704 } else {
4705 Ok(expr)
4706 }
4707}
4708
4709fn wrap_unnest_alias_in_join_item(expr: &mut Expression) {
4711 use crate::expressions::Identifier;
4712 if let Expression::Alias(alias) = expr {
4713 let is_unnest = match &alias.this {
4715 Expression::Function(f) => f.name.eq_ignore_ascii_case("UNNEST"),
4716 _ => false,
4717 };
4718
4719 if is_unnest && alias.column_aliases.is_empty() {
4720 let original_alias_name = alias.alias.name.clone();
4722 alias.alias = Identifier {
4723 name: "_u".to_string(),
4724 quoted: false,
4725 trailing_comments: Vec::new(),
4726 span: None,
4727 };
4728 alias.column_aliases = vec![Identifier {
4729 name: original_alias_name,
4730 quoted: false,
4731 trailing_comments: Vec::new(),
4732 span: None,
4733 }];
4734 }
4735 }
4736}
4737
4738fn unnest_alias_transform_single_select(expr: Expression) -> Result<Expression> {
4739 if let Expression::Select(mut select) = expr {
4740 let mut counter = 0usize;
4741
4742 if let Some(ref mut from) = select.from {
4744 for from_item in from.expressions.iter_mut() {
4746 convert_unnest_alias_in_from(from_item, &mut counter);
4747 }
4748
4749 if from.expressions.len() > 1 {
4751 let mut new_from_exprs = Vec::new();
4752 let mut new_cross_joins = Vec::new();
4753
4754 for (idx, from_item) in from.expressions.drain(..).enumerate() {
4755 if idx == 0 {
4756 new_from_exprs.push(from_item);
4758 } else {
4759 let is_unnest = match &from_item {
4761 Expression::Unnest(_) => true,
4762 Expression::Alias(a) => matches!(a.this, Expression::Unnest(_)),
4763 _ => false,
4764 };
4765
4766 if is_unnest {
4767 new_cross_joins.push(crate::expressions::Join {
4769 this: from_item,
4770 on: None,
4771 using: Vec::new(),
4772 kind: JoinKind::Cross,
4773 use_inner_keyword: false,
4774 use_outer_keyword: false,
4775 deferred_condition: false,
4776 join_hint: None,
4777 match_condition: None,
4778 pivots: Vec::new(),
4779 comments: Vec::new(),
4780 nesting_group: 0,
4781 directed: false,
4782 });
4783 } else {
4784 new_from_exprs.push(from_item);
4786 }
4787 }
4788 }
4789
4790 from.expressions = new_from_exprs;
4791 new_cross_joins.append(&mut select.joins);
4793 select.joins = new_cross_joins;
4794 }
4795 }
4796
4797 for join in select.joins.iter_mut() {
4799 convert_unnest_alias_in_from(&mut join.this, &mut counter);
4800 }
4801
4802 Ok(Expression::Select(select))
4803 } else {
4804 Ok(expr)
4805 }
4806}
4807
4808fn convert_unnest_alias_in_from(expr: &mut Expression, counter: &mut usize) {
4809 use crate::expressions::Identifier;
4810
4811 if let Expression::Alias(ref mut alias) = expr {
4812 let is_unnest = matches!(&alias.this, Expression::Unnest(_))
4814 || matches!(&alias.this, Expression::Function(f) if f.name.eq_ignore_ascii_case("EXPLODE"));
4815
4816 if is_unnest && alias.column_aliases.is_empty() {
4817 let col_alias = alias.alias.clone();
4819 alias.column_aliases = vec![col_alias];
4820 alias.alias = Identifier::new(format!("_t{}", counter));
4821 *counter += 1;
4822 }
4823 }
4824}
4825
4826pub fn expand_posexplode_duckdb(expr: Expression) -> Result<Expression> {
4833 use crate::expressions::{Alias, Function};
4834
4835 match expr {
4836 Expression::Select(mut select) => {
4837 let mut new_expressions = Vec::new();
4839 let mut changed = false;
4840
4841 for sel_expr in select.expressions.drain(..) {
4842 if let Expression::Alias(ref alias_box) = sel_expr {
4844 if let Expression::Function(ref func) = alias_box.this {
4845 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4846 let arg = func.args[0].clone();
4847 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
4849 (
4850 alias_box.column_aliases[0].name.clone(),
4851 alias_box.column_aliases[1].name.clone(),
4852 )
4853 } else if !alias_box.alias.is_empty() {
4854 ("pos".to_string(), alias_box.alias.name.clone())
4856 } else {
4857 ("pos".to_string(), "col".to_string())
4858 };
4859
4860 let gen_subscripts = Expression::Function(Box::new(Function::new(
4862 "GENERATE_SUBSCRIPTS".to_string(),
4863 vec![
4864 arg.clone(),
4865 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4866 ],
4867 )));
4868 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4869 gen_subscripts,
4870 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4871 )));
4872 let pos_alias = Expression::Alias(Box::new(Alias {
4873 this: sub_one,
4874 alias: Identifier::new(pos_name),
4875 column_aliases: Vec::new(),
4876 alias_explicit_as: false,
4877 alias_keyword: None,
4878 pre_alias_comments: Vec::new(),
4879 trailing_comments: Vec::new(),
4880 inferred_type: None,
4881 }));
4882
4883 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4885 this: arg,
4886 expressions: Vec::new(),
4887 with_ordinality: false,
4888 alias: None,
4889 offset_alias: None,
4890 inferred_type: None,
4891 }));
4892 let col_alias = Expression::Alias(Box::new(Alias {
4893 this: unnest,
4894 alias: Identifier::new(col_name),
4895 column_aliases: Vec::new(),
4896 alias_explicit_as: false,
4897 alias_keyword: None,
4898 pre_alias_comments: Vec::new(),
4899 trailing_comments: Vec::new(),
4900 inferred_type: None,
4901 }));
4902
4903 new_expressions.push(pos_alias);
4904 new_expressions.push(col_alias);
4905 changed = true;
4906 continue;
4907 }
4908 }
4909 }
4910
4911 if let Expression::Function(ref func) = sel_expr {
4913 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
4914 let arg = func.args[0].clone();
4915 let pos_name = "pos";
4916 let col_name = "col";
4917
4918 let gen_subscripts = Expression::Function(Box::new(Function::new(
4920 "GENERATE_SUBSCRIPTS".to_string(),
4921 vec![
4922 arg.clone(),
4923 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4924 ],
4925 )));
4926 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
4927 gen_subscripts,
4928 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
4929 )));
4930 let pos_alias = Expression::Alias(Box::new(Alias {
4931 this: sub_one,
4932 alias: Identifier::new(pos_name),
4933 column_aliases: Vec::new(),
4934 alias_explicit_as: false,
4935 alias_keyword: None,
4936 pre_alias_comments: Vec::new(),
4937 trailing_comments: Vec::new(),
4938 inferred_type: None,
4939 }));
4940
4941 let unnest = Expression::Unnest(Box::new(UnnestFunc {
4943 this: arg,
4944 expressions: Vec::new(),
4945 with_ordinality: false,
4946 alias: None,
4947 offset_alias: None,
4948 inferred_type: None,
4949 }));
4950 let col_alias = Expression::Alias(Box::new(Alias {
4951 this: unnest,
4952 alias: Identifier::new(col_name),
4953 column_aliases: Vec::new(),
4954 alias_explicit_as: false,
4955 alias_keyword: None,
4956 pre_alias_comments: Vec::new(),
4957 trailing_comments: Vec::new(),
4958 inferred_type: None,
4959 }));
4960
4961 new_expressions.push(pos_alias);
4962 new_expressions.push(col_alias);
4963 changed = true;
4964 continue;
4965 }
4966 }
4967
4968 new_expressions.push(sel_expr);
4970 }
4971
4972 if changed {
4973 select.expressions = new_expressions;
4974 } else {
4975 select.expressions = new_expressions;
4976 }
4977
4978 if let Some(ref mut from) = select.from {
4981 expand_posexplode_in_from_duckdb(from)?;
4982 }
4983
4984 Ok(Expression::Select(select))
4985 }
4986 other => Ok(other),
4987 }
4988}
4989
4990fn expand_posexplode_in_from_duckdb(from: &mut From) -> Result<()> {
4992 use crate::expressions::{Alias, Function};
4993
4994 let mut new_expressions = Vec::new();
4995 let mut _changed = false;
4996
4997 for table_expr in from.expressions.drain(..) {
4998 if let Expression::Alias(ref alias_box) = table_expr {
5000 if let Expression::Function(ref func) = alias_box.this {
5001 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
5002 let arg = func.args[0].clone();
5003 let (pos_name, col_name) = if alias_box.column_aliases.len() == 2 {
5004 (
5005 alias_box.column_aliases[0].name.clone(),
5006 alias_box.column_aliases[1].name.clone(),
5007 )
5008 } else {
5009 ("pos".to_string(), "col".to_string())
5010 };
5011
5012 let gen_subscripts = Expression::Function(Box::new(Function::new(
5014 "GENERATE_SUBSCRIPTS".to_string(),
5015 vec![
5016 arg.clone(),
5017 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5018 ],
5019 )));
5020 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
5021 gen_subscripts,
5022 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5023 )));
5024 let pos_alias = Expression::Alias(Box::new(Alias {
5025 this: sub_one,
5026 alias: Identifier::new(&pos_name),
5027 column_aliases: Vec::new(),
5028 alias_explicit_as: false,
5029 alias_keyword: None,
5030 pre_alias_comments: Vec::new(),
5031 trailing_comments: Vec::new(),
5032 inferred_type: None,
5033 }));
5034 let unnest = Expression::Unnest(Box::new(UnnestFunc {
5035 this: arg,
5036 expressions: Vec::new(),
5037 with_ordinality: false,
5038 alias: None,
5039 offset_alias: None,
5040 inferred_type: None,
5041 }));
5042 let col_alias = Expression::Alias(Box::new(Alias {
5043 this: unnest,
5044 alias: Identifier::new(&col_name),
5045 column_aliases: Vec::new(),
5046 alias_explicit_as: false,
5047 alias_keyword: None,
5048 pre_alias_comments: Vec::new(),
5049 trailing_comments: Vec::new(),
5050 inferred_type: None,
5051 }));
5052
5053 let mut inner_select = Select::new();
5054 inner_select.expressions = vec![pos_alias, col_alias];
5055
5056 let subquery = Expression::Subquery(Box::new(Subquery {
5057 this: Expression::Select(Box::new(inner_select)),
5058 alias: None,
5059 column_aliases: Vec::new(),
5060 alias_explicit_as: false,
5061 alias_keyword: None,
5062 order_by: None,
5063 limit: None,
5064 offset: None,
5065 distribute_by: None,
5066 sort_by: None,
5067 cluster_by: None,
5068 lateral: false,
5069 modifiers_inside: false,
5070 trailing_comments: Vec::new(),
5071 inferred_type: None,
5072 }));
5073 new_expressions.push(subquery);
5074 _changed = true;
5075 continue;
5076 }
5077 }
5078 }
5079
5080 if let Expression::Function(ref func) = table_expr {
5082 if func.name.eq_ignore_ascii_case("POSEXPLODE") && func.args.len() == 1 {
5083 let arg = func.args[0].clone();
5084
5085 let gen_subscripts = Expression::Function(Box::new(Function::new(
5087 "GENERATE_SUBSCRIPTS".to_string(),
5088 vec![
5089 arg.clone(),
5090 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5091 ],
5092 )));
5093 let sub_one = Expression::Sub(Box::new(BinaryOp::new(
5094 gen_subscripts,
5095 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5096 )));
5097 let pos_alias = Expression::Alias(Box::new(Alias {
5098 this: sub_one,
5099 alias: Identifier::new("pos"),
5100 column_aliases: Vec::new(),
5101 alias_explicit_as: false,
5102 alias_keyword: None,
5103 pre_alias_comments: Vec::new(),
5104 trailing_comments: Vec::new(),
5105 inferred_type: None,
5106 }));
5107 let unnest = Expression::Unnest(Box::new(UnnestFunc {
5108 this: arg,
5109 expressions: Vec::new(),
5110 with_ordinality: false,
5111 alias: None,
5112 offset_alias: None,
5113 inferred_type: None,
5114 }));
5115 let col_alias = Expression::Alias(Box::new(Alias {
5116 this: unnest,
5117 alias: Identifier::new("col"),
5118 column_aliases: Vec::new(),
5119 alias_explicit_as: false,
5120 alias_keyword: None,
5121 pre_alias_comments: Vec::new(),
5122 trailing_comments: Vec::new(),
5123 inferred_type: None,
5124 }));
5125
5126 let mut inner_select = Select::new();
5127 inner_select.expressions = vec![pos_alias, col_alias];
5128
5129 let subquery = Expression::Subquery(Box::new(Subquery {
5130 this: Expression::Select(Box::new(inner_select)),
5131 alias: None,
5132 column_aliases: Vec::new(),
5133 alias_explicit_as: false,
5134 alias_keyword: None,
5135 order_by: None,
5136 limit: None,
5137 offset: None,
5138 distribute_by: None,
5139 sort_by: None,
5140 cluster_by: None,
5141 lateral: false,
5142 modifiers_inside: false,
5143 trailing_comments: Vec::new(),
5144 inferred_type: None,
5145 }));
5146 new_expressions.push(subquery);
5147 _changed = true;
5148 continue;
5149 }
5150 }
5151
5152 new_expressions.push(table_expr);
5153 }
5154
5155 from.expressions = new_expressions;
5156 Ok(())
5157}
5158
5159pub fn explode_projection_to_unnest(expr: Expression, target: DialectType) -> Result<Expression> {
5174 match expr {
5175 Expression::Select(select) => explode_projection_to_unnest_impl(*select, target),
5176 other => Ok(other),
5177 }
5178}
5179
5180pub fn snowflake_flatten_projection_to_unnest(expr: Expression) -> Result<Expression> {
5190 match expr {
5191 Expression::Select(select) => snowflake_flatten_projection_to_unnest_impl(*select),
5192 other => Ok(other),
5193 }
5194}
5195
5196fn snowflake_flatten_projection_to_unnest_impl(mut select: Select) -> Result<Expression> {
5197 let mut flattened_inputs: Vec<Expression> = Vec::new();
5198 let mut new_selects: Vec<Expression> = Vec::with_capacity(select.expressions.len());
5199
5200 for sel_expr in select.expressions.into_iter() {
5201 let found_input: RefCell<Option<Expression>> = RefCell::new(None);
5202
5203 let rewritten = transform_recursive(sel_expr, &|e| {
5204 if let Expression::Lateral(lat) = e {
5205 if let Some(input_expr) = extract_flatten_input(&lat) {
5206 if found_input.borrow().is_none() {
5207 *found_input.borrow_mut() = Some(input_expr);
5208 }
5209 return Ok(Expression::Lateral(Box::new(rewrite_flatten_lateral(*lat))));
5210 }
5211 return Ok(Expression::Lateral(lat));
5212 }
5213 Ok(e)
5214 })?;
5215
5216 if let Some(input) = found_input.into_inner() {
5217 flattened_inputs.push(input);
5218 }
5219 new_selects.push(rewritten);
5220 }
5221
5222 if flattened_inputs.is_empty() {
5223 select.expressions = new_selects;
5224 return Ok(Expression::Select(Box::new(select)));
5225 }
5226
5227 select.expressions = new_selects;
5228
5229 for (idx, input_expr) in flattened_inputs.into_iter().enumerate() {
5230 let is_first = idx == 0;
5232 let series_alias = if is_first {
5233 "pos".to_string()
5234 } else {
5235 format!("pos_{}", idx + 1)
5236 };
5237 let series_source_alias = if is_first {
5238 "_u".to_string()
5239 } else {
5240 format!("_u_{}", idx * 2 + 1)
5241 };
5242 let unnest_source_alias = if is_first {
5243 "_u_2".to_string()
5244 } else {
5245 format!("_u_{}", idx * 2 + 2)
5246 };
5247 let pos2_alias = if is_first {
5248 "pos_2".to_string()
5249 } else {
5250 format!("{}_2", series_alias)
5251 };
5252 let entity_alias = if is_first {
5253 "entity".to_string()
5254 } else {
5255 format!("entity_{}", idx + 1)
5256 };
5257
5258 let array_size_call = Expression::Function(Box::new(Function::new(
5259 "ARRAY_SIZE".to_string(),
5260 vec![Expression::NamedArgument(Box::new(NamedArgument {
5261 name: Identifier::new("INPUT"),
5262 value: input_expr.clone(),
5263 separator: NamedArgSeparator::DArrow,
5264 }))],
5265 )));
5266
5267 let greatest = Expression::Function(Box::new(Function::new(
5268 "GREATEST".to_string(),
5269 vec![array_size_call.clone()],
5270 )));
5271
5272 let series_end = Expression::Add(Box::new(BinaryOp::new(
5273 Expression::Paren(Box::new(crate::expressions::Paren {
5274 this: Expression::Sub(Box::new(BinaryOp::new(
5275 greatest,
5276 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5277 ))),
5278 trailing_comments: Vec::new(),
5279 })),
5280 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5281 )));
5282
5283 let series_range = Expression::Function(Box::new(Function::new(
5284 "ARRAY_GENERATE_RANGE".to_string(),
5285 vec![
5286 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
5287 series_end,
5288 ],
5289 )));
5290
5291 let series_flatten = Expression::Function(Box::new(Function::new(
5292 "FLATTEN".to_string(),
5293 vec![Expression::NamedArgument(Box::new(NamedArgument {
5294 name: Identifier::new("INPUT"),
5295 value: series_range,
5296 separator: NamedArgSeparator::DArrow,
5297 }))],
5298 )));
5299
5300 let series_table = Expression::Function(Box::new(Function::new(
5301 "TABLE".to_string(),
5302 vec![series_flatten],
5303 )));
5304
5305 let series_alias_expr = Expression::Alias(Box::new(Alias {
5306 this: series_table,
5307 alias: Identifier::new(series_source_alias.clone()),
5308 column_aliases: vec![
5309 Identifier::new("seq"),
5310 Identifier::new("key"),
5311 Identifier::new("path"),
5312 Identifier::new("index"),
5313 Identifier::new(series_alias.clone()),
5314 Identifier::new("this"),
5315 ],
5316 alias_explicit_as: false,
5317 alias_keyword: None,
5318 pre_alias_comments: Vec::new(),
5319 trailing_comments: Vec::new(),
5320 inferred_type: None,
5321 }));
5322
5323 select.joins.push(Join {
5324 this: series_alias_expr,
5325 on: None,
5326 using: Vec::new(),
5327 kind: JoinKind::Cross,
5328 use_inner_keyword: false,
5329 use_outer_keyword: false,
5330 deferred_condition: false,
5331 join_hint: None,
5332 match_condition: None,
5333 pivots: Vec::new(),
5334 comments: Vec::new(),
5335 nesting_group: 0,
5336 directed: false,
5337 });
5338
5339 let entity_flatten = Expression::Function(Box::new(Function::new(
5340 "FLATTEN".to_string(),
5341 vec![Expression::NamedArgument(Box::new(NamedArgument {
5342 name: Identifier::new("INPUT"),
5343 value: input_expr.clone(),
5344 separator: NamedArgSeparator::DArrow,
5345 }))],
5346 )));
5347
5348 let entity_table = Expression::Function(Box::new(Function::new(
5349 "TABLE".to_string(),
5350 vec![entity_flatten],
5351 )));
5352
5353 let entity_alias_expr = Expression::Alias(Box::new(Alias {
5354 this: entity_table,
5355 alias: Identifier::new(unnest_source_alias.clone()),
5356 column_aliases: vec![
5357 Identifier::new("seq"),
5358 Identifier::new("key"),
5359 Identifier::new("path"),
5360 Identifier::new(pos2_alias.clone()),
5361 Identifier::new(entity_alias.clone()),
5362 Identifier::new("this"),
5363 ],
5364 alias_explicit_as: false,
5365 alias_keyword: None,
5366 pre_alias_comments: Vec::new(),
5367 trailing_comments: Vec::new(),
5368 inferred_type: None,
5369 }));
5370
5371 select.joins.push(Join {
5372 this: entity_alias_expr,
5373 on: None,
5374 using: Vec::new(),
5375 kind: JoinKind::Cross,
5376 use_inner_keyword: false,
5377 use_outer_keyword: false,
5378 deferred_condition: false,
5379 join_hint: None,
5380 match_condition: None,
5381 pivots: Vec::new(),
5382 comments: Vec::new(),
5383 nesting_group: 0,
5384 directed: false,
5385 });
5386
5387 let pos_col =
5388 Expression::qualified_column(series_source_alias.clone(), series_alias.clone());
5389 let pos2_col =
5390 Expression::qualified_column(unnest_source_alias.clone(), pos2_alias.clone());
5391
5392 let eq = Expression::Eq(Box::new(BinaryOp::new(pos_col.clone(), pos2_col.clone())));
5393 let size_minus_1 = Expression::Paren(Box::new(crate::expressions::Paren {
5394 this: Expression::Sub(Box::new(BinaryOp::new(
5395 array_size_call,
5396 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
5397 ))),
5398 trailing_comments: Vec::new(),
5399 }));
5400 let gt = Expression::Gt(Box::new(BinaryOp::new(pos_col, size_minus_1.clone())));
5401 let pos2_eq_size = Expression::Eq(Box::new(BinaryOp::new(pos2_col, size_minus_1)));
5402 let and_cond = Expression::And(Box::new(BinaryOp::new(gt, pos2_eq_size)));
5403 let or_cond = Expression::Or(Box::new(BinaryOp::new(
5404 eq,
5405 Expression::Paren(Box::new(crate::expressions::Paren {
5406 this: and_cond,
5407 trailing_comments: Vec::new(),
5408 })),
5409 )));
5410
5411 select.where_clause = Some(match select.where_clause.take() {
5412 Some(existing) => Where {
5413 this: Expression::And(Box::new(BinaryOp::new(existing.this, or_cond))),
5414 },
5415 None => Where { this: or_cond },
5416 });
5417 }
5418
5419 Ok(Expression::Select(Box::new(select)))
5420}
5421
5422fn extract_flatten_input(lat: &Lateral) -> Option<Expression> {
5423 let Expression::Function(f) = lat.this.as_ref() else {
5424 return None;
5425 };
5426 if !f.name.eq_ignore_ascii_case("FLATTEN") {
5427 return None;
5428 }
5429
5430 for arg in &f.args {
5431 if let Expression::NamedArgument(na) = arg {
5432 if na.name.name.eq_ignore_ascii_case("INPUT") {
5433 return Some(na.value.clone());
5434 }
5435 }
5436 }
5437 f.args.first().cloned()
5438}
5439
5440fn rewrite_flatten_lateral(mut lat: Lateral) -> Lateral {
5441 let cond = Expression::Eq(Box::new(BinaryOp::new(
5442 Expression::qualified_column("_u", "pos"),
5443 Expression::qualified_column("_u_2", "pos_2"),
5444 )));
5445 let true_expr = Expression::qualified_column("_u_2", "entity");
5446 let iff_expr = Expression::Function(Box::new(Function::new(
5447 "IFF".to_string(),
5448 vec![cond, true_expr, Expression::Null(crate::expressions::Null)],
5449 )));
5450
5451 lat.this = Box::new(iff_expr);
5452 if lat.column_aliases.is_empty() {
5453 lat.column_aliases = vec![
5454 "SEQ".to_string(),
5455 "KEY".to_string(),
5456 "PATH".to_string(),
5457 "INDEX".to_string(),
5458 "VALUE".to_string(),
5459 "THIS".to_string(),
5460 ];
5461 }
5462 lat
5463}
5464
5465struct ExplodeInfo {
5467 arg_sql: String,
5469 explode_alias: String,
5471 pos_alias: String,
5473 unnest_source_alias: String,
5475}
5476
5477fn explode_projection_to_unnest_impl(select: Select, target: DialectType) -> Result<Expression> {
5478 let is_presto = matches!(
5479 target,
5480 DialectType::Presto | DialectType::Trino | DialectType::Athena
5481 );
5482 let is_bigquery = matches!(target, DialectType::BigQuery);
5483
5484 if !is_presto && !is_bigquery {
5485 return Ok(Expression::Select(Box::new(select)));
5486 }
5487
5488 let has_explode = select.expressions.iter().any(|e| expr_contains_explode(e));
5490 if !has_explode {
5491 return Ok(Expression::Select(Box::new(select)));
5492 }
5493
5494 let mut taken_select_names = std::collections::HashSet::new();
5496 let mut taken_source_names = std::collections::HashSet::new();
5497
5498 for sel in &select.expressions {
5500 if let Some(name) = get_output_name(sel) {
5501 taken_select_names.insert(name);
5502 }
5503 }
5504
5505 for sel in &select.expressions {
5507 let explode_expr = find_explode_in_expr(sel);
5508 if let Some(arg) = explode_expr {
5509 if let Some(name) = get_output_name(&arg) {
5510 taken_select_names.insert(name);
5511 }
5512 }
5513 }
5514
5515 if let Some(ref from) = select.from {
5517 for from_expr in &from.expressions {
5518 collect_source_names(from_expr, &mut taken_source_names);
5519 }
5520 }
5521 for join in &select.joins {
5523 collect_source_names(&join.this, &mut taken_source_names);
5524 }
5525
5526 let series_alias = new_name(&mut taken_select_names, "pos");
5528
5529 let series_source_alias = new_name(&mut taken_source_names, "_u");
5531
5532 let target_dialect = Dialect::get(target);
5534
5535 let mut explode_infos: Vec<ExplodeInfo> = Vec::new();
5537 let mut new_projections: Vec<String> = Vec::new();
5538
5539 for (_idx, sel_expr) in select.expressions.iter().enumerate() {
5540 let explode_data = extract_explode_data(sel_expr);
5541
5542 if let Some((is_posexplode, arg_expr, explicit_alias, explicit_pos_alias)) = explode_data {
5543 let arg_sql = target_dialect
5545 .generate(&arg_expr)
5546 .unwrap_or_else(|_| "NULL".to_string());
5547
5548 let unnest_source_alias = new_name(&mut taken_source_names, "_u");
5549
5550 let explode_alias = if let Some(ref ea) = explicit_alias {
5551 taken_select_names.remove(ea.as_str());
5554 let name = new_name(&mut taken_select_names, ea);
5556 name
5557 } else {
5558 new_name(&mut taken_select_names, "col")
5559 };
5560
5561 let pos_alias = if let Some(ref pa) = explicit_pos_alias {
5562 taken_select_names.remove(pa.as_str());
5564 let name = new_name(&mut taken_select_names, pa);
5565 name
5566 } else {
5567 new_name(&mut taken_select_names, "pos")
5568 };
5569
5570 if is_presto {
5572 let if_col = format!(
5574 "IF({}.{} = {}.{}, {}.{}) AS {}",
5575 series_source_alias,
5576 series_alias,
5577 unnest_source_alias,
5578 pos_alias,
5579 unnest_source_alias,
5580 explode_alias,
5581 explode_alias
5582 );
5583 new_projections.push(if_col);
5584
5585 if is_posexplode {
5587 let if_pos = format!(
5588 "IF({}.{} = {}.{}, {}.{}) AS {}",
5589 series_source_alias,
5590 series_alias,
5591 unnest_source_alias,
5592 pos_alias,
5593 unnest_source_alias,
5594 pos_alias,
5595 pos_alias
5596 );
5597 new_projections.push(if_pos);
5598 }
5599 } else {
5600 let if_col = format!(
5602 "IF({} = {}, {}, NULL) AS {}",
5603 series_alias, pos_alias, explode_alias, explode_alias
5604 );
5605 new_projections.push(if_col);
5606
5607 if is_posexplode {
5609 let if_pos = format!(
5610 "IF({} = {}, {}, NULL) AS {}",
5611 series_alias, pos_alias, pos_alias, pos_alias
5612 );
5613 new_projections.push(if_pos);
5614 }
5615 }
5616
5617 explode_infos.push(ExplodeInfo {
5618 arg_sql,
5619 explode_alias,
5620 pos_alias,
5621 unnest_source_alias,
5622 });
5623 } else {
5624 let sel_sql = target_dialect
5626 .generate(sel_expr)
5627 .unwrap_or_else(|_| "*".to_string());
5628 new_projections.push(sel_sql);
5629 }
5630 }
5631
5632 if explode_infos.is_empty() {
5633 return Ok(Expression::Select(Box::new(select)));
5634 }
5635
5636 let mut from_parts: Vec<String> = Vec::new();
5638
5639 if let Some(ref from) = select.from {
5641 for from_expr in &from.expressions {
5642 let from_sql = target_dialect.generate(from_expr).unwrap_or_default();
5643 from_parts.push(from_sql);
5644 }
5645 }
5646
5647 let size_exprs: Vec<String> = explode_infos
5649 .iter()
5650 .map(|info| {
5651 if is_presto {
5652 format!("CARDINALITY({})", info.arg_sql)
5653 } else {
5654 format!("ARRAY_LENGTH({})", info.arg_sql)
5655 }
5656 })
5657 .collect();
5658
5659 let greatest_arg = if size_exprs.len() == 1 {
5660 size_exprs[0].clone()
5661 } else {
5662 format!("GREATEST({})", size_exprs.join(", "))
5663 };
5664
5665 let series_sql = if is_presto {
5668 if size_exprs.len() == 1 {
5670 format!(
5671 "UNNEST(SEQUENCE(1, GREATEST({}))) AS {}({})",
5672 greatest_arg, series_source_alias, series_alias
5673 )
5674 } else {
5675 format!(
5677 "UNNEST(SEQUENCE(1, {})) AS {}({})",
5678 greatest_arg, series_source_alias, series_alias
5679 )
5680 }
5681 } else {
5682 if size_exprs.len() == 1 {
5684 format!(
5685 "UNNEST(GENERATE_ARRAY(0, GREATEST({}) - 1)) AS {}",
5686 greatest_arg, series_alias
5687 )
5688 } else {
5689 format!(
5691 "UNNEST(GENERATE_ARRAY(0, {} - 1)) AS {}",
5692 greatest_arg, series_alias
5693 )
5694 }
5695 };
5696
5697 let mut cross_joins: Vec<String> = Vec::new();
5701
5702 for info in &explode_infos {
5703 cross_joins.push(format!(
5705 "CROSS JOIN UNNEST({}) WITH ORDINALITY AS {}({}, {})",
5706 info.arg_sql, info.unnest_source_alias, info.explode_alias, info.pos_alias
5707 ));
5708 }
5709
5710 let mut where_conditions: Vec<String> = Vec::new();
5712
5713 for info in &explode_infos {
5714 let size_expr = if is_presto {
5715 format!("CARDINALITY({})", info.arg_sql)
5716 } else {
5717 format!("ARRAY_LENGTH({})", info.arg_sql)
5718 };
5719
5720 let cond = if is_presto {
5721 format!(
5722 "{series_src}.{series_al} = {unnest_src}.{pos_al} OR ({series_src}.{series_al} > {size} AND {unnest_src}.{pos_al} = {size})",
5723 series_src = series_source_alias,
5724 series_al = series_alias,
5725 unnest_src = info.unnest_source_alias,
5726 pos_al = info.pos_alias,
5727 size = size_expr
5728 )
5729 } else {
5730 format!(
5731 "{series_al} = {pos_al} OR ({series_al} > ({size} - 1) AND {pos_al} = ({size} - 1))",
5732 series_al = series_alias,
5733 pos_al = info.pos_alias,
5734 size = size_expr
5735 )
5736 };
5737
5738 where_conditions.push(cond);
5739 }
5740
5741 let where_sql = if where_conditions.len() == 1 {
5743 where_conditions[0].clone()
5744 } else {
5745 where_conditions
5746 .iter()
5747 .map(|c| format!("({})", c))
5748 .collect::<Vec<_>>()
5749 .join(" AND ")
5750 };
5751
5752 let select_part = new_projections.join(", ");
5754
5755 let from_and_joins = if from_parts.is_empty() {
5757 format!("FROM {} {}", series_sql, cross_joins.join(" "))
5759 } else {
5760 format!(
5761 "FROM {} {} {}",
5762 from_parts.join(", "),
5763 format!("CROSS JOIN {}", series_sql),
5764 cross_joins.join(" ")
5765 )
5766 };
5767
5768 let full_sql = format!(
5769 "SELECT {} {} WHERE {}",
5770 select_part, from_and_joins, where_sql
5771 );
5772
5773 let generic_dialect = Dialect::get(DialectType::Generic);
5776 let parsed = generic_dialect.parse(&full_sql);
5777 match parsed {
5778 Ok(mut stmts) if !stmts.is_empty() => {
5779 let mut result = stmts.remove(0);
5780
5781 if is_bigquery {
5785 convert_unnest_presto_to_bigquery(&mut result);
5786 }
5787
5788 Ok(result)
5789 }
5790 _ => {
5791 Ok(Expression::Select(Box::new(select)))
5793 }
5794 }
5795}
5796
5797fn convert_unnest_presto_to_bigquery(expr: &mut Expression) {
5801 match expr {
5802 Expression::Select(ref mut select) => {
5803 if let Some(ref mut from) = select.from {
5805 for from_item in from.expressions.iter_mut() {
5806 convert_unnest_presto_to_bigquery(from_item);
5807 }
5808 }
5809 for join in select.joins.iter_mut() {
5811 convert_unnest_presto_to_bigquery(&mut join.this);
5812 }
5813 }
5814 Expression::Alias(ref alias) => {
5815 if let Expression::Unnest(ref unnest) = alias.this {
5817 if unnest.with_ordinality && alias.column_aliases.len() >= 2 {
5818 let col_alias = alias.column_aliases[0].clone();
5819 let pos_alias = alias.column_aliases[1].clone();
5820 let mut new_unnest = unnest.as_ref().clone();
5821 new_unnest.alias = Some(col_alias);
5822 new_unnest.offset_alias = Some(pos_alias);
5823 *expr = Expression::Unnest(Box::new(new_unnest));
5825 }
5826 }
5827 }
5828 _ => {}
5829 }
5830}
5831
5832fn new_name(names: &mut std::collections::HashSet<String>, base: &str) -> String {
5835 if !names.contains(base) {
5836 names.insert(base.to_string());
5837 return base.to_string();
5838 }
5839 let mut i = 2;
5840 loop {
5841 let candidate = format!("{}_{}", base, i);
5842 if !names.contains(&candidate) {
5843 names.insert(candidate.clone());
5844 return candidate;
5845 }
5846 i += 1;
5847 }
5848}
5849
5850fn expr_contains_explode(expr: &Expression) -> bool {
5852 match expr {
5853 Expression::Explode(_) => true,
5854 Expression::ExplodeOuter(_) => true,
5855 Expression::Function(f) => {
5856 let name = f.name.to_uppercase();
5857 name == "POSEXPLODE" || name == "POSEXPLODE_OUTER"
5858 }
5859 Expression::Alias(a) => expr_contains_explode(&a.this),
5860 _ => false,
5861 }
5862}
5863
5864fn find_explode_in_expr(expr: &Expression) -> Option<Expression> {
5866 match expr {
5867 Expression::Explode(uf) => Some(uf.this.clone()),
5868 Expression::ExplodeOuter(uf) => Some(uf.this.clone()),
5869 Expression::Function(f) => {
5870 let name = f.name.to_uppercase();
5871 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5872 Some(f.args[0].clone())
5873 } else {
5874 None
5875 }
5876 }
5877 Expression::Alias(a) => find_explode_in_expr(&a.this),
5878 _ => None,
5879 }
5880}
5881
5882fn extract_explode_data(
5885 expr: &Expression,
5886) -> Option<(bool, Expression, Option<String>, Option<String>)> {
5887 match expr {
5888 Expression::Explode(uf) => Some((false, uf.this.clone(), None, None)),
5890 Expression::ExplodeOuter(uf) => Some((false, uf.this.clone(), None, None)),
5891 Expression::Function(f) => {
5893 let name = f.name.to_uppercase();
5894 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5895 Some((true, f.args[0].clone(), None, None))
5896 } else {
5897 None
5898 }
5899 }
5900 Expression::Alias(a) => {
5902 match &a.this {
5903 Expression::Explode(uf) => {
5904 let alias = if !a.alias.is_empty() {
5905 Some(a.alias.name.clone())
5906 } else {
5907 None
5908 };
5909 Some((false, uf.this.clone(), alias, None))
5910 }
5911 Expression::ExplodeOuter(uf) => {
5912 let alias = if !a.alias.is_empty() {
5913 Some(a.alias.name.clone())
5914 } else {
5915 None
5916 };
5917 Some((false, uf.this.clone(), alias, None))
5918 }
5919 Expression::Function(f) => {
5920 let name = f.name.to_uppercase();
5921 if (name == "POSEXPLODE" || name == "POSEXPLODE_OUTER") && !f.args.is_empty() {
5922 if a.column_aliases.len() == 2 {
5924 let pos_alias = a.column_aliases[0].name.clone();
5925 let col_alias = a.column_aliases[1].name.clone();
5926 Some((true, f.args[0].clone(), Some(col_alias), Some(pos_alias)))
5927 } else if !a.alias.is_empty() {
5928 Some((true, f.args[0].clone(), Some(a.alias.name.clone()), None))
5930 } else {
5931 Some((true, f.args[0].clone(), None, None))
5932 }
5933 } else {
5934 None
5935 }
5936 }
5937 _ => None,
5938 }
5939 }
5940 _ => None,
5941 }
5942}
5943
5944fn get_output_name(expr: &Expression) -> Option<String> {
5946 match expr {
5947 Expression::Alias(a) => {
5948 if !a.alias.is_empty() {
5949 Some(a.alias.name.clone())
5950 } else {
5951 None
5952 }
5953 }
5954 Expression::Column(c) => Some(c.name.name.clone()),
5955 Expression::Identifier(id) => Some(id.name.clone()),
5956 _ => None,
5957 }
5958}
5959
5960fn collect_source_names(expr: &Expression, names: &mut std::collections::HashSet<String>) {
5962 match expr {
5963 Expression::Alias(a) => {
5964 if !a.alias.is_empty() {
5965 names.insert(a.alias.name.clone());
5966 }
5967 }
5968 Expression::Subquery(s) => {
5969 if let Some(ref alias) = s.alias {
5970 names.insert(alias.name.clone());
5971 }
5972 }
5973 Expression::Table(t) => {
5974 if let Some(ref alias) = t.alias {
5975 names.insert(alias.name.clone());
5976 } else {
5977 names.insert(t.name.name.clone());
5978 }
5979 }
5980 Expression::Column(c) => {
5981 names.insert(c.name.name.clone());
5982 }
5983 Expression::Identifier(id) => {
5984 names.insert(id.name.clone());
5985 }
5986 _ => {}
5987 }
5988}
5989
5990pub fn strip_unnest_column_refs(expr: Expression) -> Result<Expression> {
5993 use crate::dialects::transform_recursive;
5994 transform_recursive(expr, &strip_unnest_column_refs_single)
5995}
5996
5997fn strip_unnest_column_refs_single(expr: Expression) -> Result<Expression> {
5998 if let Expression::Select(mut select) = expr {
5999 for join in select.joins.iter_mut() {
6001 strip_unnest_from_expr(&mut join.this);
6002 }
6003 if let Some(ref mut from) = select.from {
6005 for from_item in from.expressions.iter_mut() {
6006 strip_unnest_from_expr(from_item);
6007 }
6008 }
6009 Ok(Expression::Select(select))
6010 } else {
6011 Ok(expr)
6012 }
6013}
6014
6015fn strip_unnest_from_expr(expr: &mut Expression) {
6018 if let Expression::Alias(ref mut alias) = expr {
6019 if let Expression::Unnest(ref unnest) = alias.this {
6020 let is_column_ref = matches!(&unnest.this, Expression::Column(_) | Expression::Dot(_));
6021 if is_column_ref {
6022 let inner = unnest.this.clone();
6024 alias.this = inner;
6025 }
6026 }
6027 }
6028}
6029
6030pub fn wrap_duckdb_unnest_struct(expr: Expression) -> Result<Expression> {
6033 use crate::dialects::transform_recursive;
6034 transform_recursive(expr, &wrap_duckdb_unnest_struct_single)
6035}
6036
6037fn wrap_duckdb_unnest_struct_single(expr: Expression) -> Result<Expression> {
6038 if let Expression::Select(mut select) = expr {
6039 if let Some(ref mut from) = select.from {
6041 for from_item in from.expressions.iter_mut() {
6042 try_wrap_unnest_in_subquery(from_item);
6043 }
6044 }
6045
6046 for join in select.joins.iter_mut() {
6048 try_wrap_unnest_in_subquery(&mut join.this);
6049 }
6050
6051 Ok(Expression::Select(select))
6052 } else {
6053 Ok(expr)
6054 }
6055}
6056
6057fn is_struct_array_unnest_arg(expr: &Expression) -> bool {
6059 match expr {
6060 Expression::Array(arr) => arr
6062 .expressions
6063 .iter()
6064 .any(|e| matches!(e, Expression::Struct(_))),
6065 Expression::ArrayFunc(arr) => arr
6066 .expressions
6067 .iter()
6068 .any(|e| matches!(e, Expression::Struct(_))),
6069 Expression::Cast(c) => {
6071 matches!(&c.to, DataType::Array { element_type, .. } if matches!(**element_type, DataType::Struct { .. }))
6072 }
6073 _ => false,
6074 }
6075}
6076
6077fn try_wrap_unnest_in_subquery(expr: &mut Expression) {
6080 if let Expression::Alias(ref alias) = expr {
6082 if let Expression::Unnest(ref unnest) = alias.this {
6083 if is_struct_array_unnest_arg(&unnest.this) {
6084 let unnest_clone = (**unnest).clone();
6085 let alias_name = alias.alias.clone();
6086 let new_expr = make_unnest_subquery(unnest_clone, Some(alias_name));
6087 *expr = new_expr;
6088 return;
6089 }
6090 }
6091 }
6092
6093 if let Expression::Unnest(ref unnest) = expr {
6095 if is_struct_array_unnest_arg(&unnest.this) {
6096 let unnest_clone = (**unnest).clone();
6097 let new_expr = make_unnest_subquery(unnest_clone, None);
6098 *expr = new_expr;
6099 }
6100 }
6101}
6102
6103fn make_unnest_subquery(unnest: UnnestFunc, alias: Option<Identifier>) -> Expression {
6105 let max_depth_arg = Expression::NamedArgument(Box::new(NamedArgument {
6107 name: Identifier::new("max_depth".to_string()),
6108 value: Expression::Literal(Box::new(Literal::Number("2".to_string()))),
6109 separator: NamedArgSeparator::DArrow,
6110 }));
6111
6112 let mut unnest_args = vec![unnest.this];
6113 unnest_args.extend(unnest.expressions);
6114 unnest_args.push(max_depth_arg);
6115
6116 let unnest_func =
6117 Expression::Function(Box::new(Function::new("UNNEST".to_string(), unnest_args)));
6118
6119 let mut inner_select = Select::new();
6121 inner_select.expressions = vec![unnest_func];
6122 let inner_select = Expression::Select(Box::new(inner_select));
6123
6124 let subquery = Subquery {
6126 this: inner_select,
6127 alias,
6128 column_aliases: Vec::new(),
6129 alias_explicit_as: false,
6130 alias_keyword: None,
6131 order_by: None,
6132 limit: None,
6133 offset: None,
6134 distribute_by: None,
6135 sort_by: None,
6136 cluster_by: None,
6137 lateral: false,
6138 modifiers_inside: false,
6139 trailing_comments: Vec::new(),
6140 inferred_type: None,
6141 };
6142
6143 Expression::Subquery(Box::new(subquery))
6144}
6145
6146pub fn no_limit_order_by_union(expr: Expression) -> Result<Expression> {
6158 use crate::expressions::{split_set_limit, Limit, Offset as OffsetClause, OrderBy, Star};
6159
6160 match expr {
6161 Expression::Union(mut u) => {
6162 if u.order_by.is_none() && u.limit.is_none() && u.offset.is_none() {
6165 if let Expression::Select(ref mut right_select) = u.right {
6167 if right_select.order_by.is_some()
6168 || right_select.limit.is_some()
6169 || right_select.offset.is_some()
6170 {
6171 u.order_by = right_select.order_by.take();
6173 u.limit = right_select.limit.take().map(Limit::into_set_limit);
6174 u.offset = right_select.offset.take().map(|o| Box::new(o.this));
6175 }
6176 }
6177 }
6178
6179 let has_order_or_limit =
6180 u.order_by.is_some() || u.limit.is_some() || u.offset.is_some();
6181 if has_order_or_limit {
6182 let order_by: Option<OrderBy> = u.order_by.take();
6184 let union_limit: Option<Box<Expression>> = u.limit.take();
6185 let union_offset: Option<Box<Expression>> = u.offset.take();
6186
6187 let (select_limit, select_fetch) = split_set_limit(union_limit);
6188
6189 let select_offset: Option<OffsetClause> = union_offset.map(|o| OffsetClause {
6191 this: *o,
6192 rows: None,
6193 });
6194
6195 let subquery = Subquery {
6197 this: Expression::Union(u),
6198 alias: Some(Identifier::new("_l_0")),
6199 column_aliases: Vec::new(),
6200 alias_explicit_as: true,
6201 alias_keyword: None,
6202 lateral: false,
6203 modifiers_inside: false,
6204 order_by: None,
6205 limit: None,
6206 offset: None,
6207 distribute_by: None,
6208 sort_by: None,
6209 cluster_by: None,
6210 trailing_comments: Vec::new(),
6211 inferred_type: None,
6212 };
6213
6214 let mut select = Select::default();
6216 select.expressions = vec![Expression::Star(Star {
6217 table: None,
6218 except: None,
6219 replace: None,
6220 rename: None,
6221 trailing_comments: Vec::new(),
6222 span: None,
6223 })];
6224 select.from = Some(From {
6225 expressions: vec![Expression::Subquery(Box::new(subquery))],
6226 });
6227 select.order_by = order_by;
6228 select.limit = select_limit;
6229 select.fetch = select_fetch;
6230 select.offset = select_offset;
6231
6232 Ok(Expression::Select(Box::new(select)))
6233 } else {
6234 Ok(Expression::Union(u))
6235 }
6236 }
6237 _ => Ok(expr),
6238 }
6239}
6240
6241pub fn expand_like_any(expr: Expression) -> Result<Expression> {
6249 use crate::expressions::{BinaryOp, LikeOp, Paren};
6250
6251 const LIKE_ALL_MARKER: &str = "__LIKE_ALL_EXPANSION__";
6254
6255 fn unwrap_parens(e: &Expression) -> &Expression {
6256 match e {
6257 Expression::Paren(p) => unwrap_parens(&p.this),
6258 _ => e,
6259 }
6260 }
6261
6262 fn extract_tuple_values(e: &Expression) -> Option<Vec<Expression>> {
6263 let inner = unwrap_parens(e);
6264 match inner {
6265 Expression::Tuple(t) => Some(t.expressions.clone()),
6266 _ if !matches!(e, Expression::Tuple(_)) => Some(vec![inner.clone()]),
6268 _ => None,
6269 }
6270 }
6271
6272 fn expand_like_quantifier(
6274 op: &LikeOp,
6275 values: Vec<Expression>,
6276 is_ilike: bool,
6277 combiner: fn(Expression, Expression) -> Expression,
6278 wrap_marker: bool,
6279 ) -> Expression {
6280 let num_values = values.len();
6281 let mut result: Option<Expression> = None;
6282 for val in values {
6283 let like = if is_ilike {
6284 Expression::ILike(Box::new(LikeOp {
6285 left: op.left.clone(),
6286 right: val,
6287 escape: op.escape.clone(),
6288 quantifier: None,
6289 inferred_type: None,
6290 }))
6291 } else {
6292 Expression::Like(Box::new(LikeOp {
6293 left: op.left.clone(),
6294 right: val,
6295 escape: op.escape.clone(),
6296 quantifier: None,
6297 inferred_type: None,
6298 }))
6299 };
6300 result = Some(match result {
6301 None => like,
6302 Some(prev) => combiner(prev, like),
6303 });
6304 }
6305 let expanded = result.unwrap_or_else(|| unreachable!("values is non-empty"));
6306 if wrap_marker && num_values > 1 {
6310 Expression::Paren(Box::new(Paren {
6311 this: expanded,
6312 trailing_comments: vec![LIKE_ALL_MARKER.to_string()],
6313 }))
6314 } else {
6315 expanded
6316 }
6317 }
6318
6319 fn or_combiner(a: Expression, b: Expression) -> Expression {
6320 Expression::Or(Box::new(BinaryOp::new(a, b)))
6321 }
6322
6323 fn and_combiner(a: Expression, b: Expression) -> Expression {
6324 Expression::And(Box::new(BinaryOp::new(a, b)))
6325 }
6326
6327 fn is_like_all_marker(p: &Paren) -> bool {
6328 p.trailing_comments.len() == 1 && p.trailing_comments[0] == LIKE_ALL_MARKER
6329 }
6330
6331 let result = transform_recursive(expr, &|e| {
6339 match e {
6340 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6342 if let Some(values) = extract_tuple_values(&op.right) {
6343 if values.is_empty() {
6344 return Ok(e);
6345 }
6346 Ok(expand_like_quantifier(
6347 op,
6348 values,
6349 false,
6350 or_combiner,
6351 false,
6352 ))
6353 } else {
6354 Ok(e)
6355 }
6356 }
6357 Expression::Like(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6359 if let Some(values) = extract_tuple_values(&op.right) {
6360 if values.is_empty() {
6361 return Ok(e);
6362 }
6363 Ok(expand_like_quantifier(
6364 op,
6365 values,
6366 false,
6367 and_combiner,
6368 true,
6369 ))
6370 } else {
6371 Ok(e)
6372 }
6373 }
6374 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ANY") => {
6376 if let Some(values) = extract_tuple_values(&op.right) {
6377 if values.is_empty() {
6378 return Ok(e);
6379 }
6380 Ok(expand_like_quantifier(op, values, true, or_combiner, false))
6381 } else {
6382 Ok(e)
6383 }
6384 }
6385 Expression::ILike(ref op) if op.quantifier.as_deref() == Some("ALL") => {
6387 if let Some(values) = extract_tuple_values(&op.right) {
6388 if values.is_empty() {
6389 return Ok(e);
6390 }
6391 Ok(expand_like_quantifier(op, values, true, and_combiner, true))
6392 } else {
6393 Ok(e)
6394 }
6395 }
6396 Expression::And(mut op) => {
6401 if matches!(&op.left, Expression::Or(_)) {
6402 op.left = Expression::Paren(Box::new(Paren {
6403 this: op.left,
6404 trailing_comments: vec![],
6405 }));
6406 }
6407 if matches!(&op.right, Expression::Or(_)) {
6408 op.right = Expression::Paren(Box::new(Paren {
6409 this: op.right,
6410 trailing_comments: vec![],
6411 }));
6412 }
6413 Ok(Expression::And(op))
6414 }
6415 Expression::Or(mut op) => {
6418 if let Expression::Paren(ref mut p) = op.left {
6419 if is_like_all_marker(p) {
6420 p.trailing_comments.clear();
6421 }
6422 }
6423 if let Expression::Paren(ref mut p) = op.right {
6424 if is_like_all_marker(p) {
6425 p.trailing_comments.clear();
6426 }
6427 }
6428 Ok(Expression::Or(op))
6429 }
6430 _ => Ok(e),
6431 }
6432 })?;
6433
6434 transform_recursive(result, &|e| {
6438 if let Expression::Paren(p) = &e {
6439 if is_like_all_marker(p) {
6440 let Expression::Paren(p) = e else {
6441 unreachable!()
6442 };
6443 return Ok(p.this);
6444 }
6445 }
6446 Ok(e)
6447 })
6448}
6449
6450pub fn qualify_derived_table_outputs(expr: Expression) -> Result<Expression> {
6458 use crate::expressions::Alias;
6459
6460 fn add_self_aliases_to_select(select: &mut Select) {
6461 let new_expressions: Vec<Expression> = select
6462 .expressions
6463 .iter()
6464 .map(|e| {
6465 match e {
6466 Expression::Column(col) => {
6468 let alias_name = col.name.clone();
6469 Expression::Alias(Box::new(Alias {
6470 this: e.clone(),
6471 alias: alias_name,
6472 column_aliases: Vec::new(),
6473 alias_explicit_as: false,
6474 alias_keyword: None,
6475 pre_alias_comments: Vec::new(),
6476 trailing_comments: Vec::new(),
6477 inferred_type: None,
6478 }))
6479 }
6480 _ => e.clone(),
6482 }
6483 })
6484 .collect();
6485 select.expressions = new_expressions;
6486 }
6487
6488 fn walk_and_qualify(expr: &mut Expression) {
6489 match expr {
6490 Expression::Select(ref mut select) => {
6491 if let Some(ref mut from) = select.from {
6493 for e in from.expressions.iter_mut() {
6494 qualify_subquery_expr(e);
6495 walk_and_qualify(e);
6496 }
6497 }
6498 for join in select.joins.iter_mut() {
6500 qualify_subquery_expr(&mut join.this);
6501 walk_and_qualify(&mut join.this);
6502 }
6503 for e in select.expressions.iter_mut() {
6505 walk_and_qualify(e);
6506 }
6507 if let Some(ref mut w) = select.where_clause {
6509 walk_and_qualify(&mut w.this);
6510 }
6511 }
6512 Expression::Subquery(ref mut subquery) => {
6513 walk_and_qualify(&mut subquery.this);
6514 }
6515 Expression::Union(ref mut u) => {
6516 walk_and_qualify(&mut u.left);
6517 walk_and_qualify(&mut u.right);
6518 }
6519 Expression::Intersect(ref mut i) => {
6520 walk_and_qualify(&mut i.left);
6521 walk_and_qualify(&mut i.right);
6522 }
6523 Expression::Except(ref mut e) => {
6524 walk_and_qualify(&mut e.left);
6525 walk_and_qualify(&mut e.right);
6526 }
6527 Expression::Cte(ref mut cte) => {
6528 walk_and_qualify(&mut cte.this);
6529 }
6530 _ => {}
6531 }
6532 }
6533
6534 fn qualify_subquery_expr(expr: &mut Expression) {
6535 match expr {
6536 Expression::Subquery(ref mut subquery) => {
6537 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
6539 if let Expression::Select(ref mut inner_select) = subquery.this {
6540 let has_star = inner_select
6542 .expressions
6543 .iter()
6544 .any(|e| matches!(e, Expression::Star(_)));
6545 if !has_star {
6546 add_self_aliases_to_select(inner_select);
6547 }
6548 }
6549 }
6550 walk_and_qualify(&mut subquery.this);
6552 }
6553 Expression::Alias(ref mut alias) => {
6554 qualify_subquery_expr(&mut alias.this);
6555 }
6556 _ => {}
6557 }
6558 }
6559
6560 let mut result = expr;
6561 walk_and_qualify(&mut result);
6562
6563 if let Expression::Select(ref mut select) = result {
6565 if let Some(ref mut with) = select.with {
6566 for cte in with.ctes.iter_mut() {
6567 if cte.columns.is_empty() {
6569 walk_and_qualify(&mut cte.this);
6571 }
6572 }
6573 }
6574 }
6575
6576 Ok(result)
6577}
6578
6579#[cfg(test)]
6580mod tests {
6581 use super::*;
6582 use crate::dialects::{Dialect, DialectType};
6583 use crate::expressions::Column;
6584
6585 fn gen(expr: &Expression) -> String {
6586 let dialect = Dialect::get(DialectType::Generic);
6587 dialect.generate(expr).unwrap()
6588 }
6589
6590 #[test]
6591 fn test_preprocess() {
6592 let expr = Expression::Boolean(BooleanLiteral { value: true });
6593 let result = preprocess(expr, &[replace_bool_with_int]).unwrap();
6594 assert!(
6595 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6596 );
6597 }
6598
6599 #[test]
6600 fn test_preprocess_chain() {
6601 let expr = Expression::Boolean(BooleanLiteral { value: true });
6603 let transforms: Vec<fn(Expression) -> Result<Expression>> =
6605 vec![replace_bool_with_int, replace_int_with_bool];
6606 let result = preprocess(expr, &transforms).unwrap();
6607 if let Expression::Boolean(b) = result {
6610 assert!(b.value);
6611 } else {
6612 panic!("Expected boolean literal");
6613 }
6614 }
6615
6616 #[test]
6617 fn test_unnest_to_explode() {
6618 let unnest = Expression::Unnest(Box::new(UnnestFunc {
6619 this: Expression::boxed_column(Column {
6620 name: Identifier::new("arr".to_string()),
6621 table: None,
6622 join_mark: false,
6623 trailing_comments: vec![],
6624 span: None,
6625 inferred_type: None,
6626 }),
6627 expressions: Vec::new(),
6628 with_ordinality: false,
6629 alias: None,
6630 offset_alias: None,
6631 inferred_type: None,
6632 }));
6633
6634 let result = unnest_to_explode(unnest).unwrap();
6635 assert!(matches!(result, Expression::Explode(_)));
6636 }
6637
6638 #[test]
6639 fn test_explode_to_unnest() {
6640 let explode = Expression::Explode(Box::new(UnaryFunc {
6641 this: Expression::boxed_column(Column {
6642 name: Identifier::new("arr".to_string()),
6643 table: None,
6644 join_mark: false,
6645 trailing_comments: vec![],
6646 span: None,
6647 inferred_type: None,
6648 }),
6649 original_name: None,
6650 inferred_type: None,
6651 }));
6652
6653 let result = explode_to_unnest(explode).unwrap();
6654 assert!(matches!(result, Expression::Unnest(_)));
6655 }
6656
6657 #[test]
6658 fn test_replace_bool_with_int() {
6659 let true_expr = Expression::Boolean(BooleanLiteral { value: true });
6660 let result = replace_bool_with_int(true_expr).unwrap();
6661 if let Expression::Literal(lit) = result {
6662 if let Literal::Number(n) = lit.as_ref() {
6663 assert_eq!(n, "1");
6664 }
6665 } else {
6666 panic!("Expected number literal");
6667 }
6668
6669 let false_expr = Expression::Boolean(BooleanLiteral { value: false });
6670 let result = replace_bool_with_int(false_expr).unwrap();
6671 if let Expression::Literal(lit) = result {
6672 if let Literal::Number(n) = lit.as_ref() {
6673 assert_eq!(n, "0");
6674 }
6675 } else {
6676 panic!("Expected number literal");
6677 }
6678 }
6679
6680 #[test]
6681 fn test_replace_int_with_bool() {
6682 let one_expr = Expression::Literal(Box::new(Literal::Number("1".to_string())));
6683 let result = replace_int_with_bool(one_expr).unwrap();
6684 if let Expression::Boolean(b) = result {
6685 assert!(b.value);
6686 } else {
6687 panic!("Expected boolean true");
6688 }
6689
6690 let zero_expr = Expression::Literal(Box::new(Literal::Number("0".to_string())));
6691 let result = replace_int_with_bool(zero_expr).unwrap();
6692 if let Expression::Boolean(b) = result {
6693 assert!(!b.value);
6694 } else {
6695 panic!("Expected boolean false");
6696 }
6697
6698 let two_expr = Expression::Literal(Box::new(Literal::Number("2".to_string())));
6700 let result = replace_int_with_bool(two_expr).unwrap();
6701 assert!(
6702 matches!(result, Expression::Literal(lit) if matches!(lit.as_ref(), Literal::Number(_)))
6703 );
6704 }
6705
6706 #[test]
6707 fn test_strip_data_type_params() {
6708 let decimal = DataType::Decimal {
6710 precision: Some(10),
6711 scale: Some(2),
6712 };
6713 let stripped = strip_data_type_params(decimal);
6714 assert_eq!(
6715 stripped,
6716 DataType::Decimal {
6717 precision: None,
6718 scale: None
6719 }
6720 );
6721
6722 let varchar = DataType::VarChar {
6724 length: Some(255),
6725 parenthesized_length: false,
6726 };
6727 let stripped = strip_data_type_params(varchar);
6728 assert_eq!(
6729 stripped,
6730 DataType::VarChar {
6731 length: None,
6732 parenthesized_length: false
6733 }
6734 );
6735
6736 let char_type = DataType::Char { length: Some(10) };
6738 let stripped = strip_data_type_params(char_type);
6739 assert_eq!(stripped, DataType::Char { length: None });
6740
6741 let timestamp = DataType::Timestamp {
6743 precision: Some(6),
6744 timezone: true,
6745 };
6746 let stripped = strip_data_type_params(timestamp);
6747 assert_eq!(
6748 stripped,
6749 DataType::Timestamp {
6750 precision: None,
6751 timezone: true
6752 }
6753 );
6754
6755 let array = DataType::Array {
6757 element_type: Box::new(DataType::VarChar {
6758 length: Some(100),
6759 parenthesized_length: false,
6760 }),
6761 dimension: None,
6762 };
6763 let stripped = strip_data_type_params(array);
6764 assert_eq!(
6765 stripped,
6766 DataType::Array {
6767 element_type: Box::new(DataType::VarChar {
6768 length: None,
6769 parenthesized_length: false
6770 }),
6771 dimension: None,
6772 }
6773 );
6774
6775 let text = DataType::Text;
6777 let stripped = strip_data_type_params(text);
6778 assert_eq!(stripped, DataType::Text);
6779 }
6780
6781 #[test]
6782 fn test_remove_precision_parameterized_types_cast() {
6783 let cast_expr = Expression::Cast(Box::new(Cast {
6785 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6786 to: DataType::Decimal {
6787 precision: Some(10),
6788 scale: Some(2),
6789 },
6790 trailing_comments: vec![],
6791 double_colon_syntax: false,
6792 format: None,
6793 default: None,
6794 inferred_type: None,
6795 }));
6796
6797 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6798 if let Expression::Cast(cast) = result {
6799 assert_eq!(
6800 cast.to,
6801 DataType::Decimal {
6802 precision: None,
6803 scale: None
6804 }
6805 );
6806 } else {
6807 panic!("Expected Cast expression");
6808 }
6809 }
6810
6811 #[test]
6812 fn test_remove_precision_parameterized_types_varchar() {
6813 let cast_expr = Expression::Cast(Box::new(Cast {
6815 this: Expression::Literal(Box::new(Literal::String("hello".to_string()))),
6816 to: DataType::VarChar {
6817 length: Some(10),
6818 parenthesized_length: false,
6819 },
6820 trailing_comments: vec![],
6821 double_colon_syntax: false,
6822 format: None,
6823 default: None,
6824 inferred_type: None,
6825 }));
6826
6827 let result = remove_precision_parameterized_types(cast_expr).unwrap();
6828 if let Expression::Cast(cast) = result {
6829 assert_eq!(
6830 cast.to,
6831 DataType::VarChar {
6832 length: None,
6833 parenthesized_length: false
6834 }
6835 );
6836 } else {
6837 panic!("Expected Cast expression");
6838 }
6839 }
6840
6841 #[test]
6842 fn test_remove_precision_direct_cast() {
6843 let cast = Expression::Cast(Box::new(Cast {
6847 this: Expression::Literal(Box::new(Literal::Number("1".to_string()))),
6848 to: DataType::Decimal {
6849 precision: Some(10),
6850 scale: Some(2),
6851 },
6852 trailing_comments: vec![],
6853 double_colon_syntax: false,
6854 format: None,
6855 default: None,
6856 inferred_type: None,
6857 }));
6858
6859 let transformed = remove_precision_parameterized_types(cast).unwrap();
6860 let generated = gen(&transformed);
6861
6862 assert!(generated.contains("DECIMAL"));
6864 assert!(!generated.contains("(10"));
6865 }
6866
6867 #[test]
6868 fn test_epoch_cast_to_ts() {
6869 let cast_expr = Expression::Cast(Box::new(Cast {
6871 this: Expression::Literal(Box::new(Literal::String("epoch".to_string()))),
6872 to: DataType::Timestamp {
6873 precision: None,
6874 timezone: false,
6875 },
6876 trailing_comments: vec![],
6877 double_colon_syntax: false,
6878 format: None,
6879 default: None,
6880 inferred_type: None,
6881 }));
6882
6883 let result = epoch_cast_to_ts(cast_expr).unwrap();
6884 if let Expression::Cast(cast) = result {
6885 if let Expression::Literal(lit) = cast.this {
6886 if let Literal::String(s) = lit.as_ref() {
6887 assert_eq!(s, "1970-01-01 00:00:00");
6888 }
6889 } else {
6890 panic!("Expected string literal");
6891 }
6892 } else {
6893 panic!("Expected Cast expression");
6894 }
6895 }
6896
6897 #[test]
6898 fn test_epoch_cast_to_ts_preserves_non_epoch() {
6899 let cast_expr = Expression::Cast(Box::new(Cast {
6901 this: Expression::Literal(Box::new(Literal::String("2024-01-15".to_string()))),
6902 to: DataType::Timestamp {
6903 precision: None,
6904 timezone: false,
6905 },
6906 trailing_comments: vec![],
6907 double_colon_syntax: false,
6908 format: None,
6909 default: None,
6910 inferred_type: None,
6911 }));
6912
6913 let result = epoch_cast_to_ts(cast_expr).unwrap();
6914 if let Expression::Cast(cast) = result {
6915 if let Expression::Literal(lit) = cast.this {
6916 if let Literal::String(s) = lit.as_ref() {
6917 assert_eq!(s, "2024-01-15");
6918 }
6919 } else {
6920 panic!("Expected string literal");
6921 }
6922 } else {
6923 panic!("Expected Cast expression");
6924 }
6925 }
6926
6927 #[test]
6928 fn test_unqualify_columns() {
6929 let col = Expression::boxed_column(Column {
6931 name: Identifier::new("id".to_string()),
6932 table: Some(Identifier::new("users".to_string())),
6933 join_mark: false,
6934 trailing_comments: vec![],
6935 span: None,
6936 inferred_type: None,
6937 });
6938
6939 let result = unqualify_columns(col).unwrap();
6940 if let Expression::Column(c) = result {
6941 assert!(c.table.is_none());
6942 assert_eq!(c.name.name, "id");
6943 } else {
6944 panic!("Expected Column expression");
6945 }
6946 }
6947
6948 #[test]
6949 fn test_is_temporal_type() {
6950 assert!(is_temporal_type(&DataType::Date));
6951 assert!(is_temporal_type(&DataType::Timestamp {
6952 precision: None,
6953 timezone: false
6954 }));
6955 assert!(is_temporal_type(&DataType::Time {
6956 precision: None,
6957 timezone: false
6958 }));
6959 assert!(!is_temporal_type(&DataType::Int {
6960 length: None,
6961 integer_spelling: false
6962 }));
6963 assert!(!is_temporal_type(&DataType::VarChar {
6964 length: None,
6965 parenthesized_length: false
6966 }));
6967 }
6968
6969 #[test]
6970 fn test_eliminate_semi_join_basic() {
6971 use crate::expressions::{Join, TableRef};
6972
6973 let select = Expression::Select(Box::new(Select {
6975 vertica: None,
6976 expressions: vec![Expression::boxed_column(Column {
6977 name: Identifier::new("a".to_string()),
6978 table: None,
6979 join_mark: false,
6980 trailing_comments: vec![],
6981 span: None,
6982 inferred_type: None,
6983 })],
6984 from: Some(From {
6985 expressions: vec![Expression::Table(Box::new(TableRef::new("t1")))],
6986 }),
6987 joins: vec![Join {
6988 this: Expression::Table(Box::new(TableRef::new("t2"))),
6989 kind: JoinKind::Semi,
6990 on: Some(Expression::Eq(Box::new(BinaryOp {
6991 left: Expression::boxed_column(Column {
6992 name: Identifier::new("x".to_string()),
6993 table: None,
6994 join_mark: false,
6995 trailing_comments: vec![],
6996 span: None,
6997 inferred_type: None,
6998 }),
6999 right: Expression::boxed_column(Column {
7000 name: Identifier::new("y".to_string()),
7001 table: None,
7002 join_mark: false,
7003 trailing_comments: vec![],
7004 span: None,
7005 inferred_type: None,
7006 }),
7007 left_comments: vec![],
7008 operator_comments: vec![],
7009 trailing_comments: vec![],
7010 inferred_type: None,
7011 }))),
7012 using: vec![],
7013 use_inner_keyword: false,
7014 use_outer_keyword: false,
7015 deferred_condition: false,
7016 join_hint: None,
7017 match_condition: None,
7018 pivots: Vec::new(),
7019 comments: Vec::new(),
7020 nesting_group: 0,
7021 directed: false,
7022 }],
7023 ..Select::new()
7024 }));
7025
7026 let result = eliminate_semi_and_anti_joins(select).unwrap();
7027 if let Expression::Select(s) = result {
7028 assert!(s.joins.is_empty());
7030 assert!(s.where_clause.is_some());
7032 } else {
7033 panic!("Expected Select expression");
7034 }
7035 }
7036
7037 #[test]
7038 fn test_no_ilike_sql() {
7039 use crate::expressions::LikeOp;
7040
7041 let ilike_expr = Expression::ILike(Box::new(LikeOp {
7043 left: Expression::boxed_column(Column {
7044 name: Identifier::new("name".to_string()),
7045 table: None,
7046 join_mark: false,
7047 trailing_comments: vec![],
7048 span: None,
7049 inferred_type: None,
7050 }),
7051 right: Expression::Literal(Box::new(Literal::String("%test%".to_string()))),
7052 escape: None,
7053 quantifier: None,
7054 inferred_type: None,
7055 }));
7056
7057 let result = no_ilike_sql(ilike_expr).unwrap();
7058 if let Expression::Like(like) = result {
7059 if let Expression::Function(f) = &like.left {
7061 assert_eq!(f.name, "LOWER");
7062 } else {
7063 panic!("Expected LOWER function on left");
7064 }
7065 if let Expression::Function(f) = &like.right {
7067 assert_eq!(f.name, "LOWER");
7068 } else {
7069 panic!("Expected LOWER function on right");
7070 }
7071 } else {
7072 panic!("Expected Like expression");
7073 }
7074 }
7075
7076 #[test]
7077 fn test_no_trycast_sql() {
7078 let trycast_expr = Expression::TryCast(Box::new(Cast {
7080 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
7081 to: DataType::Int {
7082 length: None,
7083 integer_spelling: false,
7084 },
7085 trailing_comments: vec![],
7086 double_colon_syntax: false,
7087 format: None,
7088 default: None,
7089 inferred_type: None,
7090 }));
7091
7092 let result = no_trycast_sql(trycast_expr).unwrap();
7093 assert!(matches!(result, Expression::Cast(_)));
7094 }
7095
7096 #[test]
7097 fn test_no_safe_cast_sql() {
7098 let safe_cast_expr = Expression::SafeCast(Box::new(Cast {
7100 this: Expression::Literal(Box::new(Literal::String("123".to_string()))),
7101 to: DataType::Int {
7102 length: None,
7103 integer_spelling: false,
7104 },
7105 trailing_comments: vec![],
7106 double_colon_syntax: false,
7107 format: None,
7108 default: None,
7109 inferred_type: None,
7110 }));
7111
7112 let result = no_safe_cast_sql(safe_cast_expr).unwrap();
7113 assert!(matches!(result, Expression::Cast(_)));
7114 }
7115
7116 #[test]
7117 fn test_explode_to_unnest_presto() {
7118 let spark = Dialect::get(DialectType::Spark);
7119 let result = spark
7120 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::Presto)
7121 .unwrap();
7122 assert_eq!(
7123 result[0],
7124 "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))"
7125 );
7126 }
7127
7128 #[test]
7129 fn test_explode_to_unnest_bigquery() {
7130 let spark = Dialect::get(DialectType::Spark);
7131 let result = spark
7132 .transpile("SELECT EXPLODE(x) FROM tbl", DialectType::BigQuery)
7133 .unwrap();
7134 assert_eq!(
7135 result[0],
7136 "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))"
7137 );
7138 }
7139}