1use super::{DialectImpl, DialectType};
14use crate::error::Result;
15use crate::expressions::{
16 Alias, BinaryOp, Cast, Column, Cte, DataType, Exists, Expression, From, Function, Identifier,
17 In, Join, JoinKind, LikeOp, Literal, Null, Over, Paren, QuantifiedOp, Select, Star,
18 StringAggFunc, Subquery, TrimFunc, TrimPosition, Tuple, UnaryFunc, Values, Where,
19 WindowFunction,
20};
21#[cfg(feature = "generate")]
22use crate::generator::GeneratorConfig;
23use crate::tokens::TokenizerConfig;
24use std::collections::HashMap;
25
26pub struct TSQLDialect;
28
29impl DialectImpl for TSQLDialect {
30 fn dialect_type(&self) -> DialectType {
31 DialectType::TSQL
32 }
33
34 fn tokenizer_config(&self) -> TokenizerConfig {
35 let mut config = TokenizerConfig::default();
36 config.identifiers.insert('[', ']');
38 config.identifiers.insert('"', '"');
40 config.hex_number_strings = true;
42 config
43 }
44
45 #[cfg(feature = "generate")]
46
47 fn generator_config(&self) -> GeneratorConfig {
48 use crate::generator::IdentifierQuoteStyle;
49 GeneratorConfig {
50 identifier_quote: '[',
52 identifier_quote_style: IdentifierQuoteStyle::BRACKET,
53 dialect: Some(DialectType::TSQL),
54 limit_fetch_style: crate::generator::LimitFetchStyle::FetchFirst,
57 null_ordering_supported: false,
59 aggregate_filter_supported: false,
61 supports_select_into: true,
63 alter_table_include_column_keyword: false,
65 computed_column_with_type: false,
67 cte_recursive_keyword_required: false,
69 ensure_bools: true,
71 supports_single_arg_concat: false,
73 tablesample_seed_keyword: "REPEATABLE",
75 json_path_bracketed_key_supported: false,
77 supports_to_number: false,
79 set_op_modifiers: false,
81 copy_params_eq_required: true,
83 except_intersect_support_all_clause: false,
85 alter_set_wrapped: true,
87 try_supported: true,
89 nvl2_supported: false,
91 parameter_default_equals: true,
93 supports_window_exclude: false,
95 multi_arg_distinct: false,
97 locking_reads_supported: false,
99 ..Default::default()
100 }
101 }
102
103 #[cfg(feature = "transpile")]
104
105 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
106 if let Expression::CreateTable(mut ct) = expr {
108 for col in &mut ct.columns {
109 if let Ok(Expression::DataType(new_dt)) =
110 self.transform_data_type(col.data_type.clone())
111 {
112 col.data_type = new_dt;
113 }
114 }
115 return Ok(Expression::CreateTable(ct));
116 }
117
118 match expr {
119 Expression::Select(mut select) => {
124 select.expressions = select
125 .expressions
126 .into_iter()
127 .map(|e| {
128 match e {
129 Expression::Eq(op) => {
130 match &op.left {
133 Expression::Column(col)
134 if col.table.is_none()
135 && !col.name.name.starts_with('@') =>
136 {
137 Expression::Alias(Box::new(Alias {
138 this: op.right,
139 alias: col.name.clone(),
140 column_aliases: Vec::new(),
141 alias_explicit_as: false,
142 alias_keyword: None,
143 pre_alias_comments: Vec::new(),
144 trailing_comments: Vec::new(),
145 inferred_type: None,
146 }))
147 }
148 Expression::Identifier(ident)
149 if !ident.name.starts_with('@') =>
150 {
151 Expression::Alias(Box::new(Alias {
152 this: op.right,
153 alias: ident.clone(),
154 column_aliases: Vec::new(),
155 alias_explicit_as: false,
156 alias_keyword: None,
157 pre_alias_comments: Vec::new(),
158 trailing_comments: Vec::new(),
159 inferred_type: None,
160 }))
161 }
162 _ => Expression::Eq(op),
163 }
164 }
165 other => other,
166 }
167 })
168 .collect();
169
170 Self::normalize_frame_incompatible_window_functions(&mut select);
171
172 let outer_qualifier = Self::single_select_source_qualifier(&select);
173
174 select.expressions = select
175 .expressions
176 .into_iter()
177 .map(|expression| {
178 Self::rewrite_tuple_in_subquery_predicates(
179 expression,
180 outer_qualifier.as_ref(),
181 false,
182 )
183 })
184 .collect();
185
186 for join in &mut select.joins {
187 if let Some(on) = join.on.take() {
188 join.on = Some(Self::rewrite_tuple_in_subquery_predicates(
189 on,
190 outer_qualifier.as_ref(),
191 false,
192 ));
193 }
194 if let Some(match_condition) = join.match_condition.take() {
195 join.match_condition = Some(Self::rewrite_tuple_in_subquery_predicates(
196 match_condition,
197 outer_qualifier.as_ref(),
198 false,
199 ));
200 }
201 }
202
203 if let Some(ref mut prewhere) = select.prewhere {
204 *prewhere = Self::rewrite_tuple_in_subquery_predicates(
205 std::mem::replace(prewhere, Expression::Null(Null)),
206 outer_qualifier.as_ref(),
207 false,
208 );
209 }
210
211 if let Some(ref mut where_clause) = select.where_clause {
212 where_clause.this = Self::rewrite_tuple_in_subquery_predicates(
213 std::mem::replace(&mut where_clause.this, Expression::Null(Null)),
214 outer_qualifier.as_ref(),
215 false,
216 );
217 }
218
219 if let Some(ref mut having) = select.having {
220 having.this = Self::rewrite_tuple_in_subquery_predicates(
221 std::mem::replace(&mut having.this, Expression::Null(Null)),
222 outer_qualifier.as_ref(),
223 false,
224 );
225 }
226
227 if let Some(ref mut qualify) = select.qualify {
228 qualify.this = Self::rewrite_tuple_in_subquery_predicates(
229 std::mem::replace(&mut qualify.this, Expression::Null(Null)),
230 outer_qualifier.as_ref(),
231 false,
232 );
233 }
234
235 if let Some(ref mut with) = select.with {
237 with.ctes = with
238 .ctes
239 .drain(..)
240 .map(|cte| self.transform_cte_inner(cte))
241 .collect();
242 }
243
244 Self::rewrite_comma_lateral_sources_to_joins(&mut select);
245
246 Ok(Expression::Select(select))
247 }
248
249 Expression::DataType(dt) => self.transform_data_type(dt),
251
252 Expression::IsTrue(it) => Ok(Self::boolean_test_predicate(it.this, true, it.not)),
256 Expression::IsFalse(it) => Ok(Self::boolean_test_predicate(it.this, false, it.not)),
257
258 Expression::In(mut in_expr) if in_expr.not => {
262 in_expr.not = false;
263 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
264 this: Expression::In(in_expr),
265 inferred_type: None,
266 })))
267 }
268
269 Expression::Coalesce(f) if f.expressions.len() == 2 => Ok(Expression::Function(
272 Box::new(Function::new("ISNULL".to_string(), f.expressions)),
273 )),
274
275 Expression::Nvl(f) => Ok(Expression::Function(Box::new(Function::new(
277 "ISNULL".to_string(),
278 vec![f.this, f.expression],
279 )))),
280
281 Expression::GroupConcat(f) => Ok(Expression::StringAgg(Box::new(StringAggFunc {
283 this: f.this,
284 separator: f.separator,
285 order_by: f.order_by,
286 distinct: f.distinct,
287 filter: f.filter,
288 limit: None,
289 inferred_type: None,
290 }))),
291
292 Expression::ListAgg(f) => Ok(Expression::StringAgg(Box::new(StringAggFunc {
294 this: f.this,
295 separator: f.separator,
296 order_by: f.order_by,
297 distinct: f.distinct,
298 filter: f.filter,
299 limit: None,
300 inferred_type: None,
301 }))),
302
303 Expression::Sum(f) => Ok(Expression::Sum(Self::without_inert_ordering(f))),
307 Expression::Avg(f) => Ok(Expression::Avg(Self::without_inert_ordering(f))),
308 Expression::Min(f) => Ok(Expression::Min(Self::without_inert_ordering(f))),
309 Expression::Max(f) => Ok(Expression::Max(Self::without_inert_ordering(f))),
310 Expression::AnyValue(f) => Ok(Expression::Max(Self::without_inert_ordering(f))),
311 Expression::ApproxCountDistinct(f) => Ok(Expression::ApproxCountDistinct(
312 Self::without_inert_ordering(f),
313 )),
314
315 Expression::LogicalAnd(f) => Self::transform_logical_aggregate(f.this, f.filter, "MIN"),
318 Expression::LogicalOr(f) => Self::transform_logical_aggregate(f.this, f.filter, "MAX"),
319
320 Expression::WindowFunction(f) => Ok(Self::reassociate_logical_aggregate_window(*f)),
324
325 Expression::TryCast(c) => Ok(Expression::TryCast(c)),
327
328 Expression::SafeCast(c) => Ok(Expression::TryCast(c)),
330
331 Expression::ILike(op) => {
333 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left)));
336 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right)));
337 Ok(Expression::Like(Box::new(LikeOp {
338 left: lower_left,
339 right: lower_right,
340 escape: op.escape,
341 quantifier: op.quantifier,
342 inferred_type: None,
343 })))
344 }
345
346 Expression::Concat(op) => {
349 Ok(Expression::Add(op))
351 }
352
353 Expression::Random(_) => Ok(Expression::Rand(Box::new(crate::expressions::Rand {
355 seed: None,
356 lower: None,
357 upper: None,
358 }))),
359
360 Expression::Unnest(f) => {
362 Ok(Expression::Function(Box::new(Function::new(
365 "OPENJSON".to_string(),
366 vec![f.this],
367 ))))
368 }
369
370 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
372 "OPENJSON".to_string(),
373 vec![f.this],
374 )))),
375
376 Expression::Join(join) => Ok(Expression::Join(Box::new(
378 Self::transform_lateral_join_to_apply(*join)?,
379 ))),
380
381 Expression::Length(f) => Ok(Expression::Function(Box::new(Function::new(
383 "LEN".to_string(),
384 vec![f.this],
385 )))),
386
387 Expression::Stddev(f) => Ok(Expression::Function(Box::new(Function::new(
389 "STDEV".to_string(),
390 vec![f.this],
391 )))),
392 Expression::StddevSamp(f) => Ok(Expression::Function(Box::new(Function::new(
393 "STDEV".to_string(),
394 vec![f.this],
395 )))),
396 Expression::StddevPop(f) => Ok(Expression::Function(Box::new(Function::new(
397 "STDEVP".to_string(),
398 vec![f.this],
399 )))),
400
401 Expression::Boolean(b) => {
403 let value = if b.value { 1 } else { 0 };
404 Ok(Expression::Literal(Box::new(
405 crate::expressions::Literal::Number(value.to_string()),
406 )))
407 }
408
409 Expression::Ln(f) => Ok(Expression::Function(Box::new(Function::new(
411 "LOG".to_string(),
412 vec![f.this],
413 )))),
414
415 Expression::CurrentDate(_) => Ok(Self::cast_getdate_to(DataType::Date)),
418
419 Expression::CurrentTime(_) => Ok(Self::cast_getdate_to(DataType::Time {
421 precision: None,
422 timezone: false,
423 })),
424
425 Expression::CurrentTimestamp(_) => Ok(Self::getdate()),
427
428 Expression::Localtimestamp(_) => Ok(Self::getdate()),
430
431 Expression::MakeDate(f) => Ok(Self::function(
433 "DATEFROMPARTS",
434 vec![f.year, f.month, f.day],
435 )),
436
437 Expression::DateDiff(f) => {
439 let unit_str = match f.unit {
441 Some(crate::expressions::IntervalUnit::Year) => "YEAR",
442 Some(crate::expressions::IntervalUnit::Quarter) => "QUARTER",
443 Some(crate::expressions::IntervalUnit::Month) => "MONTH",
444 Some(crate::expressions::IntervalUnit::Week) => "WEEK",
445 Some(crate::expressions::IntervalUnit::Day) => "DAY",
446 Some(crate::expressions::IntervalUnit::Hour) => "HOUR",
447 Some(crate::expressions::IntervalUnit::Minute) => "MINUTE",
448 Some(crate::expressions::IntervalUnit::Second) => "SECOND",
449 Some(crate::expressions::IntervalUnit::Millisecond) => "MILLISECOND",
450 Some(crate::expressions::IntervalUnit::Microsecond) => "MICROSECOND",
451 Some(crate::expressions::IntervalUnit::Nanosecond) => "NANOSECOND",
452 None => "DAY",
453 };
454 let unit = Expression::Identifier(crate::expressions::Identifier {
455 name: unit_str.to_string(),
456 quoted: false,
457 trailing_comments: Vec::new(),
458 span: None,
459 });
460 Ok(Expression::Function(Box::new(Function::new(
461 "DATEDIFF".to_string(),
462 vec![unit, f.expression, f.this], ))))
464 }
465
466 Expression::DateAdd(f) => {
468 let unit_str = match f.unit {
469 crate::expressions::IntervalUnit::Year => "YEAR",
470 crate::expressions::IntervalUnit::Quarter => "QUARTER",
471 crate::expressions::IntervalUnit::Month => "MONTH",
472 crate::expressions::IntervalUnit::Week => "WEEK",
473 crate::expressions::IntervalUnit::Day => "DAY",
474 crate::expressions::IntervalUnit::Hour => "HOUR",
475 crate::expressions::IntervalUnit::Minute => "MINUTE",
476 crate::expressions::IntervalUnit::Second => "SECOND",
477 crate::expressions::IntervalUnit::Millisecond => "MILLISECOND",
478 crate::expressions::IntervalUnit::Microsecond => "MICROSECOND",
479 crate::expressions::IntervalUnit::Nanosecond => "NANOSECOND",
480 };
481 let unit = Expression::Identifier(crate::expressions::Identifier {
482 name: unit_str.to_string(),
483 quoted: false,
484 trailing_comments: Vec::new(),
485 span: None,
486 });
487 Ok(Expression::Function(Box::new(Function::new(
488 "DATEADD".to_string(),
489 vec![unit, f.interval, f.this],
490 ))))
491 }
492
493 Expression::Uuid(_) => Ok(Expression::Function(Box::new(Function::new(
496 "NEWID".to_string(),
497 vec![],
498 )))),
499
500 Expression::IfFunc(f) => {
503 let false_val = f
504 .false_value
505 .unwrap_or(Expression::Null(crate::expressions::Null));
506 Ok(Expression::Function(Box::new(Function::new(
507 "IIF".to_string(),
508 vec![f.condition, f.true_value, false_val],
509 ))))
510 }
511
512 Expression::StringAgg(f) => Ok(Expression::StringAgg(f)),
515
516 Expression::LastDay(f) => Ok(Expression::Function(Box::new(Function::new(
518 "EOMONTH".to_string(),
519 vec![f.this.clone()],
520 )))),
521
522 Expression::Ceil(f) => Ok(Expression::Function(Box::new(Function::new(
524 "CEILING".to_string(),
525 vec![f.this],
526 )))),
527
528 Expression::Repeat(f) => Ok(Expression::Function(Box::new(Function::new(
530 "REPLICATE".to_string(),
531 vec![f.this, f.times],
532 )))),
533
534 Expression::Chr(f) => Ok(Expression::Function(Box::new(Function::new(
536 "CHAR".to_string(),
537 vec![f.this],
538 )))),
539
540 Expression::Overlay(f) => Ok(Self::overlay_to_stuff(*f)),
542
543 Expression::StartsWith(f) => Ok(Self::starts_with_predicate(f.this, f.expression)),
546
547 Expression::DecodeCase(mut f)
549 if f.expressions.len() == 2
550 && Self::literal_string(&f.expressions[1])
551 .is_some_and(|format| format.eq_ignore_ascii_case("hex")) =>
552 {
553 Ok(Self::tsql_convert(
554 DataType::Custom {
555 name: "VARBINARY(MAX)".to_string(),
556 },
557 f.expressions.remove(0),
558 Some(2),
559 ))
560 }
561
562 Expression::ToNumber(f) => Ok(Self::to_number_or_fallback(*f)),
565
566 Expression::VarPop(f) => Ok(Expression::Function(Box::new(Function::new(
569 "VARP".to_string(),
570 vec![f.this],
571 )))),
572
573 Expression::Variance(f) => Ok(Expression::Function(Box::new(Function::new(
575 "VAR".to_string(),
576 vec![f.this],
577 )))),
578 Expression::VarSamp(f) => Ok(Expression::Function(Box::new(Function::new(
579 "VAR".to_string(),
580 vec![f.this],
581 )))),
582
583 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
586 "HASHBYTES".to_string(),
587 vec![Expression::string("MD5"), *f.this],
588 )))),
589
590 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
592 "HASHBYTES".to_string(),
593 vec![Expression::string("SHA1"), f.this],
594 )))),
595
596 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
598 "HASHBYTES".to_string(),
599 vec![Expression::string("SHA1"), f.this],
600 )))),
601
602 Expression::ArrayToString(f) => Ok(Expression::Function(Box::new(Function::new(
605 "STRING_AGG".to_string(),
606 vec![f.this],
607 )))),
608
609 Expression::AutoIncrementColumnConstraint(_) => Ok(Expression::Function(Box::new(
612 Function::new("IDENTITY".to_string(), vec![]),
613 ))),
614
615 Expression::CreateView(mut view) => {
619 view.name.catalog = None;
621 Ok(Expression::CreateView(view))
622 }
623
624 Expression::DropView(mut view) => {
625 view.name.catalog = None;
627 Ok(Expression::DropView(view))
628 }
629
630 Expression::JSONExtract(e) if e.variant_extract.is_some() => {
634 let path = match *e.expression {
635 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
636 let Literal::String(s) = lit.as_ref() else {
637 unreachable!()
638 };
639 let normalized = if s.starts_with('$') {
640 s.clone()
641 } else if s.starts_with('[') {
642 format!("${}", s)
643 } else {
644 format!("$.{}", s)
645 };
646 Expression::Literal(Box::new(Literal::String(normalized)))
647 }
648 other => other,
649 };
650 let json_query = Expression::Function(Box::new(Function::new(
651 "JSON_QUERY".to_string(),
652 vec![(*e.this).clone(), path.clone()],
653 )));
654 let json_value = Expression::Function(Box::new(Function::new(
655 "JSON_VALUE".to_string(),
656 vec![*e.this, path],
657 )));
658 Ok(Expression::Function(Box::new(Function::new(
659 "ISNULL".to_string(),
660 vec![json_query, json_value],
661 ))))
662 }
663
664 Expression::Function(f) => self.transform_function(*f),
666
667 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
669
670 Expression::Cte(cte) => self.transform_cte(*cte),
673
674 Expression::Subquery(subquery) => self.transform_subquery(*subquery),
677
678 Expression::JsonQuery(f) => {
680 let json_query = Expression::Function(Box::new(Function::new(
681 "JSON_QUERY".to_string(),
682 vec![f.this.clone(), f.path.clone()],
683 )));
684 let json_value = Expression::Function(Box::new(Function::new(
685 "JSON_VALUE".to_string(),
686 vec![f.this, f.path],
687 )));
688 Ok(Expression::Function(Box::new(Function::new(
689 "ISNULL".to_string(),
690 vec![json_query, json_value],
691 ))))
692 }
693 Expression::JsonValue(f) => Ok(Expression::Function(Box::new(Function::new(
695 "JSON_VALUE".to_string(),
696 vec![f.this, f.path],
697 )))),
698
699 Expression::Any(ref q) if matches!(&q.op, Some(QuantifiedOp::Eq)) => {
702 match Self::scalar_array_comparison_values(&q.subquery) {
703 Some(expressions) if expressions.is_empty() => {
704 Ok(Expression::Eq(Box::new(crate::expressions::BinaryOp::new(
705 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
706 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
707 ))))
708 }
709 Some(expressions) => Ok(Expression::In(Box::new(In {
710 this: q.this.clone(),
711 expressions,
712 query: None,
713 not: false,
714 global: false,
715 unnest: None,
716 is_field: false,
717 }))),
718 None => Ok(expr.clone()),
719 }
720 }
721
722 _ => Ok(expr),
724 }
725 }
726}
727
728#[cfg(feature = "transpile")]
729impl TSQLDialect {
730 fn getdate() -> Expression {
731 Expression::Function(Box::new(Function::new("GETDATE".to_string(), vec![])))
732 }
733
734 fn cast_getdate_to(to: DataType) -> Expression {
735 Expression::Cast(Box::new(Cast {
736 this: Self::getdate(),
737 to,
738 trailing_comments: Vec::new(),
739 double_colon_syntax: false,
740 format: None,
741 default: None,
742 inferred_type: None,
743 }))
744 }
745
746 fn cast(this: Expression, to: DataType) -> Expression {
747 Expression::Cast(Box::new(Cast {
748 this,
749 to,
750 trailing_comments: Vec::new(),
751 double_colon_syntax: false,
752 format: None,
753 default: None,
754 inferred_type: None,
755 }))
756 }
757
758 fn function(name: impl Into<String>, args: Vec<Expression>) -> Expression {
759 Expression::Function(Box::new(Function::new(name, args)))
760 }
761
762 fn make_time(mut args: Vec<Expression>) -> Expression {
763 let seconds = args.pop().expect("MAKE_TIME has three arguments");
764 let minute = args.pop().expect("MAKE_TIME has three arguments");
765 let hour = args.pop().expect("MAKE_TIME has three arguments");
766
767 if let Some((whole_seconds, microseconds)) = Self::literal_time_parts(&seconds) {
768 let (fractions, precision) = if microseconds == 0 {
769 (Expression::number(0), Expression::number(0))
770 } else {
771 (Expression::number(microseconds), Expression::number(6))
772 };
773
774 return Self::function(
775 "TIMEFROMPARTS",
776 vec![
777 hour,
778 minute,
779 Expression::number(whole_seconds),
780 fractions,
781 precision,
782 ],
783 );
784 }
785
786 let rounded_microseconds = Self::cast(
790 Self::function(
791 "ROUND",
792 vec![
793 Expression::Mul(Box::new(BinaryOp::new(
794 seconds,
795 Expression::number(1_000_000),
796 ))),
797 Expression::number(0),
798 ],
799 ),
800 DataType::BigInt { length: None },
801 );
802
803 Self::function(
804 "TIMEFROMPARTS",
805 vec![
806 hour,
807 minute,
808 Expression::Div(Box::new(BinaryOp::new(
809 rounded_microseconds.clone(),
810 Expression::number(1_000_000),
811 ))),
812 Expression::Mod(Box::new(BinaryOp::new(
813 rounded_microseconds,
814 Expression::number(1_000_000),
815 ))),
816 Expression::number(6),
817 ],
818 )
819 }
820
821 fn literal_time_parts(expr: &Expression) -> Option<(i64, i64)> {
822 let value = match expr {
823 Expression::Literal(lit) => match lit.as_ref() {
824 Literal::Number(value) => value.parse::<f64>().ok()?,
825 _ => return None,
826 },
827 Expression::Paren(paren) => return Self::literal_time_parts(&paren.this),
828 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
829 if Self::is_numeric_data_type(&cast.to) =>
830 {
831 let parts = Self::literal_time_parts(&cast.this);
832 return match (&cast.to, parts) {
833 (_, Some((0, 0))) => Some((0, 0)),
837 (DataType::Float { .. } | DataType::Double { .. }, parts) => parts,
838 _ => None,
839 };
840 }
841 _ => return None,
842 };
843
844 if !value.is_finite() || value < 0.0 || value > i64::MAX as f64 / 1_000_000.0 {
845 return None;
846 }
847
848 let total_microseconds = (value * 1_000_000.0).round() as i64;
849 Some((
850 total_microseconds / 1_000_000,
851 total_microseconds % 1_000_000,
852 ))
853 }
854
855 fn lower(this: Expression) -> Expression {
856 Expression::Lower(Box::new(UnaryFunc::new(this)))
857 }
858
859 fn tsql_convert(to: DataType, expression: Expression, style: Option<i64>) -> Expression {
860 let mut args = vec![Expression::DataType(to), expression];
861 if let Some(style) = style {
862 args.push(Expression::number(style));
863 }
864 Self::function("CONVERT", args)
865 }
866
867 fn tsql_hex_text(expression: Expression, varchar_type: DataType) -> Expression {
868 Self::lower(Self::tsql_convert(varchar_type, expression, Some(2)))
869 }
870
871 fn tsql_hex_from_varbinary(expression: Expression) -> Expression {
872 Self::tsql_hex_text(
873 Self::cast(
874 expression,
875 DataType::Custom {
876 name: "VARBINARY(MAX)".to_string(),
877 },
878 ),
879 DataType::Text,
880 )
881 }
882
883 fn tsql_postgres_to_hex(expression: Expression) -> Expression {
884 let hex = Self::tsql_hex_from_varbinary(expression);
885 let without_leading_zeroes = Self::function("LTRIM", vec![hex, Expression::string("0")]);
886 let non_empty = Self::function(
887 "NULLIF",
888 vec![without_leading_zeroes, Expression::string("")],
889 );
890 Self::function("ISNULL", vec![non_empty, Expression::string("0")])
891 }
892
893 fn tsql_md5_hex(expression: Expression) -> Expression {
894 let hashbytes = Self::function("HASHBYTES", vec![Expression::string("MD5"), expression]);
895 Self::tsql_hex_text(
896 hashbytes,
897 DataType::VarChar {
898 length: Some(32),
899 parenthesized_length: false,
900 },
901 )
902 }
903
904 fn overlay_to_stuff(f: crate::expressions::OverlayFunc) -> Expression {
905 let length = f
906 .length
907 .unwrap_or_else(|| Self::function("LEN", vec![f.replacement.clone()]));
908 Self::function("STUFF", vec![f.this, f.from, length, f.replacement])
909 }
910
911 fn starts_with_predicate(this: Expression, prefix: Expression) -> Expression {
912 let prefix_len = Self::function("LEN", vec![prefix.clone()]);
913 let left_prefix = Self::function("LEFT", vec![this, prefix_len]);
914 Self::eq(left_prefix, prefix)
915 }
916
917 fn to_number_or_fallback(f: crate::expressions::ToNumber) -> Expression {
918 let crate::expressions::ToNumber {
919 this,
920 format,
921 nlsparam,
922 precision,
923 scale,
924 safe,
925 safe_name,
926 } = f;
927
928 if nlsparam.is_none()
929 && precision.is_none()
930 && scale.is_none()
931 && safe.is_none()
932 && safe_name.is_none()
933 {
934 if let Some(format) = format.as_deref() {
935 if let Some(scale) = Self::simple_to_number_scale(format) {
936 return Self::function(
937 "TRY_CONVERT",
938 vec![
939 Expression::DataType(DataType::Decimal {
940 precision: Some(18),
941 scale: Some(scale),
942 }),
943 *this,
944 ],
945 );
946 }
947 }
948 }
949
950 Expression::ToNumber(Box::new(crate::expressions::ToNumber {
951 this,
952 format,
953 nlsparam,
954 precision,
955 scale,
956 safe,
957 safe_name,
958 }))
959 }
960
961 fn simple_to_number_scale(format: &Expression) -> Option<u32> {
962 let format = Self::literal_string(format)?;
963 let format = format.strip_prefix("FM").unwrap_or(format);
964 let mut saw_digit = false;
965 let mut saw_decimal = false;
966 let mut scale = 0u32;
967
968 for ch in format.chars() {
969 match ch {
970 '9' | '0' => {
971 saw_digit = true;
972 if saw_decimal {
973 scale = scale.checked_add(1)?;
974 }
975 }
976 '.' if !saw_decimal => saw_decimal = true,
977 ',' | ' ' => {}
978 _ => return None,
979 }
980 }
981
982 saw_digit.then_some(scale)
983 }
984
985 fn binary(
986 left: Expression,
987 right: Expression,
988 op: fn(Box<BinaryOp>) -> Expression,
989 ) -> Expression {
990 op(Box::new(BinaryOp {
991 left,
992 right,
993 left_comments: Vec::new(),
994 operator_comments: Vec::new(),
995 trailing_comments: Vec::new(),
996 inferred_type: None,
997 }))
998 }
999
1000 fn eq(left: Expression, right: Expression) -> Expression {
1001 Self::binary(left, right, Expression::Eq)
1002 }
1003
1004 fn or(left: Expression, right: Expression) -> Expression {
1005 Self::binary(left, right, Expression::Or)
1006 }
1007
1008 fn not(this: Expression) -> Expression {
1009 Expression::Not(Box::new(crate::expressions::UnaryOp {
1010 this,
1011 inferred_type: None,
1012 }))
1013 }
1014
1015 fn is_null(this: Expression) -> Expression {
1016 Expression::IsNull(Box::new(crate::expressions::IsNull {
1017 this,
1018 not: false,
1019 postfix_form: false,
1020 }))
1021 }
1022
1023 fn paren(this: Expression) -> Expression {
1024 Expression::Paren(Box::new(Paren {
1025 this,
1026 trailing_comments: Vec::new(),
1027 }))
1028 }
1029
1030 fn boolean_test_case_for_predicate(
1031 predicate: Expression,
1032 test_true: bool,
1033 negated: bool,
1034 ) -> Expression {
1035 let condition = match (test_true, negated) {
1036 (true, false) => predicate,
1037 (false, false) => Self::not(predicate),
1038 (true, true) => {
1039 return Expression::Case(Box::new(crate::expressions::Case {
1040 operand: None,
1041 whens: vec![(predicate, Expression::number(0))],
1042 else_: Some(Expression::number(1)),
1043 comments: Vec::new(),
1044 inferred_type: None,
1045 }))
1046 }
1047 (false, true) => {
1048 return Expression::Case(Box::new(crate::expressions::Case {
1049 operand: None,
1050 whens: vec![(Self::not(predicate), Expression::number(0))],
1051 else_: Some(Expression::number(1)),
1052 comments: Vec::new(),
1053 inferred_type: None,
1054 }))
1055 }
1056 };
1057
1058 Expression::Case(Box::new(crate::expressions::Case {
1059 operand: None,
1060 whens: vec![(condition, Expression::number(1))],
1061 else_: Some(Expression::number(0)),
1062 comments: Vec::new(),
1063 inferred_type: None,
1064 }))
1065 }
1066
1067 fn boolean_test_predicate(operand: Expression, test_true: bool, negated: bool) -> Expression {
1068 if Self::is_boolean_predicate_operand(&operand) {
1069 return match (test_true, negated) {
1070 (true, false) => operand,
1071 (false, false) => Self::not(operand),
1072 _ => Self::eq(
1073 Self::boolean_test_case_for_predicate(operand, test_true, negated),
1074 Expression::number(1),
1075 ),
1076 };
1077 }
1078
1079 match (test_true, negated) {
1080 (true, false) => Self::eq(operand, Expression::number(1)),
1081 (false, false) => Self::eq(operand, Expression::number(0)),
1082 (true, true) => Self::or(
1083 Self::eq(operand.clone(), Expression::number(0)),
1084 Self::is_null(operand),
1085 ),
1086 (false, true) => Self::or(
1087 Self::eq(operand.clone(), Expression::number(1)),
1088 Self::is_null(operand),
1089 ),
1090 }
1091 }
1092
1093 fn is_boolean_predicate_operand(expr: &Expression) -> bool {
1094 match expr {
1095 Expression::Paren(paren) => Self::is_boolean_predicate_operand(&paren.this),
1096 Expression::Eq(_)
1097 | Expression::Neq(_)
1098 | Expression::Lt(_)
1099 | Expression::Lte(_)
1100 | Expression::Gt(_)
1101 | Expression::Gte(_)
1102 | Expression::Is(_)
1103 | Expression::IsNull(_)
1104 | Expression::IsTrue(_)
1105 | Expression::IsFalse(_)
1106 | Expression::Like(_)
1107 | Expression::ILike(_)
1108 | Expression::SimilarTo(_)
1109 | Expression::Glob(_)
1110 | Expression::RegexpLike(_)
1111 | Expression::In(_)
1112 | Expression::Between(_)
1113 | Expression::Exists(_)
1114 | Expression::And(_)
1115 | Expression::Or(_)
1116 | Expression::Not(_)
1117 | Expression::Any(_)
1118 | Expression::All(_)
1119 | Expression::EqualNull(_) => true,
1120 _ => false,
1121 }
1122 }
1123
1124 fn scalar_array_comparison_values(expr: &Expression) -> Option<Vec<Expression>> {
1125 let (mut values, element_type) = Self::scalar_array_comparison_values_inner(expr)?;
1126 if let Some(to) = element_type {
1127 values = values
1128 .into_iter()
1129 .map(|value| Self::cast_scalar_array_comparison_value(value, to.clone()))
1130 .collect();
1131 }
1132 Some(values)
1133 }
1134
1135 fn scalar_array_comparison_values_inner(
1136 expr: &Expression,
1137 ) -> Option<(Vec<Expression>, Option<DataType>)> {
1138 match expr {
1139 Expression::ArrayFunc(a) => Some((a.expressions.clone(), None)),
1140 Expression::Array(a) => Some((a.expressions.clone(), None)),
1141 Expression::Tuple(t) => Some((t.expressions.clone(), None)),
1142 Expression::Paren(p) => Self::scalar_array_comparison_values_inner(&p.this),
1143 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
1144 let DataType::Array { element_type, .. } = &c.to else {
1145 return None;
1146 };
1147 let (values, _) = Self::scalar_array_comparison_values_inner(&c.this)?;
1148 Some((values, Some((**element_type).clone())))
1149 }
1150 _ => None,
1151 }
1152 }
1153
1154 fn cast_scalar_array_comparison_value(value: Expression, to: DataType) -> Expression {
1155 if matches!(&value, Expression::Cast(c) if c.to == to) {
1156 return value;
1157 }
1158
1159 Expression::Cast(Box::new(Cast {
1160 this: value,
1161 to,
1162 trailing_comments: Vec::new(),
1163 double_colon_syntax: false,
1164 format: None,
1165 default: None,
1166 inferred_type: None,
1167 }))
1168 }
1169
1170 fn normalize_frame_incompatible_window_functions(select: &mut Select) {
1171 let window_map: HashMap<String, Over> = select
1172 .windows
1173 .as_ref()
1174 .map(|windows| {
1175 windows
1176 .iter()
1177 .map(|window| (window.name.name.to_lowercase(), window.spec.clone()))
1178 .collect()
1179 })
1180 .unwrap_or_default();
1181
1182 for expr in &mut select.expressions {
1183 Self::normalize_frame_incompatible_window_expr(expr, &window_map);
1184 }
1185
1186 if let Some(order_by) = &mut select.order_by {
1187 for ordered in &mut order_by.expressions {
1188 Self::normalize_frame_incompatible_window_expr(&mut ordered.this, &window_map);
1189 }
1190 }
1191
1192 if let Some(qualify) = &mut select.qualify {
1193 Self::normalize_frame_incompatible_window_expr(&mut qualify.this, &window_map);
1194 }
1195 }
1196
1197 fn normalize_frame_incompatible_window_expr(
1198 expr: &mut Expression,
1199 window_map: &HashMap<String, Over>,
1200 ) {
1201 match expr {
1202 Expression::WindowFunction(wf) => {
1203 Self::normalize_frame_incompatible_window_expr(&mut wf.this, window_map);
1204
1205 if !Self::is_tsql_frame_incompatible_window_function(&wf.this) {
1206 return;
1207 }
1208
1209 wf.over.frame = None;
1210
1211 let Some(window_name) = wf.over.window_name.clone() else {
1212 return;
1213 };
1214 let Some(named_spec) =
1215 Self::resolve_named_window_spec(&window_name.name, window_map, &mut Vec::new())
1216 else {
1217 return;
1218 };
1219
1220 if named_spec.frame.is_none() {
1221 return;
1222 }
1223
1224 if wf.over.partition_by.is_empty() {
1225 wf.over.partition_by = named_spec.partition_by;
1226 }
1227 if wf.over.order_by.is_empty() {
1228 wf.over.order_by = named_spec.order_by;
1229 }
1230 wf.over.window_name = None;
1231 wf.over.frame = None;
1232 }
1233 Expression::Alias(alias) => {
1234 Self::normalize_frame_incompatible_window_expr(&mut alias.this, window_map);
1235 }
1236 Expression::Paren(paren) => {
1237 Self::normalize_frame_incompatible_window_expr(&mut paren.this, window_map);
1238 }
1239 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
1240 Self::normalize_frame_incompatible_window_expr(&mut cast.this, window_map);
1241 }
1242 Expression::Function(function) => {
1243 for arg in &mut function.args {
1244 Self::normalize_frame_incompatible_window_expr(arg, window_map);
1245 }
1246 }
1247 Expression::Case(case) => {
1248 if let Some(operand) = &mut case.operand {
1249 Self::normalize_frame_incompatible_window_expr(operand, window_map);
1250 }
1251 for (condition, result) in &mut case.whens {
1252 Self::normalize_frame_incompatible_window_expr(condition, window_map);
1253 Self::normalize_frame_incompatible_window_expr(result, window_map);
1254 }
1255 if let Some(else_expr) = &mut case.else_ {
1256 Self::normalize_frame_incompatible_window_expr(else_expr, window_map);
1257 }
1258 }
1259 Expression::And(op)
1260 | Expression::Or(op)
1261 | Expression::Add(op)
1262 | Expression::Sub(op)
1263 | Expression::Mul(op)
1264 | Expression::Div(op)
1265 | Expression::Mod(op)
1266 | Expression::Eq(op)
1267 | Expression::Neq(op)
1268 | Expression::Lt(op)
1269 | Expression::Lte(op)
1270 | Expression::Gt(op)
1271 | Expression::Gte(op)
1272 | Expression::Match(op)
1273 | Expression::BitwiseAnd(op)
1274 | Expression::BitwiseOr(op)
1275 | Expression::BitwiseXor(op)
1276 | Expression::Concat(op)
1277 | Expression::Adjacent(op)
1278 | Expression::TsMatch(op)
1279 | Expression::PropertyEQ(op)
1280 | Expression::ArrayContainsAll(op)
1281 | Expression::ArrayContainedBy(op)
1282 | Expression::ArrayOverlaps(op)
1283 | Expression::JSONBContainsAllTopKeys(op)
1284 | Expression::JSONBContainsAnyTopKeys(op)
1285 | Expression::JSONBDeleteAtPath(op)
1286 | Expression::ExtendsLeft(op)
1287 | Expression::ExtendsRight(op)
1288 | Expression::Is(op)
1289 | Expression::MemberOf(op) => {
1290 Self::normalize_frame_incompatible_window_expr(&mut op.left, window_map);
1291 Self::normalize_frame_incompatible_window_expr(&mut op.right, window_map);
1292 }
1293 Expression::Like(op) | Expression::ILike(op) => {
1294 Self::normalize_frame_incompatible_window_expr(&mut op.left, window_map);
1295 Self::normalize_frame_incompatible_window_expr(&mut op.right, window_map);
1296 if let Some(escape) = &mut op.escape {
1297 Self::normalize_frame_incompatible_window_expr(escape, window_map);
1298 }
1299 }
1300 Expression::Not(op) | Expression::Neg(op) | Expression::BitwiseNot(op) => {
1301 Self::normalize_frame_incompatible_window_expr(&mut op.this, window_map);
1302 }
1303 Expression::In(in_expr) => {
1304 Self::normalize_frame_incompatible_window_expr(&mut in_expr.this, window_map);
1305 for value in &mut in_expr.expressions {
1306 Self::normalize_frame_incompatible_window_expr(value, window_map);
1307 }
1308 }
1309 Expression::Between(between) => {
1310 Self::normalize_frame_incompatible_window_expr(&mut between.this, window_map);
1311 Self::normalize_frame_incompatible_window_expr(&mut between.low, window_map);
1312 Self::normalize_frame_incompatible_window_expr(&mut between.high, window_map);
1313 }
1314 Expression::IsNull(is_null) => {
1315 Self::normalize_frame_incompatible_window_expr(&mut is_null.this, window_map);
1316 }
1317 Expression::IsTrue(is_true) | Expression::IsFalse(is_true) => {
1318 Self::normalize_frame_incompatible_window_expr(&mut is_true.this, window_map);
1319 }
1320 _ => {}
1321 }
1322 }
1323
1324 fn is_tsql_frame_incompatible_window_function(expr: &Expression) -> bool {
1325 matches!(
1326 expr,
1327 Expression::RowNumber(_)
1328 | Expression::Rank(_)
1329 | Expression::DenseRank(_)
1330 | Expression::NTile(_)
1331 | Expression::Ntile(_)
1332 | Expression::Lead(_)
1333 | Expression::Lag(_)
1334 | Expression::PercentRank(_)
1335 | Expression::CumeDist(_)
1336 )
1337 }
1338
1339 fn resolve_named_window_spec(
1340 name: &str,
1341 window_map: &HashMap<String, Over>,
1342 seen: &mut Vec<String>,
1343 ) -> Option<Over> {
1344 let key = name.to_lowercase();
1345 if seen.iter().any(|seen_name| seen_name == &key) {
1346 return None;
1347 }
1348
1349 let named_spec = window_map.get(&key)?.clone();
1350 seen.push(key);
1351
1352 let mut resolved = if let Some(base_window) = &named_spec.window_name {
1353 Self::resolve_named_window_spec(&base_window.name, window_map, seen)
1354 .unwrap_or_else(Self::empty_over)
1355 } else {
1356 Self::empty_over()
1357 };
1358
1359 if !named_spec.partition_by.is_empty() {
1360 resolved.partition_by = named_spec.partition_by;
1361 }
1362 if !named_spec.order_by.is_empty() {
1363 resolved.order_by = named_spec.order_by;
1364 }
1365 if named_spec.frame.is_some() {
1366 resolved.frame = named_spec.frame;
1367 }
1368
1369 Some(resolved)
1370 }
1371
1372 fn empty_over() -> Over {
1373 Over {
1374 window_name: None,
1375 partition_by: Vec::new(),
1376 order_by: Vec::new(),
1377 frame: None,
1378 alias: None,
1379 }
1380 }
1381
1382 const LATERAL_WRAPPER_SOURCE_ALIAS: &'static str = "_polyglot_lateral_source";
1383 const LATERAL_WRAPPER_OUTPUT_ALIAS: &'static str = "_polyglot_lateral";
1384
1385 fn transform_lateral_join_to_apply(mut join: Join) -> Result<Join> {
1386 let Some(apply_kind) = Self::lateral_apply_kind(&join) else {
1387 return Ok(join);
1388 };
1389
1390 let original_alias = Self::table_expression_alias(&join.this);
1391 let on = join.on.take();
1392 let rhs = Self::remove_lateral_marker(join.this);
1393 join.this = if on
1394 .as_ref()
1395 .is_some_and(|expr| !Self::is_true_condition(expr))
1396 {
1397 Self::wrap_lateral_apply_rhs(rhs, on.expect("checked as Some"), original_alias)?
1398 } else {
1399 rhs
1400 };
1401 join.using.clear();
1402 join.kind = apply_kind;
1403 join.use_inner_keyword = false;
1404 join.use_outer_keyword = false;
1405 join.deferred_condition = false;
1406 join.join_hint = None;
1407 join.match_condition = None;
1408 join.directed = false;
1409 Ok(join)
1410 }
1411
1412 fn rewrite_comma_lateral_sources_to_joins(select: &mut Select) {
1413 let Some(from) = select.from.as_mut() else {
1414 return;
1415 };
1416 let has_comma_lateral = from
1417 .expressions
1418 .iter()
1419 .skip(1)
1420 .any(Self::is_lateral_table_expression);
1421 let has_apply_join = select
1422 .joins
1423 .iter()
1424 .any(|join| matches!(join.kind, JoinKind::CrossApply | JoinKind::OuterApply));
1425
1426 if from.expressions.len() < 2 || (!has_comma_lateral && !has_apply_join) {
1427 return;
1428 }
1429
1430 let mut expressions = std::mem::take(&mut from.expressions).into_iter();
1431 let Some(first) = expressions.next() else {
1432 return;
1433 };
1434 from.expressions = vec![first];
1435
1436 let mut joins = expressions
1437 .map(|source| {
1438 if Self::is_lateral_table_expression(&source) {
1439 Self::new_join(Self::remove_lateral_marker(source), JoinKind::CrossApply)
1440 } else {
1441 Self::new_join(source, JoinKind::Cross)
1442 }
1443 })
1444 .collect::<Vec<_>>();
1445 joins.append(&mut select.joins);
1446 select.joins = joins;
1447 }
1448
1449 fn new_join(this: Expression, kind: JoinKind) -> Join {
1450 Join {
1451 this,
1452 on: None,
1453 using: Vec::new(),
1454 kind,
1455 use_inner_keyword: false,
1456 use_outer_keyword: false,
1457 deferred_condition: false,
1458 join_hint: None,
1459 match_condition: None,
1460 pivots: Vec::new(),
1461 comments: Vec::new(),
1462 nesting_group: 0,
1463 directed: false,
1464 }
1465 }
1466
1467 fn lateral_apply_kind(join: &Join) -> Option<JoinKind> {
1468 if !join.using.is_empty() {
1469 return None;
1470 }
1471
1472 match join.kind {
1473 JoinKind::Lateral => Some(JoinKind::CrossApply),
1474 JoinKind::LeftLateral => Some(JoinKind::OuterApply),
1475 JoinKind::Cross | JoinKind::Inner | JoinKind::Implicit
1476 if Self::is_lateral_table_expression(&join.this) =>
1477 {
1478 Some(JoinKind::CrossApply)
1479 }
1480 JoinKind::Left if Self::is_lateral_table_expression(&join.this) => {
1481 Some(JoinKind::OuterApply)
1482 }
1483 _ => None,
1484 }
1485 }
1486
1487 fn is_true_condition(expr: &Expression) -> bool {
1488 match expr {
1489 Expression::Boolean(boolean) => boolean.value,
1490 Expression::Literal(lit) => {
1491 matches!(lit.as_ref(), Literal::Number(value) if value.trim() == "1")
1492 }
1493 Expression::Eq(op) => {
1494 Self::is_true_condition(&op.left) && Self::is_true_condition(&op.right)
1495 }
1496 Expression::Paren(paren) => Self::is_true_condition(&paren.this),
1497 _ => false,
1498 }
1499 }
1500
1501 fn table_expression_alias(expr: &Expression) -> Option<(Identifier, Vec<Identifier>)> {
1502 match expr {
1503 Expression::Subquery(subquery) => subquery
1504 .alias
1505 .clone()
1506 .map(|alias| (alias, subquery.column_aliases.clone())),
1507 Expression::Alias(alias) if !alias.alias.is_empty() => {
1508 Some((alias.alias.clone(), alias.column_aliases.clone()))
1509 }
1510 Expression::Lateral(lateral) => lateral.alias.as_ref().map(|alias| {
1511 (
1512 if lateral.alias_quoted {
1513 Identifier::quoted(alias)
1514 } else {
1515 Identifier::new(alias)
1516 },
1517 lateral
1518 .column_aliases
1519 .iter()
1520 .map(|column| Identifier::new(column.clone()))
1521 .collect(),
1522 )
1523 }),
1524 _ => None,
1525 }
1526 }
1527
1528 fn wrap_lateral_apply_rhs(
1529 rhs: Expression,
1530 predicate: Expression,
1531 original_alias: Option<(Identifier, Vec<Identifier>)>,
1532 ) -> Result<Expression> {
1533 let (outer_alias, column_aliases) = original_alias.unwrap_or_else(|| {
1534 (
1535 Identifier::new(Self::LATERAL_WRAPPER_OUTPUT_ALIAS),
1536 Vec::new(),
1537 )
1538 });
1539 let inner_alias = Identifier::new(Self::LATERAL_WRAPPER_SOURCE_ALIAS);
1540 let source =
1541 Self::with_table_expression_alias(rhs, inner_alias.clone(), column_aliases.clone());
1542 let predicate = Self::rewrite_column_qualifier(predicate, &outer_alias, &inner_alias)?;
1543
1544 let mut select = Select::new();
1545 select.expressions = vec![Expression::Star(Star {
1546 table: None,
1547 except: None,
1548 replace: None,
1549 rename: None,
1550 trailing_comments: Vec::new(),
1551 span: None,
1552 })];
1553 select.from = Some(crate::expressions::From {
1554 expressions: vec![source],
1555 });
1556 select.where_clause = Some(Where { this: predicate });
1557
1558 Ok(Expression::Subquery(Box::new(Subquery {
1559 this: Expression::Select(Box::new(select)),
1560 alias: Some(outer_alias),
1561 column_aliases,
1562 alias_explicit_as: true,
1563 alias_keyword: None,
1564 order_by: None,
1565 limit: None,
1566 offset: None,
1567 distribute_by: None,
1568 sort_by: None,
1569 cluster_by: None,
1570 lateral: false,
1571 modifiers_inside: false,
1572 trailing_comments: Vec::new(),
1573 inferred_type: None,
1574 })))
1575 }
1576
1577 fn with_table_expression_alias(
1578 expr: Expression,
1579 alias: Identifier,
1580 column_aliases: Vec<Identifier>,
1581 ) -> Expression {
1582 match expr {
1583 Expression::Subquery(mut subquery) => {
1584 subquery.alias = Some(alias);
1585 subquery.column_aliases = column_aliases;
1586 subquery.alias_explicit_as = true;
1587 subquery.alias_keyword = None;
1588 Expression::Subquery(subquery)
1589 }
1590 Expression::Alias(mut aliased) => {
1591 aliased.alias = alias;
1592 aliased.column_aliases = column_aliases;
1593 aliased.alias_explicit_as = true;
1594 aliased.alias_keyword = None;
1595 Expression::Alias(aliased)
1596 }
1597 Expression::Table(mut table) => {
1598 table.alias = Some(alias);
1599 table.alias_explicit_as = true;
1600 table.column_aliases = column_aliases;
1601 Expression::Table(table)
1602 }
1603 other => Expression::Alias(Box::new(Alias {
1604 this: other,
1605 alias,
1606 column_aliases,
1607 alias_explicit_as: true,
1608 alias_keyword: None,
1609 pre_alias_comments: Vec::new(),
1610 trailing_comments: Vec::new(),
1611 inferred_type: None,
1612 })),
1613 }
1614 }
1615
1616 fn rewrite_column_qualifier(
1617 expr: Expression,
1618 from: &Identifier,
1619 to: &Identifier,
1620 ) -> Result<Expression> {
1621 super::transform_recursive(expr, &|expr| {
1622 Ok(match expr {
1623 Expression::Column(mut column)
1624 if column
1625 .table
1626 .as_ref()
1627 .is_some_and(|table| Self::same_identifier(table, from)) =>
1628 {
1629 column.table = Some(to.clone());
1630 Expression::Column(column)
1631 }
1632 other => other,
1633 })
1634 })
1635 }
1636
1637 fn same_identifier(left: &Identifier, right: &Identifier) -> bool {
1638 if left.quoted || right.quoted {
1639 left.quoted == right.quoted && left.name == right.name
1640 } else {
1641 left.name.eq_ignore_ascii_case(&right.name)
1642 }
1643 }
1644
1645 fn is_lateral_table_expression(expr: &Expression) -> bool {
1646 match expr {
1647 Expression::Subquery(subquery) => subquery.lateral,
1648 Expression::Lateral(_) => true,
1649 Expression::Alias(alias) => Self::is_lateral_table_expression(&alias.this),
1650 _ => false,
1651 }
1652 }
1653
1654 fn remove_lateral_marker(expr: Expression) -> Expression {
1655 match expr {
1656 Expression::Subquery(mut subquery) => {
1657 subquery.lateral = false;
1658 Expression::Subquery(subquery)
1659 }
1660 Expression::Lateral(lateral) => Self::lateral_to_table_expression(*lateral),
1661 Expression::Alias(mut alias) => {
1662 alias.this = Self::remove_lateral_marker(alias.this);
1663 Expression::Alias(alias)
1664 }
1665 other => other,
1666 }
1667 }
1668
1669 fn lateral_to_table_expression(lateral: crate::expressions::Lateral) -> Expression {
1670 let expr = *lateral.this;
1671 let Some(alias) = lateral.alias else {
1672 return expr;
1673 };
1674
1675 Expression::Alias(Box::new(Alias {
1676 this: expr,
1677 alias: if lateral.alias_quoted {
1678 Identifier::quoted(alias)
1679 } else {
1680 Identifier::new(alias)
1681 },
1682 column_aliases: lateral
1683 .column_aliases
1684 .into_iter()
1685 .map(Identifier::new)
1686 .collect(),
1687 alias_explicit_as: true,
1688 alias_keyword: None,
1689 pre_alias_comments: Vec::new(),
1690 trailing_comments: Vec::new(),
1691 inferred_type: None,
1692 }))
1693 }
1694
1695 fn rewrite_tuple_in_subquery_predicates(
1696 expr: Expression,
1697 outer_qualifier: Option<&Identifier>,
1698 under_not: bool,
1699 ) -> Expression {
1700 match expr {
1701 Expression::In(in_expr) if !under_not => {
1702 let in_expr = *in_expr;
1703 Self::tuple_in_subquery_to_exists(&in_expr, outer_qualifier, in_expr.not)
1704 .unwrap_or_else(|| Expression::In(Box::new(in_expr)))
1705 }
1706 Expression::Eq(op) if !under_not => {
1707 let op = *op;
1708 Self::tuple_subquery_eq_to_exists(&op, outer_qualifier)
1709 .unwrap_or_else(|| Expression::Eq(Box::new(op)))
1710 }
1711 Expression::And(mut op) => {
1712 op.left =
1713 Self::rewrite_tuple_in_subquery_predicates(op.left, outer_qualifier, under_not);
1714 op.right = Self::rewrite_tuple_in_subquery_predicates(
1715 op.right,
1716 outer_qualifier,
1717 under_not,
1718 );
1719 Expression::And(op)
1720 }
1721 Expression::Or(mut op) => {
1722 op.left =
1723 Self::rewrite_tuple_in_subquery_predicates(op.left, outer_qualifier, under_not);
1724 op.right = Self::rewrite_tuple_in_subquery_predicates(
1725 op.right,
1726 outer_qualifier,
1727 under_not,
1728 );
1729 Expression::Or(op)
1730 }
1731 Expression::Paren(mut paren) => {
1732 paren.this = Self::rewrite_tuple_in_subquery_predicates(
1733 paren.this,
1734 outer_qualifier,
1735 under_not,
1736 );
1737 Expression::Paren(paren)
1738 }
1739 Expression::Not(mut not) => {
1740 if let Some(rewritten) = Self::direct_tuple_subquery_predicate_to_exists(
1741 ¬.this,
1742 outer_qualifier,
1743 true,
1744 ) {
1745 rewritten
1746 } else {
1747 not.this =
1748 Self::rewrite_tuple_in_subquery_predicates(not.this, outer_qualifier, true);
1749 Expression::Not(not)
1750 }
1751 }
1752 Expression::Alias(mut alias) => {
1753 alias.this = Self::rewrite_tuple_in_subquery_predicates(
1754 alias.this,
1755 outer_qualifier,
1756 under_not,
1757 );
1758 Expression::Alias(alias)
1759 }
1760 Expression::Cast(mut cast) => {
1761 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1762 cast.this,
1763 outer_qualifier,
1764 under_not,
1765 );
1766 if let Some(format) = cast.format.take() {
1767 cast.format = Some(Box::new(Self::rewrite_tuple_in_subquery_predicates(
1768 *format,
1769 outer_qualifier,
1770 under_not,
1771 )));
1772 }
1773 if let Some(default) = cast.default.take() {
1774 cast.default = Some(Box::new(Self::rewrite_tuple_in_subquery_predicates(
1775 *default,
1776 outer_qualifier,
1777 under_not,
1778 )));
1779 }
1780 Expression::Cast(cast)
1781 }
1782 Expression::TryCast(mut cast) => {
1783 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1784 cast.this,
1785 outer_qualifier,
1786 under_not,
1787 );
1788 Expression::TryCast(cast)
1789 }
1790 Expression::SafeCast(mut cast) => {
1791 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1792 cast.this,
1793 outer_qualifier,
1794 under_not,
1795 );
1796 Expression::SafeCast(cast)
1797 }
1798 Expression::Case(mut case) => {
1799 if let Some(operand) = case.operand.take() {
1800 case.operand = Some(Self::rewrite_tuple_in_subquery_predicates(
1801 operand,
1802 outer_qualifier,
1803 under_not,
1804 ));
1805 }
1806 case.whens = case
1807 .whens
1808 .into_iter()
1809 .map(|(condition, result)| {
1810 (
1811 Self::rewrite_tuple_in_subquery_predicates(
1812 condition,
1813 outer_qualifier,
1814 false,
1815 ),
1816 Self::rewrite_tuple_in_subquery_predicates(
1817 result,
1818 outer_qualifier,
1819 under_not,
1820 ),
1821 )
1822 })
1823 .collect();
1824 if let Some(else_) = case.else_.take() {
1825 case.else_ = Some(Self::rewrite_tuple_in_subquery_predicates(
1826 else_,
1827 outer_qualifier,
1828 under_not,
1829 ));
1830 }
1831 Expression::Case(case)
1832 }
1833 Expression::IfFunc(mut if_func) => {
1834 if_func.condition = Self::rewrite_tuple_in_subquery_predicates(
1835 if_func.condition,
1836 outer_qualifier,
1837 false,
1838 );
1839 if_func.true_value = Self::rewrite_tuple_in_subquery_predicates(
1840 if_func.true_value,
1841 outer_qualifier,
1842 under_not,
1843 );
1844 if let Some(false_value) = if_func.false_value.take() {
1845 if_func.false_value = Some(Self::rewrite_tuple_in_subquery_predicates(
1846 false_value,
1847 outer_qualifier,
1848 under_not,
1849 ));
1850 }
1851 Expression::IfFunc(if_func)
1852 }
1853 other => other,
1854 }
1855 }
1856
1857 fn direct_tuple_subquery_predicate_to_exists(
1858 expr: &Expression,
1859 outer_qualifier: Option<&Identifier>,
1860 negated: bool,
1861 ) -> Option<Expression> {
1862 match expr {
1863 Expression::In(in_expr) => {
1864 Self::tuple_in_subquery_to_exists(in_expr, outer_qualifier, negated ^ in_expr.not)
1865 }
1866 Expression::Paren(paren) => Self::direct_tuple_subquery_predicate_to_exists(
1867 &paren.this,
1868 outer_qualifier,
1869 negated,
1870 ),
1871 _ => None,
1872 }
1873 }
1874
1875 fn tuple_in_subquery_to_exists(
1876 in_expr: &In,
1877 outer_qualifier: Option<&Identifier>,
1878 negated: bool,
1879 ) -> Option<Expression> {
1880 if in_expr.unnest.is_some() {
1881 return None;
1882 }
1883
1884 let left_expressions = Self::tuple_expressions(&in_expr.this)?;
1885 let mut select = Self::select_from_in_rhs(in_expr)?;
1886
1887 if left_expressions.len() != select.expressions.len() || left_expressions.is_empty() {
1888 return None;
1889 }
1890
1891 let inner_qualifier = Self::single_select_source_qualifier(&select);
1892 let mut predicates = Vec::with_capacity(left_expressions.len() + 1);
1893 for (projection, left) in select
1894 .expressions
1895 .iter()
1896 .cloned()
1897 .zip(left_expressions.iter().cloned())
1898 {
1899 let inner = Self::tuple_in_projection_expr(projection, inner_qualifier.as_ref())?;
1900 let outer = Self::qualify_tuple_operand(left, outer_qualifier);
1901 predicates.push(if negated {
1902 Self::tuple_component_may_match(inner, outer)
1903 } else {
1904 Expression::Eq(Box::new(BinaryOp::new(inner, outer)))
1905 });
1906 }
1907
1908 if let Some(where_clause) = select.where_clause.take() {
1909 predicates.push(where_clause.this);
1910 }
1911
1912 select.expressions = vec![Expression::number(1)];
1913 select.where_clause = Some(Where {
1914 this: Self::and_all(predicates)?,
1915 });
1916
1917 Some(Expression::Exists(Box::new(Exists {
1918 this: Expression::Select(Box::new(select)),
1919 not: negated,
1920 })))
1921 }
1922
1923 fn tuple_subquery_eq_to_exists(
1924 op: &BinaryOp,
1925 outer_qualifier: Option<&Identifier>,
1926 ) -> Option<Expression> {
1927 if let Some((tuple_expr, query_expr)) = Self::tuple_and_query_operands(&op.left, &op.right)
1928 {
1929 return Self::tuple_subquery_eq_to_exists_inner(
1930 tuple_expr,
1931 query_expr,
1932 outer_qualifier,
1933 );
1934 }
1935
1936 if let Some((tuple_expr, query_expr)) = Self::tuple_and_query_operands(&op.right, &op.left)
1937 {
1938 return Self::tuple_subquery_eq_to_exists_inner(
1939 tuple_expr,
1940 query_expr,
1941 outer_qualifier,
1942 );
1943 }
1944
1945 None
1946 }
1947
1948 fn tuple_subquery_eq_to_exists_inner(
1949 tuple_expr: &Expression,
1950 query_expr: &Expression,
1951 outer_qualifier: Option<&Identifier>,
1952 ) -> Option<Expression> {
1953 let tuple_expressions = Self::tuple_expressions(tuple_expr)?;
1954 let mut select = Self::select_from_query_expression(query_expr)?;
1955
1956 if tuple_expressions.len() != select.expressions.len() || tuple_expressions.is_empty() {
1957 return None;
1958 }
1959
1960 let inner_qualifier = Self::single_select_source_qualifier(&select);
1961 let mut predicates = Vec::with_capacity(tuple_expressions.len() + 1);
1962 for (projection, tuple_operand) in select
1963 .expressions
1964 .iter()
1965 .cloned()
1966 .zip(tuple_expressions.iter().cloned())
1967 {
1968 let inner = Self::tuple_in_projection_expr(projection, inner_qualifier.as_ref())?;
1969 let outer = Self::qualify_tuple_operand(tuple_operand, outer_qualifier);
1970 predicates.push(Expression::Eq(Box::new(BinaryOp::new(inner, outer))));
1971 }
1972
1973 if let Some(where_clause) = select.where_clause.take() {
1974 predicates.push(where_clause.this);
1975 }
1976
1977 select.expressions = vec![Expression::number(1)];
1978 select.where_clause = Some(Where {
1979 this: Self::and_all(predicates)?,
1980 });
1981
1982 Some(Expression::Exists(Box::new(Exists {
1983 this: Expression::Select(Box::new(select)),
1984 not: false,
1985 })))
1986 }
1987
1988 fn tuple_and_query_operands<'a>(
1989 tuple_candidate: &'a Expression,
1990 query_candidate: &'a Expression,
1991 ) -> Option<(&'a Expression, &'a Expression)> {
1992 if Self::tuple_expressions(tuple_candidate).is_some()
1993 && Self::select_from_query_expression(query_candidate).is_some()
1994 {
1995 Some((tuple_candidate, query_candidate))
1996 } else {
1997 None
1998 }
1999 }
2000
2001 fn select_from_query_expression(expr: &Expression) -> Option<Select> {
2002 match expr {
2003 Expression::Select(select) => Some((**select).clone()),
2004 Expression::Subquery(subquery) => Self::select_from_query_expression(&subquery.this),
2005 Expression::Paren(paren) => Self::select_from_query_expression(&paren.this),
2006 _ => None,
2007 }
2008 }
2009
2010 fn select_from_in_rhs(in_expr: &In) -> Option<Select> {
2011 if let Some(values) = Self::values_from_in_rhs(in_expr) {
2012 return Self::select_from_values(&values);
2013 }
2014
2015 if let Some(query) = &in_expr.query {
2016 return if in_expr.expressions.is_empty() {
2017 Self::select_from_query_expression(query)
2018 } else {
2019 None
2020 };
2021 }
2022
2023 if in_expr.expressions.len() == 1 {
2024 Self::select_from_query_expression(&in_expr.expressions[0])
2025 } else {
2026 None
2027 }
2028 }
2029
2030 fn values_from_in_rhs(in_expr: &In) -> Option<Values> {
2031 if let Some(query) = &in_expr.query {
2032 return if in_expr.expressions.is_empty() {
2033 Self::values_from_expression(query)
2034 } else {
2035 None
2036 };
2037 }
2038
2039 if in_expr.expressions.len() == 1 {
2040 if let Some(values) = Self::values_from_expression(&in_expr.expressions[0]) {
2041 return Some(values);
2042 }
2043 }
2044
2045 let Expression::Function(first_row) = in_expr.expressions.first()? else {
2047 return None;
2048 };
2049 if !first_row.name.eq_ignore_ascii_case("VALUES") {
2050 return None;
2051 }
2052
2053 let mut rows = Vec::with_capacity(in_expr.expressions.len());
2054 rows.push(Tuple {
2055 expressions: first_row.args.clone(),
2056 });
2057 for row in &in_expr.expressions[1..] {
2058 rows.push(Self::tuple_from_values_row(row)?);
2059 }
2060
2061 Some(Values {
2062 expressions: rows,
2063 alias: None,
2064 column_aliases: Vec::new(),
2065 })
2066 }
2067
2068 fn values_from_expression(expr: &Expression) -> Option<Values> {
2069 match expr {
2070 Expression::Values(values) => Some((**values).clone()),
2071 Expression::Paren(paren) => Self::values_from_expression(&paren.this),
2072 Expression::Subquery(subquery) => Self::values_from_expression(&subquery.this),
2073 _ => None,
2074 }
2075 }
2076
2077 fn tuple_from_values_row(expr: &Expression) -> Option<Tuple> {
2078 match expr {
2079 Expression::Tuple(tuple) => Some((**tuple).clone()),
2080 Expression::Paren(paren) => match &paren.this {
2081 Expression::Tuple(tuple) => Some((**tuple).clone()),
2082 other => Some(Tuple {
2083 expressions: vec![other.clone()],
2084 }),
2085 },
2086 _ => None,
2087 }
2088 }
2089
2090 fn select_from_values(values: &Values) -> Option<Select> {
2091 let column_count = values.expressions.first()?.expressions.len();
2092 if column_count == 0
2093 || values
2094 .expressions
2095 .iter()
2096 .any(|row| row.expressions.len() != column_count)
2097 {
2098 return None;
2099 }
2100
2101 let source_alias = Identifier::new("_polyglot_values");
2102 let column_aliases = (1..=column_count)
2103 .map(|index| Identifier::new(format!("_polyglot_value_{index}")))
2104 .collect::<Vec<_>>();
2105 let projections = column_aliases
2106 .iter()
2107 .cloned()
2108 .map(|column| Self::column_from_identifier(column, Some(source_alias.clone())))
2109 .collect();
2110
2111 let mut source_values = values.clone();
2112 source_values.alias = None;
2113 source_values.column_aliases.clear();
2114
2115 let source = Expression::Subquery(Box::new(Subquery {
2116 this: Expression::Values(Box::new(source_values)),
2117 alias: Some(source_alias),
2118 column_aliases,
2119 alias_explicit_as: true,
2120 alias_keyword: None,
2121 order_by: None,
2122 limit: None,
2123 offset: None,
2124 distribute_by: None,
2125 sort_by: None,
2126 cluster_by: None,
2127 lateral: false,
2128 modifiers_inside: false,
2129 trailing_comments: Vec::new(),
2130 inferred_type: None,
2131 }));
2132
2133 let mut select = Select::new();
2134 select.expressions = projections;
2135 select.from = Some(From {
2136 expressions: vec![source],
2137 });
2138 Some(select)
2139 }
2140
2141 fn tuple_expressions(expr: &Expression) -> Option<&[Expression]> {
2142 match expr {
2143 Expression::Tuple(tuple) => Some(&tuple.expressions),
2144 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
2145 Some(&function.args)
2146 }
2147 Expression::Paren(paren) => Self::tuple_expressions(&paren.this),
2148 _ => None,
2149 }
2150 }
2151
2152 fn tuple_in_projection_expr(
2153 expr: Expression,
2154 qualifier: Option<&Identifier>,
2155 ) -> Option<Expression> {
2156 match expr {
2157 Expression::Alias(alias) => Self::tuple_in_projection_expr(alias.this, qualifier),
2158 Expression::Column(mut column) => {
2159 if column.table.is_none() {
2160 column.table = qualifier.cloned();
2161 }
2162 Some(Expression::Column(column))
2163 }
2164 Expression::Identifier(identifier) => {
2165 Some(Self::column_from_identifier(identifier, qualifier.cloned()))
2166 }
2167 Expression::Dot(_) => Some(expr),
2168 other => Some(Self::qualify_tuple_expression(other, qualifier)),
2169 }
2170 }
2171
2172 fn qualify_tuple_operand(expr: Expression, qualifier: Option<&Identifier>) -> Expression {
2173 Self::qualify_tuple_expression(expr, qualifier)
2174 }
2175
2176 fn qualify_tuple_expression(expr: Expression, qualifier: Option<&Identifier>) -> Expression {
2177 match expr {
2178 Expression::Column(mut column) => {
2179 if column.table.is_none() {
2180 column.table = qualifier.cloned();
2181 }
2182 Expression::Column(column)
2183 }
2184 Expression::Identifier(identifier) => {
2185 Self::column_from_identifier(identifier, qualifier.cloned())
2186 }
2187 Expression::Alias(mut alias) => {
2188 alias.this = Self::qualify_tuple_expression(alias.this, qualifier);
2189 Expression::Alias(alias)
2190 }
2191 Expression::Paren(mut paren) => {
2192 paren.this = Self::qualify_tuple_expression(paren.this, qualifier);
2193 Expression::Paren(paren)
2194 }
2195 Expression::Cast(mut cast) => {
2196 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
2197 if let Some(format) = cast.format.take() {
2198 cast.format =
2199 Some(Box::new(Self::qualify_tuple_expression(*format, qualifier)));
2200 }
2201 if let Some(default) = cast.default.take() {
2202 cast.default = Some(Box::new(Self::qualify_tuple_expression(
2203 *default, qualifier,
2204 )));
2205 }
2206 Expression::Cast(cast)
2207 }
2208 Expression::TryCast(mut cast) => {
2209 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
2210 Expression::TryCast(cast)
2211 }
2212 Expression::SafeCast(mut cast) => {
2213 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
2214 Expression::SafeCast(cast)
2215 }
2216 Expression::Function(mut function) => {
2217 function.args = function
2218 .args
2219 .into_iter()
2220 .map(|arg| Self::qualify_tuple_expression(arg, qualifier))
2221 .collect();
2222 Expression::Function(function)
2223 }
2224 Expression::Add(mut op) => {
2225 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2226 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2227 Expression::Add(op)
2228 }
2229 Expression::Sub(mut op) => {
2230 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2231 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2232 Expression::Sub(op)
2233 }
2234 Expression::Mul(mut op) => {
2235 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2236 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2237 Expression::Mul(op)
2238 }
2239 Expression::Div(mut op) => {
2240 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2241 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2242 Expression::Div(op)
2243 }
2244 Expression::Mod(mut op) => {
2245 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2246 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2247 Expression::Mod(op)
2248 }
2249 other => other,
2250 }
2251 }
2252
2253 fn tuple_component_may_match(inner: Expression, outer: Expression) -> Expression {
2254 Self::paren(
2255 Self::or_all(vec![
2256 Expression::Eq(Box::new(BinaryOp::new(inner.clone(), outer.clone()))),
2257 Self::is_null(inner),
2258 Self::is_null(outer),
2259 ])
2260 .expect("tuple component match condition is non-empty"),
2261 )
2262 }
2263
2264 fn column_from_identifier(identifier: Identifier, table: Option<Identifier>) -> Expression {
2265 Expression::Column(Box::new(Column {
2266 name: identifier,
2267 table,
2268 join_mark: false,
2269 trailing_comments: Vec::new(),
2270 span: None,
2271 inferred_type: None,
2272 }))
2273 }
2274
2275 fn single_select_source_qualifier(select: &Select) -> Option<Identifier> {
2276 if !select.joins.is_empty() {
2277 return None;
2278 }
2279
2280 let from = select.from.as_ref()?;
2281 if from.expressions.len() != 1 {
2282 return None;
2283 }
2284
2285 Self::source_qualifier(&from.expressions[0])
2286 }
2287
2288 fn source_qualifier(source: &Expression) -> Option<Identifier> {
2289 match source {
2290 Expression::Table(table) => table.alias.clone().or_else(|| Some(table.name.clone())),
2291 Expression::Subquery(subquery) => subquery.alias.clone(),
2292 _ => None,
2293 }
2294 }
2295
2296 fn and_all(mut predicates: Vec<Expression>) -> Option<Expression> {
2297 if predicates.is_empty() {
2298 return None;
2299 }
2300
2301 let first = predicates.remove(0);
2302 Some(predicates.into_iter().fold(first, |left, right| {
2303 Expression::And(Box::new(BinaryOp::new(left, right)))
2304 }))
2305 }
2306
2307 fn or_all(mut predicates: Vec<Expression>) -> Option<Expression> {
2308 if predicates.is_empty() {
2309 return None;
2310 }
2311
2312 let first = predicates.remove(0);
2313 Some(predicates.into_iter().fold(first, |left, right| {
2314 Expression::Or(Box::new(BinaryOp::new(left, right)))
2315 }))
2316 }
2317
2318 pub(super) fn transform_data_type(
2320 &self,
2321 dt: crate::expressions::DataType,
2322 ) -> Result<Expression> {
2323 use crate::expressions::DataType;
2324 let transformed = match dt {
2325 DataType::Boolean => DataType::Custom {
2327 name: "BIT".to_string(),
2328 },
2329 DataType::Int { .. } => dt,
2331 DataType::Decimal { precision, scale } => DataType::Custom {
2334 name: if let (Some(p), Some(s)) = (&precision, &scale) {
2335 format!("NUMERIC({}, {})", p, s)
2336 } else if let Some(p) = &precision {
2337 format!("NUMERIC({})", p)
2338 } else {
2339 "NUMERIC".to_string()
2340 },
2341 },
2342 DataType::Text => DataType::Custom {
2344 name: "VARCHAR(MAX)".to_string(),
2345 },
2346 DataType::Timestamp { .. } => DataType::Custom {
2348 name: "DATETIME2".to_string(),
2349 },
2350 DataType::Uuid => DataType::Custom {
2352 name: "UNIQUEIDENTIFIER".to_string(),
2353 },
2354 DataType::Custom { ref name } => {
2356 let upper = name.trim().to_uppercase();
2357 let (base_name, precision, _scale) = Self::parse_type_precision_and_scale(&upper);
2358 match base_name.as_str() {
2359 "DOUBLE PRECISION" => DataType::Custom {
2361 name: "FLOAT".to_string(),
2362 },
2363 "BPCHAR" => {
2365 if let Some(len) = precision {
2366 DataType::Char { length: Some(len) }
2367 } else {
2368 DataType::Char { length: None }
2369 }
2370 }
2371 _ => dt,
2372 }
2373 }
2374 other => other,
2376 };
2377 Ok(Expression::DataType(transformed))
2378 }
2379
2380 pub(super) fn parse_type_precision_and_scale(name: &str) -> (String, Option<u32>, Option<u32>) {
2382 if let Some(paren_pos) = name.find('(') {
2383 let base = name[..paren_pos].to_string();
2384 let rest = &name[paren_pos + 1..];
2385 if let Some(close_pos) = rest.find(')') {
2386 let args = &rest[..close_pos];
2387 let parts: Vec<&str> = args.split(',').map(|s| s.trim()).collect();
2388 let precision = parts.first().and_then(|s| s.parse::<u32>().ok());
2389 let scale = parts.get(1).and_then(|s| s.parse::<u32>().ok());
2390 return (base, precision, scale);
2391 }
2392 (base, None, None)
2393 } else {
2394 (name.to_string(), None, None)
2395 }
2396 }
2397
2398 fn transform_logical_aggregate(
2399 condition: Expression,
2400 filter: Option<Expression>,
2401 aggregate_name: &str,
2402 ) -> Result<Expression> {
2403 let false_condition = Expression::Not(Box::new(crate::expressions::UnaryOp {
2404 this: condition.clone(),
2405 inferred_type: None,
2406 }));
2407 let true_condition = Self::apply_aggregate_filter(condition, filter.clone());
2408 let false_condition = Self::apply_aggregate_filter(false_condition, filter);
2409
2410 let case_expr = Expression::Case(Box::new(crate::expressions::Case {
2411 operand: None,
2412 whens: vec![
2413 (true_condition, Expression::number(1)),
2414 (false_condition, Expression::number(0)),
2415 ],
2416 else_: Some(Expression::null()),
2417 comments: Vec::new(),
2418 inferred_type: None,
2419 }));
2420
2421 let case_expr = crate::transforms::ensure_bools(case_expr)?;
2422 let aggregate = Expression::Function(Box::new(Function::new(
2423 aggregate_name.to_string(),
2424 vec![case_expr],
2425 )));
2426
2427 Ok(Expression::Cast(Box::new(Cast {
2428 this: aggregate,
2429 to: DataType::Custom {
2430 name: "BIT".to_string(),
2431 },
2432 trailing_comments: Vec::new(),
2433 double_colon_syntax: false,
2434 format: None,
2435 default: None,
2436 inferred_type: None,
2437 })))
2438 }
2439
2440 fn reassociate_logical_aggregate_window(mut window: WindowFunction) -> Expression {
2441 let Expression::Cast(mut cast) = window.this else {
2442 return Expression::WindowFunction(Box::new(window));
2443 };
2444
2445 if !Self::is_transformed_logical_aggregate_cast(&cast) {
2446 window.this = Expression::Cast(cast);
2447 return Expression::WindowFunction(Box::new(window));
2448 }
2449
2450 window.this = cast.this;
2451 cast.this = Expression::WindowFunction(Box::new(window));
2452 Expression::Cast(cast)
2453 }
2454
2455 fn is_transformed_logical_aggregate_cast(cast: &Cast) -> bool {
2456 if !matches!(
2457 &cast.to,
2458 DataType::Custom { name } if name.eq_ignore_ascii_case("BIT")
2459 ) {
2460 return false;
2461 }
2462
2463 let Expression::Function(function) = &cast.this else {
2464 return false;
2465 };
2466 if !matches!(function.name.to_ascii_uppercase().as_str(), "MIN" | "MAX")
2467 || function.args.len() != 1
2468 {
2469 return false;
2470 }
2471
2472 matches!(
2473 function.args.first(),
2474 Some(Expression::Case(case))
2475 if case.operand.is_none()
2476 && case.whens.len() == 2
2477 && matches!(case.else_.as_ref(), Some(Expression::Null(_)))
2478 )
2479 }
2480
2481 fn apply_aggregate_filter(condition: Expression, filter: Option<Expression>) -> Expression {
2482 match filter {
2483 Some(filter) => Expression::And(Box::new(crate::expressions::BinaryOp::new(
2484 filter, condition,
2485 ))),
2486 None => condition,
2487 }
2488 }
2489
2490 fn transform_function(&self, f: Function) -> Result<Expression> {
2491 let name_upper = f.name.to_uppercase();
2492 match name_upper.as_str() {
2493 "COALESCE" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2495 "ISNULL".to_string(),
2496 f.args,
2497 )))),
2498
2499 "NVL" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2501 "ISNULL".to_string(),
2502 f.args,
2503 )))),
2504
2505 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
2507 Function::new("STRING_AGG".to_string(), f.args),
2508 ))),
2509
2510 "STRING_AGG" => Ok(Expression::Function(Box::new(f))),
2512
2513 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
2515 "STRING_AGG".to_string(),
2516 f.args,
2517 )))),
2518
2519 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
2521 "SUBSTRING".to_string(),
2522 f.args,
2523 )))),
2524
2525 "LENGTH" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2527 "LEN".to_string(),
2528 f.args,
2529 )))),
2530
2531 "BTRIM" if f.args.len() == 1 || f.args.len() == 2 => {
2533 let mut args = f.args;
2534 let this = args.remove(0);
2535 let characters = if args.is_empty() {
2536 None
2537 } else {
2538 Some(args.remove(0))
2539 };
2540 Ok(Expression::Trim(Box::new(TrimFunc {
2541 this,
2542 sql_standard_syntax: characters.is_some(),
2543 characters,
2544 position: TrimPosition::Both,
2545 position_explicit: false,
2546 })))
2547 }
2548
2549 "MD5" if f.args.len() == 1 => {
2551 let mut args = f.args;
2552 Ok(Self::tsql_md5_hex(args.remove(0)))
2553 }
2554
2555 "SHA256" if f.args.len() == 1 => {
2556 let mut args = f.args;
2557 Ok(Self::function(
2558 "HASHBYTES",
2559 vec![Expression::string("SHA2_256"), args.remove(0)],
2560 ))
2561 }
2562
2563 "SHA512" if f.args.len() == 1 => {
2564 let mut args = f.args;
2565 Ok(Self::function(
2566 "HASHBYTES",
2567 vec![Expression::string("SHA2_512"), args.remove(0)],
2568 ))
2569 }
2570
2571 "OCTET_LENGTH" if f.args.len() == 1 => Ok(Self::function("DATALENGTH", f.args)),
2573
2574 "BIT_LENGTH" if f.args.len() == 1 => {
2576 let mut args = f.args;
2577 Ok(Expression::Mul(Box::new(BinaryOp::new(
2578 Self::function("DATALENGTH", vec![args.remove(0)]),
2579 Expression::number(8),
2580 ))))
2581 }
2582
2583 "TO_HEX" if f.args.len() == 1 => {
2587 let mut args = f.args;
2588 Ok(Self::tsql_postgres_to_hex(args.remove(0)))
2589 }
2590
2591 "ENCODE" if f.args.len() == 2 => {
2593 let mut args = f.args;
2594 let this = args.remove(0);
2595 let encoding = args.remove(0);
2596 if Self::literal_string(&encoding)
2597 .is_some_and(|encoding| encoding.eq_ignore_ascii_case("hex"))
2598 {
2599 Ok(Self::tsql_hex_from_varbinary(this))
2600 } else {
2601 Ok(Expression::Function(Box::new(Function::new(
2602 "ENCODE".to_string(),
2603 vec![this, encoding],
2604 ))))
2605 }
2606 }
2607
2608 "DECODE"
2611 if f.args.len() == 2
2612 && Self::literal_string(&f.args[1])
2613 .is_some_and(|format| format.eq_ignore_ascii_case("hex")) =>
2614 {
2615 let mut args = f.args;
2616 Ok(Self::tsql_convert(
2617 DataType::Custom {
2618 name: "VARBINARY(MAX)".to_string(),
2619 },
2620 args.remove(0),
2621 Some(2),
2622 ))
2623 }
2624
2625 "REPEAT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2627 "REPLICATE".to_string(),
2628 f.args,
2629 )))),
2630
2631 "CHR" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2633 "CHAR".to_string(),
2634 f.args,
2635 )))),
2636
2637 "RANDOM" => Ok(Expression::Rand(Box::new(crate::expressions::Rand {
2639 seed: None,
2640 lower: None,
2641 upper: None,
2642 }))),
2643
2644 "NOW" => Ok(Self::getdate()),
2646
2647 "CURRENT_TIMESTAMP" => Ok(Self::getdate()),
2649
2650 "CURRENT_DATE" => Ok(Self::cast_getdate_to(DataType::Date)),
2652
2653 "CURRENT_TIME" => Ok(Self::cast_getdate_to(DataType::Time {
2655 precision: None,
2656 timezone: false,
2657 })),
2658
2659 "LOCALTIMESTAMP" => Ok(Self::getdate()),
2661
2662 "CLOCK_TIMESTAMP" if f.args.is_empty() => Ok(Self::function("SYSDATETIME", vec![])),
2664
2665 "MAKE_DATE" if f.args.len() == 3 => Ok(Self::function("DATEFROMPARTS", f.args)),
2667
2668 "MAKE_TIME" if f.args.len() == 3 => Ok(Self::make_time(f.args)),
2671
2672 "TO_DATE" if f.args.len() == 2 => {
2676 Self::formatted_str_to_date_or_fallback(f.args, "TO_DATE")
2677 }
2678
2679 "TO_DATE" if f.args.len() == 1 => {
2681 let mut args = f.args;
2682 Ok(Expression::Cast(Box::new(Cast {
2683 this: args.remove(0),
2684 to: DataType::Date,
2685 trailing_comments: Vec::new(),
2686 double_colon_syntax: false,
2687 format: None,
2688 default: None,
2689 inferred_type: None,
2690 })))
2691 }
2692
2693 "TO_TIMESTAMP" if f.args.len() == 2 => {
2696 Self::formatted_str_to_time_or_fallback(f.args, "TO_TIMESTAMP")
2697 }
2698
2699 "TO_TIMESTAMP" if f.args.len() == 1 => {
2701 let mut args = f.args;
2702 Ok(Expression::UnixToTime(Box::new(
2703 crate::expressions::UnixToTime {
2704 this: Box::new(args.remove(0)),
2705 scale: Some(0),
2706 zone: None,
2707 hours: None,
2708 minutes: None,
2709 format: None,
2710 target_type: None,
2711 },
2712 )))
2713 }
2714
2715 "TO_CHAR" if f.args.len() == 2 => {
2718 Self::formatted_time_to_str_or_fallback(f.args, "TO_CHAR")
2719 }
2720
2721 "TO_CHAR" => Ok(Expression::Function(Box::new(Function::new(
2723 "FORMAT".to_string(),
2724 f.args,
2725 )))),
2726
2727 "DATE_FORMAT" => Ok(Expression::Function(Box::new(Function::new(
2729 "FORMAT".to_string(),
2730 f.args,
2731 )))),
2732
2733 "DATE_TRUNC" | "DATETRUNC" => {
2736 let mut args = Self::uppercase_first_arg_if_identifier(f.args);
2737 if args.len() >= 2 {
2739 if let Expression::Literal(lit) = &args[1] {
2740 if let Literal::String(_) = lit.as_ref() {
2741 args[1] = Expression::Cast(Box::new(Cast {
2742 this: args[1].clone(),
2743 to: DataType::Custom {
2744 name: "DATETIME2".to_string(),
2745 },
2746 trailing_comments: Vec::new(),
2747 double_colon_syntax: false,
2748 format: None,
2749 default: None,
2750 inferred_type: None,
2751 }));
2752 }
2753 }
2754 }
2755 Ok(Expression::Function(Box::new(Function::new(
2756 "DATETRUNC".to_string(),
2757 args,
2758 ))))
2759 }
2760
2761 "DATEADD" => {
2763 let args = Self::uppercase_first_arg_if_identifier(f.args);
2764 Ok(Expression::Function(Box::new(Function::new(
2765 "DATEADD".to_string(),
2766 args,
2767 ))))
2768 }
2769
2770 "DATEDIFF" => {
2772 let args = Self::uppercase_first_arg_if_identifier(f.args);
2773 Ok(Expression::Function(Box::new(Function::new(
2774 "DATEDIFF".to_string(),
2775 args,
2776 ))))
2777 }
2778
2779 "EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2781 "DATEPART".to_string(),
2782 f.args,
2783 )))),
2784
2785 "STRPOS" | "POSITION" if f.args.len() >= 2 => {
2787 Ok(Expression::Function(Box::new(Function::new(
2789 "CHARINDEX".to_string(),
2790 f.args,
2791 ))))
2792 }
2793
2794 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
2796
2797 "CEILING" | "CEIL" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
2799 Function::new("CEILING".to_string(), f.args),
2800 ))),
2801
2802 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2807 "JSON_VALUE".to_string(),
2808 f.args,
2809 )))),
2810
2811 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
2813 "JSON_VALUE".to_string(),
2814 f.args,
2815 )))),
2816
2817 "PARSE_JSON" if f.args.len() == 1 => Ok(f.args.into_iter().next().unwrap()),
2819
2820 "GET_PATH" if f.args.len() == 2 => {
2822 let mut args = f.args;
2823 let this = args.remove(0);
2824 let path = args.remove(0);
2825 let json_path = match &path {
2826 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
2827 let Literal::String(s) = lit.as_ref() else {
2828 unreachable!()
2829 };
2830 let normalized = if s.starts_with('$') {
2831 s.clone()
2832 } else if s.starts_with('[') {
2833 format!("${}", s)
2834 } else {
2835 format!("$.{}", s)
2836 };
2837 Expression::Literal(Box::new(Literal::String(normalized)))
2838 }
2839 _ => path,
2840 };
2841 let json_query = Expression::Function(Box::new(Function::new(
2843 "JSON_QUERY".to_string(),
2844 vec![this.clone(), json_path.clone()],
2845 )));
2846 let json_value = Expression::Function(Box::new(Function::new(
2847 "JSON_VALUE".to_string(),
2848 vec![this, json_path],
2849 )));
2850 Ok(Expression::Function(Box::new(Function::new(
2851 "ISNULL".to_string(),
2852 vec![json_query, json_value],
2853 ))))
2854 }
2855
2856 "JSON_QUERY" if f.args.len() == 1 => {
2859 let this = f.args.into_iter().next().unwrap();
2860 let path = Expression::Literal(Box::new(Literal::String("$".to_string())));
2861 let json_query = Expression::Function(Box::new(Function::new(
2862 "JSON_QUERY".to_string(),
2863 vec![this.clone(), path.clone()],
2864 )));
2865 let json_value = Expression::Function(Box::new(Function::new(
2866 "JSON_VALUE".to_string(),
2867 vec![this, path],
2868 )));
2869 Ok(Expression::Function(Box::new(Function::new(
2870 "ISNULL".to_string(),
2871 vec![json_query, json_value],
2872 ))))
2873 }
2874
2875 "SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2877 "STRING_SPLIT".to_string(),
2878 f.args,
2879 )))),
2880
2881 "REGEXP_LIKE" => {
2884 Ok(Expression::Function(Box::new(Function::new(
2886 "PATINDEX".to_string(),
2887 f.args,
2888 ))))
2889 }
2890
2891 "LN" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2893 "LOG".to_string(),
2894 f.args,
2895 )))),
2896
2897 "STDDEV" | "STDDEV_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2902 "STDEV".to_string(),
2903 f.args,
2904 )))),
2905
2906 "STDDEV_POP" => Ok(Expression::Function(Box::new(Function::new(
2908 "STDEVP".to_string(),
2909 f.args,
2910 )))),
2911
2912 "VARIANCE" | "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2914 "VAR".to_string(),
2915 f.args,
2916 )))),
2917
2918 "VAR_POP" => Ok(Expression::Function(Box::new(Function::new(
2920 "VARP".to_string(),
2921 f.args,
2922 )))),
2923
2924 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" | "EVERY" if f.args.len() == 1 => {
2926 let mut args = f.args;
2927 Self::transform_logical_aggregate(args.remove(0), None, "MIN")
2928 }
2929 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if f.args.len() == 1 => {
2930 let mut args = f.args;
2931 Self::transform_logical_aggregate(args.remove(0), None, "MAX")
2932 }
2933
2934 "DATE_ADD" => {
2936 if f.args.len() == 2 {
2937 let mut args = f.args;
2938 let date = args.remove(0);
2939 let interval = args.remove(0);
2940 let unit = Expression::Identifier(crate::expressions::Identifier {
2941 name: "DAY".to_string(),
2942 quoted: false,
2943 trailing_comments: Vec::new(),
2944 span: None,
2945 });
2946 Ok(Expression::Function(Box::new(Function::new(
2947 "DATEADD".to_string(),
2948 vec![unit, interval, date],
2949 ))))
2950 } else {
2951 let args = Self::uppercase_first_arg_if_identifier(f.args);
2952 Ok(Expression::Function(Box::new(Function::new(
2953 "DATEADD".to_string(),
2954 args,
2955 ))))
2956 }
2957 }
2958
2959 "INSERT" => Ok(Expression::Function(Box::new(Function::new(
2961 "STUFF".to_string(),
2962 f.args,
2963 )))),
2964
2965 "SUSER_NAME" | "SUSER_SNAME" | "SYSTEM_USER" => Ok(Expression::CurrentUser(Box::new(
2967 crate::expressions::CurrentUser { this: None },
2968 ))),
2969
2970 _ => Ok(Expression::Function(Box::new(f))),
2972 }
2973 }
2974
2975 fn literal_string(expr: &Expression) -> Option<&str> {
2976 match expr {
2977 Expression::Literal(lit) => match lit.as_ref() {
2978 Literal::String(s) => Some(s),
2979 _ => None,
2980 },
2981 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
2982 if Self::is_text_data_type(&cast.to) =>
2983 {
2984 Self::literal_string(&cast.this)
2985 }
2986 _ => None,
2987 }
2988 }
2989
2990 fn is_text_data_type(data_type: &DataType) -> bool {
2991 match data_type {
2992 DataType::Char { .. }
2993 | DataType::VarChar { .. }
2994 | DataType::String { .. }
2995 | DataType::Text
2996 | DataType::TextWithLength { .. } => true,
2997 DataType::Custom { name } => {
2998 let base = name
2999 .split_once('(')
3000 .map_or(name.as_str(), |(base, _)| base)
3001 .trim();
3002 matches!(
3003 base.to_ascii_uppercase().as_str(),
3004 "CHAR"
3005 | "NCHAR"
3006 | "VARCHAR"
3007 | "NVARCHAR"
3008 | "TEXT"
3009 | "NTEXT"
3010 | "STRING"
3011 | "CHARACTER VARYING"
3012 )
3013 }
3014 _ => false,
3015 }
3016 }
3017
3018 fn is_numeric_data_type(data_type: &DataType) -> bool {
3019 match data_type {
3020 DataType::TinyInt { .. }
3021 | DataType::SmallInt { .. }
3022 | DataType::Int { .. }
3023 | DataType::BigInt { .. }
3024 | DataType::Float { .. }
3025 | DataType::Double { .. }
3026 | DataType::Decimal { .. } => true,
3027 DataType::Custom { name } => {
3028 let base = name
3029 .split_once('(')
3030 .map_or(name.as_str(), |(base, _)| base)
3031 .trim();
3032 matches!(
3033 base.to_ascii_uppercase().as_str(),
3034 "TINYINT"
3035 | "SMALLINT"
3036 | "INT"
3037 | "INTEGER"
3038 | "BIGINT"
3039 | "DECIMAL"
3040 | "NUMERIC"
3041 | "REAL"
3042 | "FLOAT"
3043 | "MONEY"
3044 | "SMALLMONEY"
3045 )
3046 }
3047 _ => false,
3048 }
3049 }
3050
3051 fn is_explicitly_numeric_expression(expr: &Expression) -> bool {
3052 if expr.inferred_type().is_some_and(Self::is_numeric_data_type) {
3053 return true;
3054 }
3055
3056 match expr {
3057 Expression::Literal(literal) => matches!(literal.as_ref(), Literal::Number(_)),
3058 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
3059 Self::is_numeric_data_type(&cast.to)
3060 }
3061 Expression::Alias(alias) => Self::is_explicitly_numeric_expression(&alias.this),
3062 Expression::Paren(paren) => Self::is_explicitly_numeric_expression(&paren.this),
3063 Expression::Neg(unary) => Self::is_explicitly_numeric_expression(&unary.this),
3064 _ => false,
3065 }
3066 }
3067
3068 fn is_postgres_numeric_to_char_format(format: &str) -> bool {
3069 let mut unquoted = String::with_capacity(format.len());
3070 let mut quoted = false;
3071 let mut chars = format.chars().peekable();
3072
3073 while let Some(ch) = chars.next() {
3074 if ch == '"' {
3075 if quoted && chars.peek() == Some(&'"') {
3076 chars.next();
3077 } else {
3078 quoted = !quoted;
3079 }
3080 } else if !quoted {
3081 unquoted.extend(ch.to_uppercase());
3082 }
3083 }
3084
3085 unquoted.contains(['9', '0'])
3086 || ["PR", "SG", "PL", "RN", "EEEE"]
3087 .iter()
3088 .any(|token| unquoted.contains(token))
3089 }
3090
3091 fn postgres_format_to_strftime(format: &str) -> String {
3092 const POSTGRES_FORMAT_TO_STRFTIME: &[(&str, &str)] = &[
3093 ("FMHH24", "%-H"),
3094 ("FMHH12", "%-I"),
3095 ("FMDDD", "%-j"),
3096 ("TMMonth", "%B"),
3097 ("TMMon", "%b"),
3098 ("TMDay", "%A"),
3099 ("TMDy", "%a"),
3100 ("YYYY", "%Y"),
3101 ("yyyy", "%Y"),
3102 ("HH24", "%H"),
3103 ("HH12", "%I"),
3104 ("FMDD", "%-d"),
3105 ("FMMM", "%-m"),
3106 ("FMMI", "%-M"),
3107 ("FMSS", "%-S"),
3108 ("DDD", "%j"),
3109 ("ddd", "%j"),
3110 ("YY", "%y"),
3111 ("yy", "%y"),
3112 ("MM", "%m"),
3113 ("mm", "%m"),
3114 ("DD", "%d"),
3115 ("dd", "%d"),
3116 ("MI", "%M"),
3117 ("mi", "%M"),
3118 ("SS", "%S"),
3119 ("ss", "%S"),
3120 ("US", "%f"),
3121 ("OF", "%z"),
3122 ("TZ", "%Z"),
3123 ("WW", "%U"),
3124 ("ww", "%U"),
3125 ("D", "%u"),
3126 ("d", "%u"),
3127 ];
3128 crate::format_tokens::convert_format_tokens(format, POSTGRES_FORMAT_TO_STRFTIME)
3129 .unwrap_or_else(|| format.to_string())
3130 }
3131
3132 fn formatted_str_to_time_or_fallback(
3133 mut args: Vec<Expression>,
3134 original_name: &str,
3135 ) -> Result<Expression> {
3136 let this = args.remove(0);
3137 let format = args.remove(0);
3138 if let Some(format) = Self::literal_string(&format) {
3139 Ok(Expression::StrToTime(Box::new(
3140 crate::expressions::StrToTime {
3141 this: Box::new(this),
3142 format: Self::postgres_format_to_strftime(format),
3143 zone: None,
3144 safe: None,
3145 target_type: Some(Box::new(Expression::DataType(DataType::Custom {
3146 name: "DATETIME2".to_string(),
3147 }))),
3148 },
3149 )))
3150 } else {
3151 Ok(Expression::Function(Box::new(Function::new(
3152 original_name.to_string(),
3153 vec![this, format],
3154 ))))
3155 }
3156 }
3157
3158 fn formatted_str_to_date_or_fallback(
3159 mut args: Vec<Expression>,
3160 original_name: &str,
3161 ) -> Result<Expression> {
3162 let this = args.remove(0);
3163 let format = args.remove(0);
3164 if let Some(format) = Self::literal_string(&format) {
3165 Ok(Expression::StrToDate(Box::new(
3166 crate::expressions::StrToDate {
3167 this: Box::new(this),
3168 format: Some(Self::postgres_format_to_strftime(format)),
3169 safe: None,
3170 },
3171 )))
3172 } else {
3173 Ok(Expression::Function(Box::new(Function::new(
3174 original_name.to_string(),
3175 vec![this, format],
3176 ))))
3177 }
3178 }
3179
3180 fn formatted_time_to_str_or_fallback(
3181 mut args: Vec<Expression>,
3182 original_name: &str,
3183 ) -> Result<Expression> {
3184 let this = args.remove(0);
3185 let format = args.remove(0);
3186 if let Some(format_string) = Self::literal_string(&format).map(str::to_owned) {
3187 if Self::is_explicitly_numeric_expression(&this)
3188 || Self::is_postgres_numeric_to_char_format(&format_string)
3189 {
3190 return Ok(Expression::Function(Box::new(Function::new(
3191 original_name.to_string(),
3192 vec![this, format],
3193 ))));
3194 }
3195
3196 Ok(Expression::TimeToStr(Box::new(
3197 crate::expressions::TimeToStr {
3198 this: Box::new(this),
3199 format: Self::postgres_format_to_strftime(&format_string),
3200 culture: None,
3201 zone: None,
3202 },
3203 )))
3204 } else {
3205 Ok(Expression::Function(Box::new(Function::new(
3206 original_name.to_string(),
3207 vec![this, format],
3208 ))))
3209 }
3210 }
3211
3212 fn transform_aggregate_function(
3213 &self,
3214 mut f: Box<crate::expressions::AggregateFunction>,
3215 ) -> Result<Expression> {
3216 let name_upper = f.name.to_uppercase();
3217 if matches!(
3218 name_upper.as_str(),
3219 "SUM"
3220 | "AVG"
3221 | "MIN"
3222 | "MAX"
3223 | "COUNT"
3224 | "COUNT_BIG"
3225 | "ANY_VALUE"
3226 | "APPROX_COUNT_DISTINCT"
3227 | "STDEV"
3228 | "STDEVP"
3229 | "VAR"
3230 | "VARP"
3231 | "BOOL_AND"
3232 | "BOOL_OR"
3233 | "LOGICAL_AND"
3234 | "LOGICAL_OR"
3235 | "BIT_AND"
3236 | "BIT_OR"
3237 | "BIT_XOR"
3238 ) {
3239 f.order_by.clear();
3240 }
3241
3242 match name_upper.as_str() {
3243 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3245 Function::new("STRING_AGG".to_string(), f.args),
3246 ))),
3247
3248 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3250 "STRING_AGG".to_string(),
3251 f.args,
3252 )))),
3253
3254 "ARRAY_AGG" if !f.args.is_empty() => {
3257 Ok(Expression::Function(Box::new(Function::new(
3259 "STRING_AGG".to_string(),
3260 f.args,
3261 ))))
3262 }
3263
3264 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" | "EVERY" if f.args.len() == 1 => {
3266 let mut args = f.args;
3267 Self::transform_logical_aggregate(args.remove(0), f.filter, "MIN")
3268 }
3269 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if f.args.len() == 1 => {
3270 let mut args = f.args;
3271 Self::transform_logical_aggregate(args.remove(0), f.filter, "MAX")
3272 }
3273
3274 _ => Ok(Expression::AggregateFunction(f)),
3276 }
3277 }
3278
3279 fn without_inert_ordering(
3280 mut aggregate: Box<crate::expressions::AggFunc>,
3281 ) -> Box<crate::expressions::AggFunc> {
3282 aggregate.order_by.clear();
3283 aggregate
3284 }
3285
3286 fn transform_cte(&self, cte: Cte) -> Result<Expression> {
3290 Ok(Expression::Cte(Box::new(self.transform_cte_inner(cte))))
3291 }
3292
3293 fn transform_cte_inner(&self, mut cte: Cte) -> Cte {
3295 if cte.columns.is_empty() {
3298 cte.this = self.qualify_derived_table_outputs(cte.this);
3299 }
3300 cte
3301 }
3302
3303 fn transform_subquery(&self, mut subquery: Subquery) -> Result<Expression> {
3307 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
3310 subquery.this = self.qualify_derived_table_outputs(subquery.this);
3311 }
3312 Ok(Expression::Subquery(Box::new(subquery)))
3313 }
3314
3315 fn qualify_derived_table_outputs(&self, expr: Expression) -> Expression {
3319 match expr {
3320 Expression::Select(mut select) => {
3321 let has_from = select.from.is_some();
3324 if !has_from {
3325 select.expressions = select
3326 .expressions
3327 .into_iter()
3328 .map(|e| self.maybe_alias_expression(e))
3329 .collect();
3330 }
3331 Expression::Select(select)
3332 }
3333 Expression::Union(mut u) => {
3335 let left = std::mem::replace(&mut u.left, Expression::Null(Null));
3336 u.left = self.qualify_derived_table_outputs(left);
3337 Expression::Union(u)
3338 }
3339 Expression::Intersect(mut i) => {
3340 let left = std::mem::replace(&mut i.left, Expression::Null(Null));
3341 i.left = self.qualify_derived_table_outputs(left);
3342 Expression::Intersect(i)
3343 }
3344 Expression::Except(mut e) => {
3345 let left = std::mem::replace(&mut e.left, Expression::Null(Null));
3346 e.left = self.qualify_derived_table_outputs(left);
3347 Expression::Except(e)
3348 }
3349 Expression::Subquery(mut s) => {
3351 s.this = self.qualify_derived_table_outputs(s.this);
3352 Expression::Subquery(s)
3353 }
3354 other => other,
3356 }
3357 }
3358
3359 fn maybe_alias_expression(&self, expr: Expression) -> Expression {
3364 match &expr {
3365 Expression::Alias(_) => expr,
3367 Expression::Aliases(_) => expr,
3369 Expression::Star(_) => expr,
3371 _ => {
3376 if let Some(output_name) = self.get_output_name(&expr) {
3377 Expression::Alias(Box::new(Alias {
3378 this: expr,
3379 alias: Identifier {
3380 name: output_name,
3381 quoted: true, trailing_comments: Vec::new(),
3383 span: None,
3384 },
3385 column_aliases: Vec::new(),
3386 alias_explicit_as: false,
3387 alias_keyword: None,
3388 pre_alias_comments: Vec::new(),
3389 trailing_comments: Vec::new(),
3390 inferred_type: None,
3391 }))
3392 } else {
3393 expr
3395 }
3396 }
3397 }
3398 }
3399
3400 fn get_output_name(&self, expr: &Expression) -> Option<String> {
3404 match expr {
3405 Expression::Literal(lit) => match lit.as_ref() {
3407 Literal::Number(n) => Some(n.clone()),
3408 Literal::String(s) => Some(s.clone()),
3409 Literal::HexString(h) => Some(format!("0x{}", h)),
3410 Literal::HexNumber(h) => Some(format!("0x{}", h)),
3411 Literal::BitString(b) => Some(format!("b{}", b)),
3412 Literal::ByteString(b) => Some(format!("b'{}'", b)),
3413 Literal::NationalString(s) => Some(format!("N'{}'", s)),
3414 Literal::Date(d) => Some(d.clone()),
3415 Literal::Time(t) => Some(t.clone()),
3416 Literal::Timestamp(ts) => Some(ts.clone()),
3417 Literal::Datetime(dt) => Some(dt.clone()),
3418 Literal::TripleQuotedString(s, _) => Some(s.clone()),
3419 Literal::EscapeString(s) => Some(s.clone()),
3420 Literal::DollarString(s) => Some(s.clone()),
3421 Literal::RawString(s) => Some(s.clone()),
3422 },
3423 Expression::Column(col) => Some(col.name.name.clone()),
3425 Expression::Identifier(ident) => Some(ident.name.clone()),
3427 Expression::Boolean(b) => Some(if b.value { "1" } else { "0" }.to_string()),
3429 Expression::Null(_) => Some("NULL".to_string()),
3431 Expression::Function(f) => Some(f.name.clone()),
3433 Expression::AggregateFunction(f) => Some(f.name.clone()),
3435 _ => Some(format!("_col_{}", 0)),
3437 }
3438 }
3439
3440 fn uppercase_first_arg_if_identifier(mut args: Vec<Expression>) -> Vec<Expression> {
3442 use crate::expressions::Identifier;
3443 if !args.is_empty() {
3444 match &args[0] {
3445 Expression::Identifier(id) => {
3446 args[0] = Expression::Identifier(Identifier {
3447 name: id.name.to_uppercase(),
3448 quoted: id.quoted,
3449 trailing_comments: id.trailing_comments.clone(),
3450 span: None,
3451 });
3452 }
3453 Expression::Var(v) => {
3454 args[0] = Expression::Identifier(Identifier {
3455 name: v.this.to_uppercase(),
3456 quoted: false,
3457 trailing_comments: Vec::new(),
3458 span: None,
3459 });
3460 }
3461 Expression::Column(col) if col.table.is_none() => {
3462 args[0] = Expression::Identifier(Identifier {
3463 name: col.name.name.to_uppercase(),
3464 quoted: col.name.quoted,
3465 trailing_comments: col.name.trailing_comments.clone(),
3466 span: None,
3467 });
3468 }
3469 _ => {}
3470 }
3471 }
3472 args
3473 }
3474}
3475
3476#[cfg(test)]
3477mod tests {
3478 use super::*;
3479 use crate::dialects::Dialect;
3480
3481 fn transpile_to_tsql(sql: &str) -> String {
3482 let dialect = Dialect::get(DialectType::Generic);
3483 let result = dialect
3484 .transpile(sql, DialectType::TSQL)
3485 .expect("Transpile failed");
3486 result[0].clone()
3487 }
3488
3489 #[test]
3490 fn test_nvl_to_isnull() {
3491 let result = transpile_to_tsql("SELECT NVL(a, b)");
3492 assert!(
3493 result.contains("ISNULL"),
3494 "Expected ISNULL, got: {}",
3495 result
3496 );
3497 }
3498
3499 #[test]
3500 fn test_coalesce_to_isnull() {
3501 let result = transpile_to_tsql("SELECT COALESCE(a, b)");
3502 assert!(
3503 result.contains("ISNULL"),
3504 "Expected ISNULL, got: {}",
3505 result
3506 );
3507 }
3508
3509 #[test]
3510 fn test_basic_select() {
3511 let result = transpile_to_tsql("SELECT a, b FROM users WHERE id = 1");
3512 assert!(result.contains("SELECT"));
3513 assert!(result.contains("FROM users"));
3514 }
3515
3516 #[test]
3517 fn test_length_to_len() {
3518 let result = transpile_to_tsql("SELECT LENGTH(name)");
3519 assert!(result.contains("LEN"), "Expected LEN, got: {}", result);
3520 }
3521
3522 #[test]
3523 fn test_now_to_getdate() {
3524 let result = transpile_to_tsql("SELECT NOW()");
3525 assert!(
3526 result.contains("GETDATE"),
3527 "Expected GETDATE, got: {}",
3528 result
3529 );
3530 }
3531
3532 #[test]
3533 fn test_group_concat_to_string_agg() {
3534 let result = transpile_to_tsql("SELECT GROUP_CONCAT(name)");
3535 assert!(
3536 result.contains("STRING_AGG"),
3537 "Expected STRING_AGG, got: {}",
3538 result
3539 );
3540 }
3541
3542 #[test]
3543 fn test_listagg_to_string_agg() {
3544 let result = transpile_to_tsql("SELECT LISTAGG(name)");
3545 assert!(
3546 result.contains("STRING_AGG"),
3547 "Expected STRING_AGG, got: {}",
3548 result
3549 );
3550 }
3551
3552 #[test]
3553 fn test_ln_to_log() {
3554 let result = transpile_to_tsql("SELECT LN(x)");
3555 assert!(result.contains("LOG"), "Expected LOG, got: {}", result);
3556 }
3557
3558 #[test]
3559 fn test_stddev_to_stdev() {
3560 let result = transpile_to_tsql("SELECT STDDEV(x)");
3561 assert!(result.contains("STDEV"), "Expected STDEV, got: {}", result);
3562 }
3563
3564 #[test]
3565 fn test_bracket_identifiers() {
3566 let dialect = Dialect::get(DialectType::TSQL);
3568 let config = dialect.generator_config();
3569 assert_eq!(config.identifier_quote, '[');
3570 }
3571
3572 #[test]
3573 fn test_json_query_isnull_wrapper_simple() {
3574 let dialect = Dialect::get(DialectType::TSQL);
3576 let result = dialect
3577 .transpile(r#"JSON_QUERY(x, '$')"#, DialectType::TSQL)
3578 .expect("transpile failed");
3579 assert!(
3580 result[0].contains("ISNULL"),
3581 "JSON_QUERY should be wrapped with ISNULL: {}",
3582 result[0]
3583 );
3584 }
3585
3586 #[test]
3587 fn test_json_query_isnull_wrapper_nested() {
3588 let dialect = Dialect::get(DialectType::TSQL);
3589 let result = dialect
3590 .transpile(
3591 r#"JSON_QUERY(REPLACE(REPLACE(x, '''', '"'), '""', '"'))"#,
3592 DialectType::TSQL,
3593 )
3594 .expect("transpile failed");
3595 let expected = r#"ISNULL(JSON_QUERY(REPLACE(REPLACE(x, '''', '"'), '""', '"'), '$'), JSON_VALUE(REPLACE(REPLACE(x, '''', '"'), '""', '"'), '$'))"#;
3596 assert_eq!(
3597 result[0], expected,
3598 "JSON_QUERY should be wrapped with ISNULL"
3599 );
3600 }
3601}