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::ToNumber(f) => Ok(Self::to_number_or_fallback(*f)),
550
551 Expression::VarPop(f) => Ok(Expression::Function(Box::new(Function::new(
554 "VARP".to_string(),
555 vec![f.this],
556 )))),
557
558 Expression::Variance(f) => Ok(Expression::Function(Box::new(Function::new(
560 "VAR".to_string(),
561 vec![f.this],
562 )))),
563 Expression::VarSamp(f) => Ok(Expression::Function(Box::new(Function::new(
564 "VAR".to_string(),
565 vec![f.this],
566 )))),
567
568 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
571 "HASHBYTES".to_string(),
572 vec![Expression::string("MD5"), *f.this],
573 )))),
574
575 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
577 "HASHBYTES".to_string(),
578 vec![Expression::string("SHA1"), f.this],
579 )))),
580
581 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
583 "HASHBYTES".to_string(),
584 vec![Expression::string("SHA1"), f.this],
585 )))),
586
587 Expression::ArrayToString(f) => Ok(Expression::Function(Box::new(Function::new(
590 "STRING_AGG".to_string(),
591 vec![f.this],
592 )))),
593
594 Expression::AutoIncrementColumnConstraint(_) => Ok(Expression::Function(Box::new(
597 Function::new("IDENTITY".to_string(), vec![]),
598 ))),
599
600 Expression::CreateView(mut view) => {
604 view.name.catalog = None;
606 Ok(Expression::CreateView(view))
607 }
608
609 Expression::DropView(mut view) => {
610 view.name.catalog = None;
612 Ok(Expression::DropView(view))
613 }
614
615 Expression::JSONExtract(e) if e.variant_extract.is_some() => {
619 let path = match *e.expression {
620 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
621 let Literal::String(s) = lit.as_ref() else {
622 unreachable!()
623 };
624 let normalized = if s.starts_with('$') {
625 s.clone()
626 } else if s.starts_with('[') {
627 format!("${}", s)
628 } else {
629 format!("$.{}", s)
630 };
631 Expression::Literal(Box::new(Literal::String(normalized)))
632 }
633 other => other,
634 };
635 let json_query = Expression::Function(Box::new(Function::new(
636 "JSON_QUERY".to_string(),
637 vec![(*e.this).clone(), path.clone()],
638 )));
639 let json_value = Expression::Function(Box::new(Function::new(
640 "JSON_VALUE".to_string(),
641 vec![*e.this, path],
642 )));
643 Ok(Expression::Function(Box::new(Function::new(
644 "ISNULL".to_string(),
645 vec![json_query, json_value],
646 ))))
647 }
648
649 Expression::Function(f) => self.transform_function(*f),
651
652 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
654
655 Expression::Cte(cte) => self.transform_cte(*cte),
658
659 Expression::Subquery(subquery) => self.transform_subquery(*subquery),
662
663 Expression::JsonQuery(f) => {
665 let json_query = Expression::Function(Box::new(Function::new(
666 "JSON_QUERY".to_string(),
667 vec![f.this.clone(), f.path.clone()],
668 )));
669 let json_value = Expression::Function(Box::new(Function::new(
670 "JSON_VALUE".to_string(),
671 vec![f.this, f.path],
672 )));
673 Ok(Expression::Function(Box::new(Function::new(
674 "ISNULL".to_string(),
675 vec![json_query, json_value],
676 ))))
677 }
678 Expression::JsonValue(f) => Ok(Expression::Function(Box::new(Function::new(
680 "JSON_VALUE".to_string(),
681 vec![f.this, f.path],
682 )))),
683
684 Expression::Any(ref q) if matches!(&q.op, Some(QuantifiedOp::Eq)) => {
687 match Self::scalar_array_comparison_values(&q.subquery) {
688 Some(expressions) if expressions.is_empty() => {
689 Ok(Expression::Eq(Box::new(crate::expressions::BinaryOp::new(
690 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
691 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
692 ))))
693 }
694 Some(expressions) => Ok(Expression::In(Box::new(In {
695 this: q.this.clone(),
696 expressions,
697 query: None,
698 not: false,
699 global: false,
700 unnest: None,
701 is_field: false,
702 }))),
703 None => Ok(expr.clone()),
704 }
705 }
706
707 _ => Ok(expr),
709 }
710 }
711}
712
713#[cfg(feature = "transpile")]
714impl TSQLDialect {
715 fn getdate() -> Expression {
716 Expression::Function(Box::new(Function::new("GETDATE".to_string(), vec![])))
717 }
718
719 fn cast_getdate_to(to: DataType) -> Expression {
720 Expression::Cast(Box::new(Cast {
721 this: Self::getdate(),
722 to,
723 trailing_comments: Vec::new(),
724 double_colon_syntax: false,
725 format: None,
726 default: None,
727 inferred_type: None,
728 }))
729 }
730
731 fn cast(this: Expression, to: DataType) -> Expression {
732 Expression::Cast(Box::new(Cast {
733 this,
734 to,
735 trailing_comments: Vec::new(),
736 double_colon_syntax: false,
737 format: None,
738 default: None,
739 inferred_type: None,
740 }))
741 }
742
743 fn function(name: impl Into<String>, args: Vec<Expression>) -> Expression {
744 Expression::Function(Box::new(Function::new(name, args)))
745 }
746
747 fn lower(this: Expression) -> Expression {
748 Expression::Lower(Box::new(UnaryFunc::new(this)))
749 }
750
751 fn tsql_convert(to: DataType, expression: Expression, style: Option<i64>) -> Expression {
752 let mut args = vec![Expression::DataType(to), expression];
753 if let Some(style) = style {
754 args.push(Expression::number(style));
755 }
756 Self::function("CONVERT", args)
757 }
758
759 fn tsql_hex_text(expression: Expression, varchar_type: DataType) -> Expression {
760 Self::lower(Self::tsql_convert(varchar_type, expression, Some(2)))
761 }
762
763 fn tsql_hex_from_varbinary(expression: Expression) -> Expression {
764 Self::tsql_hex_text(
765 Self::cast(
766 expression,
767 DataType::Custom {
768 name: "VARBINARY(MAX)".to_string(),
769 },
770 ),
771 DataType::Text,
772 )
773 }
774
775 fn tsql_md5_hex(expression: Expression) -> Expression {
776 let hashbytes = Self::function("HASHBYTES", vec![Expression::string("MD5"), expression]);
777 Self::tsql_hex_text(
778 hashbytes,
779 DataType::VarChar {
780 length: Some(32),
781 parenthesized_length: false,
782 },
783 )
784 }
785
786 fn overlay_to_stuff(f: crate::expressions::OverlayFunc) -> Expression {
787 let length = f
788 .length
789 .unwrap_or_else(|| Self::function("LEN", vec![f.replacement.clone()]));
790 Self::function("STUFF", vec![f.this, f.from, length, f.replacement])
791 }
792
793 fn starts_with_predicate(this: Expression, prefix: Expression) -> Expression {
794 let prefix_len = Self::function("LEN", vec![prefix.clone()]);
795 let left_prefix = Self::function("LEFT", vec![this, prefix_len]);
796 Self::eq(left_prefix, prefix)
797 }
798
799 fn to_number_or_fallback(f: crate::expressions::ToNumber) -> Expression {
800 let crate::expressions::ToNumber {
801 this,
802 format,
803 nlsparam,
804 precision,
805 scale,
806 safe,
807 safe_name,
808 } = f;
809
810 if nlsparam.is_none()
811 && precision.is_none()
812 && scale.is_none()
813 && safe.is_none()
814 && safe_name.is_none()
815 {
816 if let Some(format) = format.as_deref() {
817 if let Some(scale) = Self::simple_to_number_scale(format) {
818 return Self::function(
819 "TRY_CONVERT",
820 vec![
821 Expression::DataType(DataType::Decimal {
822 precision: Some(18),
823 scale: Some(scale),
824 }),
825 *this,
826 ],
827 );
828 }
829 }
830 }
831
832 Expression::ToNumber(Box::new(crate::expressions::ToNumber {
833 this,
834 format,
835 nlsparam,
836 precision,
837 scale,
838 safe,
839 safe_name,
840 }))
841 }
842
843 fn simple_to_number_scale(format: &Expression) -> Option<u32> {
844 let format = Self::literal_string(format)?;
845 let format = format.strip_prefix("FM").unwrap_or(format);
846 let mut saw_digit = false;
847 let mut saw_decimal = false;
848 let mut scale = 0u32;
849
850 for ch in format.chars() {
851 match ch {
852 '9' | '0' => {
853 saw_digit = true;
854 if saw_decimal {
855 scale = scale.checked_add(1)?;
856 }
857 }
858 '.' if !saw_decimal => saw_decimal = true,
859 ',' | ' ' => {}
860 _ => return None,
861 }
862 }
863
864 saw_digit.then_some(scale)
865 }
866
867 fn binary(
868 left: Expression,
869 right: Expression,
870 op: fn(Box<BinaryOp>) -> Expression,
871 ) -> Expression {
872 op(Box::new(BinaryOp {
873 left,
874 right,
875 left_comments: Vec::new(),
876 operator_comments: Vec::new(),
877 trailing_comments: Vec::new(),
878 inferred_type: None,
879 }))
880 }
881
882 fn eq(left: Expression, right: Expression) -> Expression {
883 Self::binary(left, right, Expression::Eq)
884 }
885
886 fn or(left: Expression, right: Expression) -> Expression {
887 Self::binary(left, right, Expression::Or)
888 }
889
890 fn not(this: Expression) -> Expression {
891 Expression::Not(Box::new(crate::expressions::UnaryOp {
892 this,
893 inferred_type: None,
894 }))
895 }
896
897 fn is_null(this: Expression) -> Expression {
898 Expression::IsNull(Box::new(crate::expressions::IsNull {
899 this,
900 not: false,
901 postfix_form: false,
902 }))
903 }
904
905 fn paren(this: Expression) -> Expression {
906 Expression::Paren(Box::new(Paren {
907 this,
908 trailing_comments: Vec::new(),
909 }))
910 }
911
912 fn boolean_test_case_for_predicate(
913 predicate: Expression,
914 test_true: bool,
915 negated: bool,
916 ) -> Expression {
917 let condition = match (test_true, negated) {
918 (true, false) => predicate,
919 (false, false) => Self::not(predicate),
920 (true, true) => {
921 return Expression::Case(Box::new(crate::expressions::Case {
922 operand: None,
923 whens: vec![(predicate, Expression::number(0))],
924 else_: Some(Expression::number(1)),
925 comments: Vec::new(),
926 inferred_type: None,
927 }))
928 }
929 (false, true) => {
930 return Expression::Case(Box::new(crate::expressions::Case {
931 operand: None,
932 whens: vec![(Self::not(predicate), Expression::number(0))],
933 else_: Some(Expression::number(1)),
934 comments: Vec::new(),
935 inferred_type: None,
936 }))
937 }
938 };
939
940 Expression::Case(Box::new(crate::expressions::Case {
941 operand: None,
942 whens: vec![(condition, Expression::number(1))],
943 else_: Some(Expression::number(0)),
944 comments: Vec::new(),
945 inferred_type: None,
946 }))
947 }
948
949 fn boolean_test_predicate(operand: Expression, test_true: bool, negated: bool) -> Expression {
950 if Self::is_boolean_predicate_operand(&operand) {
951 return match (test_true, negated) {
952 (true, false) => operand,
953 (false, false) => Self::not(operand),
954 _ => Self::eq(
955 Self::boolean_test_case_for_predicate(operand, test_true, negated),
956 Expression::number(1),
957 ),
958 };
959 }
960
961 match (test_true, negated) {
962 (true, false) => Self::eq(operand, Expression::number(1)),
963 (false, false) => Self::eq(operand, Expression::number(0)),
964 (true, true) => Self::or(
965 Self::eq(operand.clone(), Expression::number(0)),
966 Self::is_null(operand),
967 ),
968 (false, true) => Self::or(
969 Self::eq(operand.clone(), Expression::number(1)),
970 Self::is_null(operand),
971 ),
972 }
973 }
974
975 fn is_boolean_predicate_operand(expr: &Expression) -> bool {
976 match expr {
977 Expression::Paren(paren) => Self::is_boolean_predicate_operand(&paren.this),
978 Expression::Eq(_)
979 | Expression::Neq(_)
980 | Expression::Lt(_)
981 | Expression::Lte(_)
982 | Expression::Gt(_)
983 | Expression::Gte(_)
984 | Expression::Is(_)
985 | Expression::IsNull(_)
986 | Expression::IsTrue(_)
987 | Expression::IsFalse(_)
988 | Expression::Like(_)
989 | Expression::ILike(_)
990 | Expression::SimilarTo(_)
991 | Expression::Glob(_)
992 | Expression::RegexpLike(_)
993 | Expression::In(_)
994 | Expression::Between(_)
995 | Expression::Exists(_)
996 | Expression::And(_)
997 | Expression::Or(_)
998 | Expression::Not(_)
999 | Expression::Any(_)
1000 | Expression::All(_)
1001 | Expression::EqualNull(_) => true,
1002 _ => false,
1003 }
1004 }
1005
1006 fn scalar_array_comparison_values(expr: &Expression) -> Option<Vec<Expression>> {
1007 let (mut values, element_type) = Self::scalar_array_comparison_values_inner(expr)?;
1008 if let Some(to) = element_type {
1009 values = values
1010 .into_iter()
1011 .map(|value| Self::cast_scalar_array_comparison_value(value, to.clone()))
1012 .collect();
1013 }
1014 Some(values)
1015 }
1016
1017 fn scalar_array_comparison_values_inner(
1018 expr: &Expression,
1019 ) -> Option<(Vec<Expression>, Option<DataType>)> {
1020 match expr {
1021 Expression::ArrayFunc(a) => Some((a.expressions.clone(), None)),
1022 Expression::Array(a) => Some((a.expressions.clone(), None)),
1023 Expression::Tuple(t) => Some((t.expressions.clone(), None)),
1024 Expression::Paren(p) => Self::scalar_array_comparison_values_inner(&p.this),
1025 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
1026 let DataType::Array { element_type, .. } = &c.to else {
1027 return None;
1028 };
1029 let (values, _) = Self::scalar_array_comparison_values_inner(&c.this)?;
1030 Some((values, Some((**element_type).clone())))
1031 }
1032 _ => None,
1033 }
1034 }
1035
1036 fn cast_scalar_array_comparison_value(value: Expression, to: DataType) -> Expression {
1037 if matches!(&value, Expression::Cast(c) if c.to == to) {
1038 return value;
1039 }
1040
1041 Expression::Cast(Box::new(Cast {
1042 this: value,
1043 to,
1044 trailing_comments: Vec::new(),
1045 double_colon_syntax: false,
1046 format: None,
1047 default: None,
1048 inferred_type: None,
1049 }))
1050 }
1051
1052 fn normalize_frame_incompatible_window_functions(select: &mut Select) {
1053 let window_map: HashMap<String, Over> = select
1054 .windows
1055 .as_ref()
1056 .map(|windows| {
1057 windows
1058 .iter()
1059 .map(|window| (window.name.name.to_lowercase(), window.spec.clone()))
1060 .collect()
1061 })
1062 .unwrap_or_default();
1063
1064 for expr in &mut select.expressions {
1065 Self::normalize_frame_incompatible_window_expr(expr, &window_map);
1066 }
1067
1068 if let Some(order_by) = &mut select.order_by {
1069 for ordered in &mut order_by.expressions {
1070 Self::normalize_frame_incompatible_window_expr(&mut ordered.this, &window_map);
1071 }
1072 }
1073
1074 if let Some(qualify) = &mut select.qualify {
1075 Self::normalize_frame_incompatible_window_expr(&mut qualify.this, &window_map);
1076 }
1077 }
1078
1079 fn normalize_frame_incompatible_window_expr(
1080 expr: &mut Expression,
1081 window_map: &HashMap<String, Over>,
1082 ) {
1083 match expr {
1084 Expression::WindowFunction(wf) => {
1085 Self::normalize_frame_incompatible_window_expr(&mut wf.this, window_map);
1086
1087 if !Self::is_tsql_frame_incompatible_window_function(&wf.this) {
1088 return;
1089 }
1090
1091 wf.over.frame = None;
1092
1093 let Some(window_name) = wf.over.window_name.clone() else {
1094 return;
1095 };
1096 let Some(named_spec) =
1097 Self::resolve_named_window_spec(&window_name.name, window_map, &mut Vec::new())
1098 else {
1099 return;
1100 };
1101
1102 if named_spec.frame.is_none() {
1103 return;
1104 }
1105
1106 if wf.over.partition_by.is_empty() {
1107 wf.over.partition_by = named_spec.partition_by;
1108 }
1109 if wf.over.order_by.is_empty() {
1110 wf.over.order_by = named_spec.order_by;
1111 }
1112 wf.over.window_name = None;
1113 wf.over.frame = None;
1114 }
1115 Expression::Alias(alias) => {
1116 Self::normalize_frame_incompatible_window_expr(&mut alias.this, window_map);
1117 }
1118 Expression::Paren(paren) => {
1119 Self::normalize_frame_incompatible_window_expr(&mut paren.this, window_map);
1120 }
1121 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
1122 Self::normalize_frame_incompatible_window_expr(&mut cast.this, window_map);
1123 }
1124 Expression::Function(function) => {
1125 for arg in &mut function.args {
1126 Self::normalize_frame_incompatible_window_expr(arg, window_map);
1127 }
1128 }
1129 Expression::Case(case) => {
1130 if let Some(operand) = &mut case.operand {
1131 Self::normalize_frame_incompatible_window_expr(operand, window_map);
1132 }
1133 for (condition, result) in &mut case.whens {
1134 Self::normalize_frame_incompatible_window_expr(condition, window_map);
1135 Self::normalize_frame_incompatible_window_expr(result, window_map);
1136 }
1137 if let Some(else_expr) = &mut case.else_ {
1138 Self::normalize_frame_incompatible_window_expr(else_expr, window_map);
1139 }
1140 }
1141 Expression::And(op)
1142 | Expression::Or(op)
1143 | Expression::Add(op)
1144 | Expression::Sub(op)
1145 | Expression::Mul(op)
1146 | Expression::Div(op)
1147 | Expression::Mod(op)
1148 | Expression::Eq(op)
1149 | Expression::Neq(op)
1150 | Expression::Lt(op)
1151 | Expression::Lte(op)
1152 | Expression::Gt(op)
1153 | Expression::Gte(op)
1154 | Expression::Match(op)
1155 | Expression::BitwiseAnd(op)
1156 | Expression::BitwiseOr(op)
1157 | Expression::BitwiseXor(op)
1158 | Expression::Concat(op)
1159 | Expression::Adjacent(op)
1160 | Expression::TsMatch(op)
1161 | Expression::PropertyEQ(op)
1162 | Expression::ArrayContainsAll(op)
1163 | Expression::ArrayContainedBy(op)
1164 | Expression::ArrayOverlaps(op)
1165 | Expression::JSONBContainsAllTopKeys(op)
1166 | Expression::JSONBContainsAnyTopKeys(op)
1167 | Expression::JSONBDeleteAtPath(op)
1168 | Expression::ExtendsLeft(op)
1169 | Expression::ExtendsRight(op)
1170 | Expression::Is(op)
1171 | Expression::MemberOf(op) => {
1172 Self::normalize_frame_incompatible_window_expr(&mut op.left, window_map);
1173 Self::normalize_frame_incompatible_window_expr(&mut op.right, window_map);
1174 }
1175 Expression::Like(op) | Expression::ILike(op) => {
1176 Self::normalize_frame_incompatible_window_expr(&mut op.left, window_map);
1177 Self::normalize_frame_incompatible_window_expr(&mut op.right, window_map);
1178 if let Some(escape) = &mut op.escape {
1179 Self::normalize_frame_incompatible_window_expr(escape, window_map);
1180 }
1181 }
1182 Expression::Not(op) | Expression::Neg(op) | Expression::BitwiseNot(op) => {
1183 Self::normalize_frame_incompatible_window_expr(&mut op.this, window_map);
1184 }
1185 Expression::In(in_expr) => {
1186 Self::normalize_frame_incompatible_window_expr(&mut in_expr.this, window_map);
1187 for value in &mut in_expr.expressions {
1188 Self::normalize_frame_incompatible_window_expr(value, window_map);
1189 }
1190 }
1191 Expression::Between(between) => {
1192 Self::normalize_frame_incompatible_window_expr(&mut between.this, window_map);
1193 Self::normalize_frame_incompatible_window_expr(&mut between.low, window_map);
1194 Self::normalize_frame_incompatible_window_expr(&mut between.high, window_map);
1195 }
1196 Expression::IsNull(is_null) => {
1197 Self::normalize_frame_incompatible_window_expr(&mut is_null.this, window_map);
1198 }
1199 Expression::IsTrue(is_true) | Expression::IsFalse(is_true) => {
1200 Self::normalize_frame_incompatible_window_expr(&mut is_true.this, window_map);
1201 }
1202 _ => {}
1203 }
1204 }
1205
1206 fn is_tsql_frame_incompatible_window_function(expr: &Expression) -> bool {
1207 matches!(
1208 expr,
1209 Expression::RowNumber(_)
1210 | Expression::Rank(_)
1211 | Expression::DenseRank(_)
1212 | Expression::NTile(_)
1213 | Expression::Ntile(_)
1214 | Expression::Lead(_)
1215 | Expression::Lag(_)
1216 | Expression::PercentRank(_)
1217 | Expression::CumeDist(_)
1218 )
1219 }
1220
1221 fn resolve_named_window_spec(
1222 name: &str,
1223 window_map: &HashMap<String, Over>,
1224 seen: &mut Vec<String>,
1225 ) -> Option<Over> {
1226 let key = name.to_lowercase();
1227 if seen.iter().any(|seen_name| seen_name == &key) {
1228 return None;
1229 }
1230
1231 let named_spec = window_map.get(&key)?.clone();
1232 seen.push(key);
1233
1234 let mut resolved = if let Some(base_window) = &named_spec.window_name {
1235 Self::resolve_named_window_spec(&base_window.name, window_map, seen)
1236 .unwrap_or_else(Self::empty_over)
1237 } else {
1238 Self::empty_over()
1239 };
1240
1241 if !named_spec.partition_by.is_empty() {
1242 resolved.partition_by = named_spec.partition_by;
1243 }
1244 if !named_spec.order_by.is_empty() {
1245 resolved.order_by = named_spec.order_by;
1246 }
1247 if named_spec.frame.is_some() {
1248 resolved.frame = named_spec.frame;
1249 }
1250
1251 Some(resolved)
1252 }
1253
1254 fn empty_over() -> Over {
1255 Over {
1256 window_name: None,
1257 partition_by: Vec::new(),
1258 order_by: Vec::new(),
1259 frame: None,
1260 alias: None,
1261 }
1262 }
1263
1264 const LATERAL_WRAPPER_SOURCE_ALIAS: &'static str = "_polyglot_lateral_source";
1265 const LATERAL_WRAPPER_OUTPUT_ALIAS: &'static str = "_polyglot_lateral";
1266
1267 fn transform_lateral_join_to_apply(mut join: Join) -> Result<Join> {
1268 let Some(apply_kind) = Self::lateral_apply_kind(&join) else {
1269 return Ok(join);
1270 };
1271
1272 let original_alias = Self::table_expression_alias(&join.this);
1273 let on = join.on.take();
1274 let rhs = Self::remove_lateral_marker(join.this);
1275 join.this = if on
1276 .as_ref()
1277 .is_some_and(|expr| !Self::is_true_condition(expr))
1278 {
1279 Self::wrap_lateral_apply_rhs(rhs, on.expect("checked as Some"), original_alias)?
1280 } else {
1281 rhs
1282 };
1283 join.using.clear();
1284 join.kind = apply_kind;
1285 join.use_inner_keyword = false;
1286 join.use_outer_keyword = false;
1287 join.deferred_condition = false;
1288 join.join_hint = None;
1289 join.match_condition = None;
1290 join.directed = false;
1291 Ok(join)
1292 }
1293
1294 fn rewrite_comma_lateral_sources_to_joins(select: &mut Select) {
1295 let Some(from) = select.from.as_mut() else {
1296 return;
1297 };
1298 let has_comma_lateral = from
1299 .expressions
1300 .iter()
1301 .skip(1)
1302 .any(Self::is_lateral_table_expression);
1303 let has_apply_join = select
1304 .joins
1305 .iter()
1306 .any(|join| matches!(join.kind, JoinKind::CrossApply | JoinKind::OuterApply));
1307
1308 if from.expressions.len() < 2 || (!has_comma_lateral && !has_apply_join) {
1309 return;
1310 }
1311
1312 let mut expressions = std::mem::take(&mut from.expressions).into_iter();
1313 let Some(first) = expressions.next() else {
1314 return;
1315 };
1316 from.expressions = vec![first];
1317
1318 let mut joins = expressions
1319 .map(|source| {
1320 if Self::is_lateral_table_expression(&source) {
1321 Self::new_join(Self::remove_lateral_marker(source), JoinKind::CrossApply)
1322 } else {
1323 Self::new_join(source, JoinKind::Cross)
1324 }
1325 })
1326 .collect::<Vec<_>>();
1327 joins.append(&mut select.joins);
1328 select.joins = joins;
1329 }
1330
1331 fn new_join(this: Expression, kind: JoinKind) -> Join {
1332 Join {
1333 this,
1334 on: None,
1335 using: Vec::new(),
1336 kind,
1337 use_inner_keyword: false,
1338 use_outer_keyword: false,
1339 deferred_condition: false,
1340 join_hint: None,
1341 match_condition: None,
1342 pivots: Vec::new(),
1343 comments: Vec::new(),
1344 nesting_group: 0,
1345 directed: false,
1346 }
1347 }
1348
1349 fn lateral_apply_kind(join: &Join) -> Option<JoinKind> {
1350 if !join.using.is_empty() {
1351 return None;
1352 }
1353
1354 match join.kind {
1355 JoinKind::Lateral => Some(JoinKind::CrossApply),
1356 JoinKind::LeftLateral => Some(JoinKind::OuterApply),
1357 JoinKind::Cross | JoinKind::Inner | JoinKind::Implicit
1358 if Self::is_lateral_table_expression(&join.this) =>
1359 {
1360 Some(JoinKind::CrossApply)
1361 }
1362 JoinKind::Left if Self::is_lateral_table_expression(&join.this) => {
1363 Some(JoinKind::OuterApply)
1364 }
1365 _ => None,
1366 }
1367 }
1368
1369 fn is_true_condition(expr: &Expression) -> bool {
1370 match expr {
1371 Expression::Boolean(boolean) => boolean.value,
1372 Expression::Literal(lit) => {
1373 matches!(lit.as_ref(), Literal::Number(value) if value.trim() == "1")
1374 }
1375 Expression::Eq(op) => {
1376 Self::is_true_condition(&op.left) && Self::is_true_condition(&op.right)
1377 }
1378 Expression::Paren(paren) => Self::is_true_condition(&paren.this),
1379 _ => false,
1380 }
1381 }
1382
1383 fn table_expression_alias(expr: &Expression) -> Option<(Identifier, Vec<Identifier>)> {
1384 match expr {
1385 Expression::Subquery(subquery) => subquery
1386 .alias
1387 .clone()
1388 .map(|alias| (alias, subquery.column_aliases.clone())),
1389 Expression::Alias(alias) if !alias.alias.is_empty() => {
1390 Some((alias.alias.clone(), alias.column_aliases.clone()))
1391 }
1392 Expression::Lateral(lateral) => lateral.alias.as_ref().map(|alias| {
1393 (
1394 if lateral.alias_quoted {
1395 Identifier::quoted(alias)
1396 } else {
1397 Identifier::new(alias)
1398 },
1399 lateral
1400 .column_aliases
1401 .iter()
1402 .map(|column| Identifier::new(column.clone()))
1403 .collect(),
1404 )
1405 }),
1406 _ => None,
1407 }
1408 }
1409
1410 fn wrap_lateral_apply_rhs(
1411 rhs: Expression,
1412 predicate: Expression,
1413 original_alias: Option<(Identifier, Vec<Identifier>)>,
1414 ) -> Result<Expression> {
1415 let (outer_alias, column_aliases) = original_alias.unwrap_or_else(|| {
1416 (
1417 Identifier::new(Self::LATERAL_WRAPPER_OUTPUT_ALIAS),
1418 Vec::new(),
1419 )
1420 });
1421 let inner_alias = Identifier::new(Self::LATERAL_WRAPPER_SOURCE_ALIAS);
1422 let source =
1423 Self::with_table_expression_alias(rhs, inner_alias.clone(), column_aliases.clone());
1424 let predicate = Self::rewrite_column_qualifier(predicate, &outer_alias, &inner_alias)?;
1425
1426 let mut select = Select::new();
1427 select.expressions = vec![Expression::Star(Star {
1428 table: None,
1429 except: None,
1430 replace: None,
1431 rename: None,
1432 trailing_comments: Vec::new(),
1433 span: None,
1434 })];
1435 select.from = Some(crate::expressions::From {
1436 expressions: vec![source],
1437 });
1438 select.where_clause = Some(Where { this: predicate });
1439
1440 Ok(Expression::Subquery(Box::new(Subquery {
1441 this: Expression::Select(Box::new(select)),
1442 alias: Some(outer_alias),
1443 column_aliases,
1444 alias_explicit_as: true,
1445 alias_keyword: None,
1446 order_by: None,
1447 limit: None,
1448 offset: None,
1449 distribute_by: None,
1450 sort_by: None,
1451 cluster_by: None,
1452 lateral: false,
1453 modifiers_inside: false,
1454 trailing_comments: Vec::new(),
1455 inferred_type: None,
1456 })))
1457 }
1458
1459 fn with_table_expression_alias(
1460 expr: Expression,
1461 alias: Identifier,
1462 column_aliases: Vec<Identifier>,
1463 ) -> Expression {
1464 match expr {
1465 Expression::Subquery(mut subquery) => {
1466 subquery.alias = Some(alias);
1467 subquery.column_aliases = column_aliases;
1468 subquery.alias_explicit_as = true;
1469 subquery.alias_keyword = None;
1470 Expression::Subquery(subquery)
1471 }
1472 Expression::Alias(mut aliased) => {
1473 aliased.alias = alias;
1474 aliased.column_aliases = column_aliases;
1475 aliased.alias_explicit_as = true;
1476 aliased.alias_keyword = None;
1477 Expression::Alias(aliased)
1478 }
1479 Expression::Table(mut table) => {
1480 table.alias = Some(alias);
1481 table.alias_explicit_as = true;
1482 table.column_aliases = column_aliases;
1483 Expression::Table(table)
1484 }
1485 other => Expression::Alias(Box::new(Alias {
1486 this: other,
1487 alias,
1488 column_aliases,
1489 alias_explicit_as: true,
1490 alias_keyword: None,
1491 pre_alias_comments: Vec::new(),
1492 trailing_comments: Vec::new(),
1493 inferred_type: None,
1494 })),
1495 }
1496 }
1497
1498 fn rewrite_column_qualifier(
1499 expr: Expression,
1500 from: &Identifier,
1501 to: &Identifier,
1502 ) -> Result<Expression> {
1503 super::transform_recursive(expr, &|expr| {
1504 Ok(match expr {
1505 Expression::Column(mut column)
1506 if column
1507 .table
1508 .as_ref()
1509 .is_some_and(|table| Self::same_identifier(table, from)) =>
1510 {
1511 column.table = Some(to.clone());
1512 Expression::Column(column)
1513 }
1514 other => other,
1515 })
1516 })
1517 }
1518
1519 fn same_identifier(left: &Identifier, right: &Identifier) -> bool {
1520 if left.quoted || right.quoted {
1521 left.quoted == right.quoted && left.name == right.name
1522 } else {
1523 left.name.eq_ignore_ascii_case(&right.name)
1524 }
1525 }
1526
1527 fn is_lateral_table_expression(expr: &Expression) -> bool {
1528 match expr {
1529 Expression::Subquery(subquery) => subquery.lateral,
1530 Expression::Lateral(_) => true,
1531 Expression::Alias(alias) => Self::is_lateral_table_expression(&alias.this),
1532 _ => false,
1533 }
1534 }
1535
1536 fn remove_lateral_marker(expr: Expression) -> Expression {
1537 match expr {
1538 Expression::Subquery(mut subquery) => {
1539 subquery.lateral = false;
1540 Expression::Subquery(subquery)
1541 }
1542 Expression::Lateral(lateral) => Self::lateral_to_table_expression(*lateral),
1543 Expression::Alias(mut alias) => {
1544 alias.this = Self::remove_lateral_marker(alias.this);
1545 Expression::Alias(alias)
1546 }
1547 other => other,
1548 }
1549 }
1550
1551 fn lateral_to_table_expression(lateral: crate::expressions::Lateral) -> Expression {
1552 let expr = *lateral.this;
1553 let Some(alias) = lateral.alias else {
1554 return expr;
1555 };
1556
1557 Expression::Alias(Box::new(Alias {
1558 this: expr,
1559 alias: if lateral.alias_quoted {
1560 Identifier::quoted(alias)
1561 } else {
1562 Identifier::new(alias)
1563 },
1564 column_aliases: lateral
1565 .column_aliases
1566 .into_iter()
1567 .map(Identifier::new)
1568 .collect(),
1569 alias_explicit_as: true,
1570 alias_keyword: None,
1571 pre_alias_comments: Vec::new(),
1572 trailing_comments: Vec::new(),
1573 inferred_type: None,
1574 }))
1575 }
1576
1577 fn rewrite_tuple_in_subquery_predicates(
1578 expr: Expression,
1579 outer_qualifier: Option<&Identifier>,
1580 under_not: bool,
1581 ) -> Expression {
1582 match expr {
1583 Expression::In(in_expr) if !under_not => {
1584 let in_expr = *in_expr;
1585 Self::tuple_in_subquery_to_exists(&in_expr, outer_qualifier, in_expr.not)
1586 .unwrap_or_else(|| Expression::In(Box::new(in_expr)))
1587 }
1588 Expression::Eq(op) if !under_not => {
1589 let op = *op;
1590 Self::tuple_subquery_eq_to_exists(&op, outer_qualifier)
1591 .unwrap_or_else(|| Expression::Eq(Box::new(op)))
1592 }
1593 Expression::And(mut op) => {
1594 op.left =
1595 Self::rewrite_tuple_in_subquery_predicates(op.left, outer_qualifier, under_not);
1596 op.right = Self::rewrite_tuple_in_subquery_predicates(
1597 op.right,
1598 outer_qualifier,
1599 under_not,
1600 );
1601 Expression::And(op)
1602 }
1603 Expression::Or(mut op) => {
1604 op.left =
1605 Self::rewrite_tuple_in_subquery_predicates(op.left, outer_qualifier, under_not);
1606 op.right = Self::rewrite_tuple_in_subquery_predicates(
1607 op.right,
1608 outer_qualifier,
1609 under_not,
1610 );
1611 Expression::Or(op)
1612 }
1613 Expression::Paren(mut paren) => {
1614 paren.this = Self::rewrite_tuple_in_subquery_predicates(
1615 paren.this,
1616 outer_qualifier,
1617 under_not,
1618 );
1619 Expression::Paren(paren)
1620 }
1621 Expression::Not(mut not) => {
1622 if let Some(rewritten) = Self::direct_tuple_subquery_predicate_to_exists(
1623 ¬.this,
1624 outer_qualifier,
1625 true,
1626 ) {
1627 rewritten
1628 } else {
1629 not.this =
1630 Self::rewrite_tuple_in_subquery_predicates(not.this, outer_qualifier, true);
1631 Expression::Not(not)
1632 }
1633 }
1634 Expression::Alias(mut alias) => {
1635 alias.this = Self::rewrite_tuple_in_subquery_predicates(
1636 alias.this,
1637 outer_qualifier,
1638 under_not,
1639 );
1640 Expression::Alias(alias)
1641 }
1642 Expression::Cast(mut cast) => {
1643 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1644 cast.this,
1645 outer_qualifier,
1646 under_not,
1647 );
1648 if let Some(format) = cast.format.take() {
1649 cast.format = Some(Box::new(Self::rewrite_tuple_in_subquery_predicates(
1650 *format,
1651 outer_qualifier,
1652 under_not,
1653 )));
1654 }
1655 if let Some(default) = cast.default.take() {
1656 cast.default = Some(Box::new(Self::rewrite_tuple_in_subquery_predicates(
1657 *default,
1658 outer_qualifier,
1659 under_not,
1660 )));
1661 }
1662 Expression::Cast(cast)
1663 }
1664 Expression::TryCast(mut cast) => {
1665 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1666 cast.this,
1667 outer_qualifier,
1668 under_not,
1669 );
1670 Expression::TryCast(cast)
1671 }
1672 Expression::SafeCast(mut cast) => {
1673 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1674 cast.this,
1675 outer_qualifier,
1676 under_not,
1677 );
1678 Expression::SafeCast(cast)
1679 }
1680 Expression::Case(mut case) => {
1681 if let Some(operand) = case.operand.take() {
1682 case.operand = Some(Self::rewrite_tuple_in_subquery_predicates(
1683 operand,
1684 outer_qualifier,
1685 under_not,
1686 ));
1687 }
1688 case.whens = case
1689 .whens
1690 .into_iter()
1691 .map(|(condition, result)| {
1692 (
1693 Self::rewrite_tuple_in_subquery_predicates(
1694 condition,
1695 outer_qualifier,
1696 false,
1697 ),
1698 Self::rewrite_tuple_in_subquery_predicates(
1699 result,
1700 outer_qualifier,
1701 under_not,
1702 ),
1703 )
1704 })
1705 .collect();
1706 if let Some(else_) = case.else_.take() {
1707 case.else_ = Some(Self::rewrite_tuple_in_subquery_predicates(
1708 else_,
1709 outer_qualifier,
1710 under_not,
1711 ));
1712 }
1713 Expression::Case(case)
1714 }
1715 Expression::IfFunc(mut if_func) => {
1716 if_func.condition = Self::rewrite_tuple_in_subquery_predicates(
1717 if_func.condition,
1718 outer_qualifier,
1719 false,
1720 );
1721 if_func.true_value = Self::rewrite_tuple_in_subquery_predicates(
1722 if_func.true_value,
1723 outer_qualifier,
1724 under_not,
1725 );
1726 if let Some(false_value) = if_func.false_value.take() {
1727 if_func.false_value = Some(Self::rewrite_tuple_in_subquery_predicates(
1728 false_value,
1729 outer_qualifier,
1730 under_not,
1731 ));
1732 }
1733 Expression::IfFunc(if_func)
1734 }
1735 other => other,
1736 }
1737 }
1738
1739 fn direct_tuple_subquery_predicate_to_exists(
1740 expr: &Expression,
1741 outer_qualifier: Option<&Identifier>,
1742 negated: bool,
1743 ) -> Option<Expression> {
1744 match expr {
1745 Expression::In(in_expr) => {
1746 Self::tuple_in_subquery_to_exists(in_expr, outer_qualifier, negated ^ in_expr.not)
1747 }
1748 Expression::Paren(paren) => Self::direct_tuple_subquery_predicate_to_exists(
1749 &paren.this,
1750 outer_qualifier,
1751 negated,
1752 ),
1753 _ => None,
1754 }
1755 }
1756
1757 fn tuple_in_subquery_to_exists(
1758 in_expr: &In,
1759 outer_qualifier: Option<&Identifier>,
1760 negated: bool,
1761 ) -> Option<Expression> {
1762 if in_expr.unnest.is_some() {
1763 return None;
1764 }
1765
1766 let left_expressions = Self::tuple_expressions(&in_expr.this)?;
1767 let mut select = Self::select_from_in_rhs(in_expr)?;
1768
1769 if left_expressions.len() != select.expressions.len() || left_expressions.is_empty() {
1770 return None;
1771 }
1772
1773 let inner_qualifier = Self::single_select_source_qualifier(&select);
1774 let mut predicates = Vec::with_capacity(left_expressions.len() + 1);
1775 for (projection, left) in select
1776 .expressions
1777 .iter()
1778 .cloned()
1779 .zip(left_expressions.iter().cloned())
1780 {
1781 let inner = Self::tuple_in_projection_expr(projection, inner_qualifier.as_ref())?;
1782 let outer = Self::qualify_tuple_operand(left, outer_qualifier);
1783 predicates.push(if negated {
1784 Self::tuple_component_may_match(inner, outer)
1785 } else {
1786 Expression::Eq(Box::new(BinaryOp::new(inner, outer)))
1787 });
1788 }
1789
1790 if let Some(where_clause) = select.where_clause.take() {
1791 predicates.push(where_clause.this);
1792 }
1793
1794 select.expressions = vec![Expression::number(1)];
1795 select.where_clause = Some(Where {
1796 this: Self::and_all(predicates)?,
1797 });
1798
1799 Some(Expression::Exists(Box::new(Exists {
1800 this: Expression::Select(Box::new(select)),
1801 not: negated,
1802 })))
1803 }
1804
1805 fn tuple_subquery_eq_to_exists(
1806 op: &BinaryOp,
1807 outer_qualifier: Option<&Identifier>,
1808 ) -> Option<Expression> {
1809 if let Some((tuple_expr, query_expr)) = Self::tuple_and_query_operands(&op.left, &op.right)
1810 {
1811 return Self::tuple_subquery_eq_to_exists_inner(
1812 tuple_expr,
1813 query_expr,
1814 outer_qualifier,
1815 );
1816 }
1817
1818 if let Some((tuple_expr, query_expr)) = Self::tuple_and_query_operands(&op.right, &op.left)
1819 {
1820 return Self::tuple_subquery_eq_to_exists_inner(
1821 tuple_expr,
1822 query_expr,
1823 outer_qualifier,
1824 );
1825 }
1826
1827 None
1828 }
1829
1830 fn tuple_subquery_eq_to_exists_inner(
1831 tuple_expr: &Expression,
1832 query_expr: &Expression,
1833 outer_qualifier: Option<&Identifier>,
1834 ) -> Option<Expression> {
1835 let tuple_expressions = Self::tuple_expressions(tuple_expr)?;
1836 let mut select = Self::select_from_query_expression(query_expr)?;
1837
1838 if tuple_expressions.len() != select.expressions.len() || tuple_expressions.is_empty() {
1839 return None;
1840 }
1841
1842 let inner_qualifier = Self::single_select_source_qualifier(&select);
1843 let mut predicates = Vec::with_capacity(tuple_expressions.len() + 1);
1844 for (projection, tuple_operand) in select
1845 .expressions
1846 .iter()
1847 .cloned()
1848 .zip(tuple_expressions.iter().cloned())
1849 {
1850 let inner = Self::tuple_in_projection_expr(projection, inner_qualifier.as_ref())?;
1851 let outer = Self::qualify_tuple_operand(tuple_operand, outer_qualifier);
1852 predicates.push(Expression::Eq(Box::new(BinaryOp::new(inner, outer))));
1853 }
1854
1855 if let Some(where_clause) = select.where_clause.take() {
1856 predicates.push(where_clause.this);
1857 }
1858
1859 select.expressions = vec![Expression::number(1)];
1860 select.where_clause = Some(Where {
1861 this: Self::and_all(predicates)?,
1862 });
1863
1864 Some(Expression::Exists(Box::new(Exists {
1865 this: Expression::Select(Box::new(select)),
1866 not: false,
1867 })))
1868 }
1869
1870 fn tuple_and_query_operands<'a>(
1871 tuple_candidate: &'a Expression,
1872 query_candidate: &'a Expression,
1873 ) -> Option<(&'a Expression, &'a Expression)> {
1874 if Self::tuple_expressions(tuple_candidate).is_some()
1875 && Self::select_from_query_expression(query_candidate).is_some()
1876 {
1877 Some((tuple_candidate, query_candidate))
1878 } else {
1879 None
1880 }
1881 }
1882
1883 fn select_from_query_expression(expr: &Expression) -> Option<Select> {
1884 match expr {
1885 Expression::Select(select) => Some((**select).clone()),
1886 Expression::Subquery(subquery) => Self::select_from_query_expression(&subquery.this),
1887 Expression::Paren(paren) => Self::select_from_query_expression(&paren.this),
1888 _ => None,
1889 }
1890 }
1891
1892 fn select_from_in_rhs(in_expr: &In) -> Option<Select> {
1893 if let Some(values) = Self::values_from_in_rhs(in_expr) {
1894 return Self::select_from_values(&values);
1895 }
1896
1897 if let Some(query) = &in_expr.query {
1898 return if in_expr.expressions.is_empty() {
1899 Self::select_from_query_expression(query)
1900 } else {
1901 None
1902 };
1903 }
1904
1905 if in_expr.expressions.len() == 1 {
1906 Self::select_from_query_expression(&in_expr.expressions[0])
1907 } else {
1908 None
1909 }
1910 }
1911
1912 fn values_from_in_rhs(in_expr: &In) -> Option<Values> {
1913 if let Some(query) = &in_expr.query {
1914 return if in_expr.expressions.is_empty() {
1915 Self::values_from_expression(query)
1916 } else {
1917 None
1918 };
1919 }
1920
1921 if in_expr.expressions.len() == 1 {
1922 if let Some(values) = Self::values_from_expression(&in_expr.expressions[0]) {
1923 return Some(values);
1924 }
1925 }
1926
1927 let Expression::Function(first_row) = in_expr.expressions.first()? else {
1929 return None;
1930 };
1931 if !first_row.name.eq_ignore_ascii_case("VALUES") {
1932 return None;
1933 }
1934
1935 let mut rows = Vec::with_capacity(in_expr.expressions.len());
1936 rows.push(Tuple {
1937 expressions: first_row.args.clone(),
1938 });
1939 for row in &in_expr.expressions[1..] {
1940 rows.push(Self::tuple_from_values_row(row)?);
1941 }
1942
1943 Some(Values {
1944 expressions: rows,
1945 alias: None,
1946 column_aliases: Vec::new(),
1947 })
1948 }
1949
1950 fn values_from_expression(expr: &Expression) -> Option<Values> {
1951 match expr {
1952 Expression::Values(values) => Some((**values).clone()),
1953 Expression::Paren(paren) => Self::values_from_expression(&paren.this),
1954 Expression::Subquery(subquery) => Self::values_from_expression(&subquery.this),
1955 _ => None,
1956 }
1957 }
1958
1959 fn tuple_from_values_row(expr: &Expression) -> Option<Tuple> {
1960 match expr {
1961 Expression::Tuple(tuple) => Some((**tuple).clone()),
1962 Expression::Paren(paren) => match &paren.this {
1963 Expression::Tuple(tuple) => Some((**tuple).clone()),
1964 other => Some(Tuple {
1965 expressions: vec![other.clone()],
1966 }),
1967 },
1968 _ => None,
1969 }
1970 }
1971
1972 fn select_from_values(values: &Values) -> Option<Select> {
1973 let column_count = values.expressions.first()?.expressions.len();
1974 if column_count == 0
1975 || values
1976 .expressions
1977 .iter()
1978 .any(|row| row.expressions.len() != column_count)
1979 {
1980 return None;
1981 }
1982
1983 let source_alias = Identifier::new("_polyglot_values");
1984 let column_aliases = (1..=column_count)
1985 .map(|index| Identifier::new(format!("_polyglot_value_{index}")))
1986 .collect::<Vec<_>>();
1987 let projections = column_aliases
1988 .iter()
1989 .cloned()
1990 .map(|column| Self::column_from_identifier(column, Some(source_alias.clone())))
1991 .collect();
1992
1993 let mut source_values = values.clone();
1994 source_values.alias = None;
1995 source_values.column_aliases.clear();
1996
1997 let source = Expression::Subquery(Box::new(Subquery {
1998 this: Expression::Values(Box::new(source_values)),
1999 alias: Some(source_alias),
2000 column_aliases,
2001 alias_explicit_as: true,
2002 alias_keyword: None,
2003 order_by: None,
2004 limit: None,
2005 offset: None,
2006 distribute_by: None,
2007 sort_by: None,
2008 cluster_by: None,
2009 lateral: false,
2010 modifiers_inside: false,
2011 trailing_comments: Vec::new(),
2012 inferred_type: None,
2013 }));
2014
2015 let mut select = Select::new();
2016 select.expressions = projections;
2017 select.from = Some(From {
2018 expressions: vec![source],
2019 });
2020 Some(select)
2021 }
2022
2023 fn tuple_expressions(expr: &Expression) -> Option<&[Expression]> {
2024 match expr {
2025 Expression::Tuple(tuple) => Some(&tuple.expressions),
2026 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
2027 Some(&function.args)
2028 }
2029 Expression::Paren(paren) => Self::tuple_expressions(&paren.this),
2030 _ => None,
2031 }
2032 }
2033
2034 fn tuple_in_projection_expr(
2035 expr: Expression,
2036 qualifier: Option<&Identifier>,
2037 ) -> Option<Expression> {
2038 match expr {
2039 Expression::Alias(alias) => Self::tuple_in_projection_expr(alias.this, qualifier),
2040 Expression::Column(mut column) => {
2041 if column.table.is_none() {
2042 column.table = qualifier.cloned();
2043 }
2044 Some(Expression::Column(column))
2045 }
2046 Expression::Identifier(identifier) => {
2047 Some(Self::column_from_identifier(identifier, qualifier.cloned()))
2048 }
2049 Expression::Dot(_) => Some(expr),
2050 other => Some(Self::qualify_tuple_expression(other, qualifier)),
2051 }
2052 }
2053
2054 fn qualify_tuple_operand(expr: Expression, qualifier: Option<&Identifier>) -> Expression {
2055 Self::qualify_tuple_expression(expr, qualifier)
2056 }
2057
2058 fn qualify_tuple_expression(expr: Expression, qualifier: Option<&Identifier>) -> Expression {
2059 match expr {
2060 Expression::Column(mut column) => {
2061 if column.table.is_none() {
2062 column.table = qualifier.cloned();
2063 }
2064 Expression::Column(column)
2065 }
2066 Expression::Identifier(identifier) => {
2067 Self::column_from_identifier(identifier, qualifier.cloned())
2068 }
2069 Expression::Alias(mut alias) => {
2070 alias.this = Self::qualify_tuple_expression(alias.this, qualifier);
2071 Expression::Alias(alias)
2072 }
2073 Expression::Paren(mut paren) => {
2074 paren.this = Self::qualify_tuple_expression(paren.this, qualifier);
2075 Expression::Paren(paren)
2076 }
2077 Expression::Cast(mut cast) => {
2078 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
2079 if let Some(format) = cast.format.take() {
2080 cast.format =
2081 Some(Box::new(Self::qualify_tuple_expression(*format, qualifier)));
2082 }
2083 if let Some(default) = cast.default.take() {
2084 cast.default = Some(Box::new(Self::qualify_tuple_expression(
2085 *default, qualifier,
2086 )));
2087 }
2088 Expression::Cast(cast)
2089 }
2090 Expression::TryCast(mut cast) => {
2091 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
2092 Expression::TryCast(cast)
2093 }
2094 Expression::SafeCast(mut cast) => {
2095 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
2096 Expression::SafeCast(cast)
2097 }
2098 Expression::Function(mut function) => {
2099 function.args = function
2100 .args
2101 .into_iter()
2102 .map(|arg| Self::qualify_tuple_expression(arg, qualifier))
2103 .collect();
2104 Expression::Function(function)
2105 }
2106 Expression::Add(mut op) => {
2107 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2108 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2109 Expression::Add(op)
2110 }
2111 Expression::Sub(mut op) => {
2112 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2113 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2114 Expression::Sub(op)
2115 }
2116 Expression::Mul(mut op) => {
2117 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2118 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2119 Expression::Mul(op)
2120 }
2121 Expression::Div(mut op) => {
2122 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2123 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2124 Expression::Div(op)
2125 }
2126 Expression::Mod(mut op) => {
2127 op.left = Self::qualify_tuple_expression(op.left, qualifier);
2128 op.right = Self::qualify_tuple_expression(op.right, qualifier);
2129 Expression::Mod(op)
2130 }
2131 other => other,
2132 }
2133 }
2134
2135 fn tuple_component_may_match(inner: Expression, outer: Expression) -> Expression {
2136 Self::paren(
2137 Self::or_all(vec![
2138 Expression::Eq(Box::new(BinaryOp::new(inner.clone(), outer.clone()))),
2139 Self::is_null(inner),
2140 Self::is_null(outer),
2141 ])
2142 .expect("tuple component match condition is non-empty"),
2143 )
2144 }
2145
2146 fn column_from_identifier(identifier: Identifier, table: Option<Identifier>) -> Expression {
2147 Expression::Column(Box::new(Column {
2148 name: identifier,
2149 table,
2150 join_mark: false,
2151 trailing_comments: Vec::new(),
2152 span: None,
2153 inferred_type: None,
2154 }))
2155 }
2156
2157 fn single_select_source_qualifier(select: &Select) -> Option<Identifier> {
2158 if !select.joins.is_empty() {
2159 return None;
2160 }
2161
2162 let from = select.from.as_ref()?;
2163 if from.expressions.len() != 1 {
2164 return None;
2165 }
2166
2167 Self::source_qualifier(&from.expressions[0])
2168 }
2169
2170 fn source_qualifier(source: &Expression) -> Option<Identifier> {
2171 match source {
2172 Expression::Table(table) => table.alias.clone().or_else(|| Some(table.name.clone())),
2173 Expression::Subquery(subquery) => subquery.alias.clone(),
2174 _ => None,
2175 }
2176 }
2177
2178 fn and_all(mut predicates: Vec<Expression>) -> Option<Expression> {
2179 if predicates.is_empty() {
2180 return None;
2181 }
2182
2183 let first = predicates.remove(0);
2184 Some(predicates.into_iter().fold(first, |left, right| {
2185 Expression::And(Box::new(BinaryOp::new(left, right)))
2186 }))
2187 }
2188
2189 fn or_all(mut predicates: Vec<Expression>) -> Option<Expression> {
2190 if predicates.is_empty() {
2191 return None;
2192 }
2193
2194 let first = predicates.remove(0);
2195 Some(predicates.into_iter().fold(first, |left, right| {
2196 Expression::Or(Box::new(BinaryOp::new(left, right)))
2197 }))
2198 }
2199
2200 pub(super) fn transform_data_type(
2202 &self,
2203 dt: crate::expressions::DataType,
2204 ) -> Result<Expression> {
2205 use crate::expressions::DataType;
2206 let transformed = match dt {
2207 DataType::Boolean => DataType::Custom {
2209 name: "BIT".to_string(),
2210 },
2211 DataType::Int { .. } => dt,
2213 DataType::Decimal { precision, scale } => DataType::Custom {
2216 name: if let (Some(p), Some(s)) = (&precision, &scale) {
2217 format!("NUMERIC({}, {})", p, s)
2218 } else if let Some(p) = &precision {
2219 format!("NUMERIC({})", p)
2220 } else {
2221 "NUMERIC".to_string()
2222 },
2223 },
2224 DataType::Text => DataType::Custom {
2226 name: "VARCHAR(MAX)".to_string(),
2227 },
2228 DataType::Timestamp { .. } => DataType::Custom {
2230 name: "DATETIME2".to_string(),
2231 },
2232 DataType::Uuid => DataType::Custom {
2234 name: "UNIQUEIDENTIFIER".to_string(),
2235 },
2236 DataType::Custom { ref name } => {
2238 let upper = name.trim().to_uppercase();
2239 let (base_name, precision, _scale) = Self::parse_type_precision_and_scale(&upper);
2240 match base_name.as_str() {
2241 "DOUBLE PRECISION" => DataType::Custom {
2243 name: "FLOAT".to_string(),
2244 },
2245 "BPCHAR" => {
2247 if let Some(len) = precision {
2248 DataType::Char { length: Some(len) }
2249 } else {
2250 DataType::Char { length: None }
2251 }
2252 }
2253 _ => dt,
2254 }
2255 }
2256 other => other,
2258 };
2259 Ok(Expression::DataType(transformed))
2260 }
2261
2262 pub(super) fn parse_type_precision_and_scale(name: &str) -> (String, Option<u32>, Option<u32>) {
2264 if let Some(paren_pos) = name.find('(') {
2265 let base = name[..paren_pos].to_string();
2266 let rest = &name[paren_pos + 1..];
2267 if let Some(close_pos) = rest.find(')') {
2268 let args = &rest[..close_pos];
2269 let parts: Vec<&str> = args.split(',').map(|s| s.trim()).collect();
2270 let precision = parts.first().and_then(|s| s.parse::<u32>().ok());
2271 let scale = parts.get(1).and_then(|s| s.parse::<u32>().ok());
2272 return (base, precision, scale);
2273 }
2274 (base, None, None)
2275 } else {
2276 (name.to_string(), None, None)
2277 }
2278 }
2279
2280 fn transform_logical_aggregate(
2281 condition: Expression,
2282 filter: Option<Expression>,
2283 aggregate_name: &str,
2284 ) -> Result<Expression> {
2285 let false_condition = Expression::Not(Box::new(crate::expressions::UnaryOp {
2286 this: condition.clone(),
2287 inferred_type: None,
2288 }));
2289 let true_condition = Self::apply_aggregate_filter(condition, filter.clone());
2290 let false_condition = Self::apply_aggregate_filter(false_condition, filter);
2291
2292 let case_expr = Expression::Case(Box::new(crate::expressions::Case {
2293 operand: None,
2294 whens: vec![
2295 (true_condition, Expression::number(1)),
2296 (false_condition, Expression::number(0)),
2297 ],
2298 else_: Some(Expression::null()),
2299 comments: Vec::new(),
2300 inferred_type: None,
2301 }));
2302
2303 let case_expr = crate::transforms::ensure_bools(case_expr)?;
2304 let aggregate = Expression::Function(Box::new(Function::new(
2305 aggregate_name.to_string(),
2306 vec![case_expr],
2307 )));
2308
2309 Ok(Expression::Cast(Box::new(Cast {
2310 this: aggregate,
2311 to: DataType::Custom {
2312 name: "BIT".to_string(),
2313 },
2314 trailing_comments: Vec::new(),
2315 double_colon_syntax: false,
2316 format: None,
2317 default: None,
2318 inferred_type: None,
2319 })))
2320 }
2321
2322 fn reassociate_logical_aggregate_window(mut window: WindowFunction) -> Expression {
2323 let Expression::Cast(mut cast) = window.this else {
2324 return Expression::WindowFunction(Box::new(window));
2325 };
2326
2327 if !Self::is_transformed_logical_aggregate_cast(&cast) {
2328 window.this = Expression::Cast(cast);
2329 return Expression::WindowFunction(Box::new(window));
2330 }
2331
2332 window.this = cast.this;
2333 cast.this = Expression::WindowFunction(Box::new(window));
2334 Expression::Cast(cast)
2335 }
2336
2337 fn is_transformed_logical_aggregate_cast(cast: &Cast) -> bool {
2338 if !matches!(
2339 &cast.to,
2340 DataType::Custom { name } if name.eq_ignore_ascii_case("BIT")
2341 ) {
2342 return false;
2343 }
2344
2345 let Expression::Function(function) = &cast.this else {
2346 return false;
2347 };
2348 if !matches!(function.name.to_ascii_uppercase().as_str(), "MIN" | "MAX")
2349 || function.args.len() != 1
2350 {
2351 return false;
2352 }
2353
2354 matches!(
2355 function.args.first(),
2356 Some(Expression::Case(case))
2357 if case.operand.is_none()
2358 && case.whens.len() == 2
2359 && matches!(case.else_.as_ref(), Some(Expression::Null(_)))
2360 )
2361 }
2362
2363 fn apply_aggregate_filter(condition: Expression, filter: Option<Expression>) -> Expression {
2364 match filter {
2365 Some(filter) => Expression::And(Box::new(crate::expressions::BinaryOp::new(
2366 filter, condition,
2367 ))),
2368 None => condition,
2369 }
2370 }
2371
2372 fn transform_function(&self, f: Function) -> Result<Expression> {
2373 let name_upper = f.name.to_uppercase();
2374 match name_upper.as_str() {
2375 "COALESCE" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2377 "ISNULL".to_string(),
2378 f.args,
2379 )))),
2380
2381 "NVL" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2383 "ISNULL".to_string(),
2384 f.args,
2385 )))),
2386
2387 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
2389 Function::new("STRING_AGG".to_string(), f.args),
2390 ))),
2391
2392 "STRING_AGG" => Ok(Expression::Function(Box::new(f))),
2394
2395 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
2397 "STRING_AGG".to_string(),
2398 f.args,
2399 )))),
2400
2401 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
2403 "SUBSTRING".to_string(),
2404 f.args,
2405 )))),
2406
2407 "LENGTH" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2409 "LEN".to_string(),
2410 f.args,
2411 )))),
2412
2413 "BTRIM" if f.args.len() == 1 || f.args.len() == 2 => {
2415 let mut args = f.args;
2416 let this = args.remove(0);
2417 let characters = if args.is_empty() {
2418 None
2419 } else {
2420 Some(args.remove(0))
2421 };
2422 Ok(Expression::Trim(Box::new(TrimFunc {
2423 this,
2424 sql_standard_syntax: characters.is_some(),
2425 characters,
2426 position: TrimPosition::Both,
2427 position_explicit: false,
2428 })))
2429 }
2430
2431 "MD5" if f.args.len() == 1 => {
2433 let mut args = f.args;
2434 Ok(Self::tsql_md5_hex(args.remove(0)))
2435 }
2436
2437 "OCTET_LENGTH" if f.args.len() == 1 => Ok(Self::function("DATALENGTH", f.args)),
2439
2440 "BIT_LENGTH" if f.args.len() == 1 => {
2442 let mut args = f.args;
2443 Ok(Expression::Mul(Box::new(BinaryOp::new(
2444 Self::function("DATALENGTH", vec![args.remove(0)]),
2445 Expression::number(8),
2446 ))))
2447 }
2448
2449 "TO_HEX" if f.args.len() == 1 => {
2453 let mut args = f.args;
2454 Ok(Self::tsql_hex_from_varbinary(args.remove(0)))
2455 }
2456
2457 "ENCODE" if f.args.len() == 2 => {
2459 let mut args = f.args;
2460 let this = args.remove(0);
2461 let encoding = args.remove(0);
2462 if Self::literal_string(&encoding)
2463 .is_some_and(|encoding| encoding.eq_ignore_ascii_case("hex"))
2464 {
2465 Ok(Self::tsql_hex_from_varbinary(this))
2466 } else {
2467 Ok(Expression::Function(Box::new(Function::new(
2468 "ENCODE".to_string(),
2469 vec![this, encoding],
2470 ))))
2471 }
2472 }
2473
2474 "REPEAT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2476 "REPLICATE".to_string(),
2477 f.args,
2478 )))),
2479
2480 "CHR" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2482 "CHAR".to_string(),
2483 f.args,
2484 )))),
2485
2486 "RANDOM" => Ok(Expression::Rand(Box::new(crate::expressions::Rand {
2488 seed: None,
2489 lower: None,
2490 upper: None,
2491 }))),
2492
2493 "NOW" => Ok(Self::getdate()),
2495
2496 "CURRENT_TIMESTAMP" => Ok(Self::getdate()),
2498
2499 "CURRENT_DATE" => Ok(Self::cast_getdate_to(DataType::Date)),
2501
2502 "CURRENT_TIME" => Ok(Self::cast_getdate_to(DataType::Time {
2504 precision: None,
2505 timezone: false,
2506 })),
2507
2508 "LOCALTIMESTAMP" => Ok(Self::getdate()),
2510
2511 "CLOCK_TIMESTAMP" if f.args.is_empty() => Ok(Self::function("SYSDATETIME", vec![])),
2513
2514 "MAKE_DATE" if f.args.len() == 3 => Ok(Self::function("DATEFROMPARTS", f.args)),
2516
2517 "TO_DATE" if f.args.len() == 2 => {
2521 Self::formatted_str_to_date_or_fallback(f.args, "TO_DATE")
2522 }
2523
2524 "TO_DATE" if f.args.len() == 1 => {
2526 let mut args = f.args;
2527 Ok(Expression::Cast(Box::new(Cast {
2528 this: args.remove(0),
2529 to: DataType::Date,
2530 trailing_comments: Vec::new(),
2531 double_colon_syntax: false,
2532 format: None,
2533 default: None,
2534 inferred_type: None,
2535 })))
2536 }
2537
2538 "TO_TIMESTAMP" if f.args.len() == 2 => {
2541 Self::formatted_str_to_time_or_fallback(f.args, "TO_TIMESTAMP")
2542 }
2543
2544 "TO_TIMESTAMP" if f.args.len() == 1 => {
2546 let mut args = f.args;
2547 Ok(Expression::UnixToTime(Box::new(
2548 crate::expressions::UnixToTime {
2549 this: Box::new(args.remove(0)),
2550 scale: Some(0),
2551 zone: None,
2552 hours: None,
2553 minutes: None,
2554 format: None,
2555 target_type: None,
2556 },
2557 )))
2558 }
2559
2560 "TO_CHAR" if f.args.len() == 2 => {
2563 Self::formatted_time_to_str_or_fallback(f.args, "TO_CHAR")
2564 }
2565
2566 "TO_CHAR" => Ok(Expression::Function(Box::new(Function::new(
2568 "FORMAT".to_string(),
2569 f.args,
2570 )))),
2571
2572 "DATE_FORMAT" => Ok(Expression::Function(Box::new(Function::new(
2574 "FORMAT".to_string(),
2575 f.args,
2576 )))),
2577
2578 "DATE_TRUNC" | "DATETRUNC" => {
2581 let mut args = Self::uppercase_first_arg_if_identifier(f.args);
2582 if args.len() >= 2 {
2584 if let Expression::Literal(lit) = &args[1] {
2585 if let Literal::String(_) = lit.as_ref() {
2586 args[1] = Expression::Cast(Box::new(Cast {
2587 this: args[1].clone(),
2588 to: DataType::Custom {
2589 name: "DATETIME2".to_string(),
2590 },
2591 trailing_comments: Vec::new(),
2592 double_colon_syntax: false,
2593 format: None,
2594 default: None,
2595 inferred_type: None,
2596 }));
2597 }
2598 }
2599 }
2600 Ok(Expression::Function(Box::new(Function::new(
2601 "DATETRUNC".to_string(),
2602 args,
2603 ))))
2604 }
2605
2606 "DATEADD" => {
2608 let args = Self::uppercase_first_arg_if_identifier(f.args);
2609 Ok(Expression::Function(Box::new(Function::new(
2610 "DATEADD".to_string(),
2611 args,
2612 ))))
2613 }
2614
2615 "DATEDIFF" => {
2617 let args = Self::uppercase_first_arg_if_identifier(f.args);
2618 Ok(Expression::Function(Box::new(Function::new(
2619 "DATEDIFF".to_string(),
2620 args,
2621 ))))
2622 }
2623
2624 "EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2626 "DATEPART".to_string(),
2627 f.args,
2628 )))),
2629
2630 "STRPOS" | "POSITION" if f.args.len() >= 2 => {
2632 Ok(Expression::Function(Box::new(Function::new(
2634 "CHARINDEX".to_string(),
2635 f.args,
2636 ))))
2637 }
2638
2639 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
2641
2642 "CEILING" | "CEIL" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
2644 Function::new("CEILING".to_string(), f.args),
2645 ))),
2646
2647 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2652 "JSON_VALUE".to_string(),
2653 f.args,
2654 )))),
2655
2656 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
2658 "JSON_VALUE".to_string(),
2659 f.args,
2660 )))),
2661
2662 "PARSE_JSON" if f.args.len() == 1 => Ok(f.args.into_iter().next().unwrap()),
2664
2665 "GET_PATH" if f.args.len() == 2 => {
2667 let mut args = f.args;
2668 let this = args.remove(0);
2669 let path = args.remove(0);
2670 let json_path = match &path {
2671 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
2672 let Literal::String(s) = lit.as_ref() else {
2673 unreachable!()
2674 };
2675 let normalized = if s.starts_with('$') {
2676 s.clone()
2677 } else if s.starts_with('[') {
2678 format!("${}", s)
2679 } else {
2680 format!("$.{}", s)
2681 };
2682 Expression::Literal(Box::new(Literal::String(normalized)))
2683 }
2684 _ => path,
2685 };
2686 let json_query = Expression::Function(Box::new(Function::new(
2688 "JSON_QUERY".to_string(),
2689 vec![this.clone(), json_path.clone()],
2690 )));
2691 let json_value = Expression::Function(Box::new(Function::new(
2692 "JSON_VALUE".to_string(),
2693 vec![this, json_path],
2694 )));
2695 Ok(Expression::Function(Box::new(Function::new(
2696 "ISNULL".to_string(),
2697 vec![json_query, json_value],
2698 ))))
2699 }
2700
2701 "JSON_QUERY" if f.args.len() == 1 => {
2704 let this = f.args.into_iter().next().unwrap();
2705 let path = Expression::Literal(Box::new(Literal::String("$".to_string())));
2706 let json_query = Expression::Function(Box::new(Function::new(
2707 "JSON_QUERY".to_string(),
2708 vec![this.clone(), path.clone()],
2709 )));
2710 let json_value = Expression::Function(Box::new(Function::new(
2711 "JSON_VALUE".to_string(),
2712 vec![this, path],
2713 )));
2714 Ok(Expression::Function(Box::new(Function::new(
2715 "ISNULL".to_string(),
2716 vec![json_query, json_value],
2717 ))))
2718 }
2719
2720 "SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2722 "STRING_SPLIT".to_string(),
2723 f.args,
2724 )))),
2725
2726 "REGEXP_LIKE" => {
2729 Ok(Expression::Function(Box::new(Function::new(
2731 "PATINDEX".to_string(),
2732 f.args,
2733 ))))
2734 }
2735
2736 "LN" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2738 "LOG".to_string(),
2739 f.args,
2740 )))),
2741
2742 "STDDEV" | "STDDEV_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2747 "STDEV".to_string(),
2748 f.args,
2749 )))),
2750
2751 "STDDEV_POP" => Ok(Expression::Function(Box::new(Function::new(
2753 "STDEVP".to_string(),
2754 f.args,
2755 )))),
2756
2757 "VARIANCE" | "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2759 "VAR".to_string(),
2760 f.args,
2761 )))),
2762
2763 "VAR_POP" => Ok(Expression::Function(Box::new(Function::new(
2765 "VARP".to_string(),
2766 f.args,
2767 )))),
2768
2769 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" | "EVERY" if f.args.len() == 1 => {
2771 let mut args = f.args;
2772 Self::transform_logical_aggregate(args.remove(0), None, "MIN")
2773 }
2774 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if f.args.len() == 1 => {
2775 let mut args = f.args;
2776 Self::transform_logical_aggregate(args.remove(0), None, "MAX")
2777 }
2778
2779 "DATE_ADD" => {
2781 if f.args.len() == 2 {
2782 let mut args = f.args;
2783 let date = args.remove(0);
2784 let interval = args.remove(0);
2785 let unit = Expression::Identifier(crate::expressions::Identifier {
2786 name: "DAY".to_string(),
2787 quoted: false,
2788 trailing_comments: Vec::new(),
2789 span: None,
2790 });
2791 Ok(Expression::Function(Box::new(Function::new(
2792 "DATEADD".to_string(),
2793 vec![unit, interval, date],
2794 ))))
2795 } else {
2796 let args = Self::uppercase_first_arg_if_identifier(f.args);
2797 Ok(Expression::Function(Box::new(Function::new(
2798 "DATEADD".to_string(),
2799 args,
2800 ))))
2801 }
2802 }
2803
2804 "INSERT" => Ok(Expression::Function(Box::new(Function::new(
2806 "STUFF".to_string(),
2807 f.args,
2808 )))),
2809
2810 "SUSER_NAME" | "SUSER_SNAME" | "SYSTEM_USER" => Ok(Expression::CurrentUser(Box::new(
2812 crate::expressions::CurrentUser { this: None },
2813 ))),
2814
2815 _ => Ok(Expression::Function(Box::new(f))),
2817 }
2818 }
2819
2820 fn literal_string(expr: &Expression) -> Option<&str> {
2821 match expr {
2822 Expression::Literal(lit) => match lit.as_ref() {
2823 Literal::String(s) => Some(s),
2824 _ => None,
2825 },
2826 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast)
2827 if Self::is_text_data_type(&cast.to) =>
2828 {
2829 Self::literal_string(&cast.this)
2830 }
2831 _ => None,
2832 }
2833 }
2834
2835 fn is_text_data_type(data_type: &DataType) -> bool {
2836 match data_type {
2837 DataType::Char { .. }
2838 | DataType::VarChar { .. }
2839 | DataType::String { .. }
2840 | DataType::Text
2841 | DataType::TextWithLength { .. } => true,
2842 DataType::Custom { name } => {
2843 let base = name
2844 .split_once('(')
2845 .map_or(name.as_str(), |(base, _)| base)
2846 .trim();
2847 matches!(
2848 base.to_ascii_uppercase().as_str(),
2849 "CHAR"
2850 | "NCHAR"
2851 | "VARCHAR"
2852 | "NVARCHAR"
2853 | "TEXT"
2854 | "NTEXT"
2855 | "STRING"
2856 | "CHARACTER VARYING"
2857 )
2858 }
2859 _ => false,
2860 }
2861 }
2862
2863 fn is_numeric_data_type(data_type: &DataType) -> bool {
2864 match data_type {
2865 DataType::TinyInt { .. }
2866 | DataType::SmallInt { .. }
2867 | DataType::Int { .. }
2868 | DataType::BigInt { .. }
2869 | DataType::Float { .. }
2870 | DataType::Double { .. }
2871 | DataType::Decimal { .. } => true,
2872 DataType::Custom { name } => {
2873 let base = name
2874 .split_once('(')
2875 .map_or(name.as_str(), |(base, _)| base)
2876 .trim();
2877 matches!(
2878 base.to_ascii_uppercase().as_str(),
2879 "TINYINT"
2880 | "SMALLINT"
2881 | "INT"
2882 | "INTEGER"
2883 | "BIGINT"
2884 | "DECIMAL"
2885 | "NUMERIC"
2886 | "REAL"
2887 | "FLOAT"
2888 | "MONEY"
2889 | "SMALLMONEY"
2890 )
2891 }
2892 _ => false,
2893 }
2894 }
2895
2896 fn is_explicitly_numeric_expression(expr: &Expression) -> bool {
2897 if expr.inferred_type().is_some_and(Self::is_numeric_data_type) {
2898 return true;
2899 }
2900
2901 match expr {
2902 Expression::Literal(literal) => matches!(literal.as_ref(), Literal::Number(_)),
2903 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
2904 Self::is_numeric_data_type(&cast.to)
2905 }
2906 Expression::Alias(alias) => Self::is_explicitly_numeric_expression(&alias.this),
2907 Expression::Paren(paren) => Self::is_explicitly_numeric_expression(&paren.this),
2908 Expression::Neg(unary) => Self::is_explicitly_numeric_expression(&unary.this),
2909 _ => false,
2910 }
2911 }
2912
2913 fn is_postgres_numeric_to_char_format(format: &str) -> bool {
2914 let mut unquoted = String::with_capacity(format.len());
2915 let mut quoted = false;
2916 let mut chars = format.chars().peekable();
2917
2918 while let Some(ch) = chars.next() {
2919 if ch == '"' {
2920 if quoted && chars.peek() == Some(&'"') {
2921 chars.next();
2922 } else {
2923 quoted = !quoted;
2924 }
2925 } else if !quoted {
2926 unquoted.extend(ch.to_uppercase());
2927 }
2928 }
2929
2930 unquoted.contains(['9', '0'])
2931 || ["PR", "SG", "PL", "RN", "EEEE"]
2932 .iter()
2933 .any(|token| unquoted.contains(token))
2934 }
2935
2936 fn postgres_format_to_strftime(format: &str) -> String {
2937 const POSTGRES_FORMAT_TO_STRFTIME: &[(&str, &str)] = &[
2938 ("FMHH24", "%-H"),
2939 ("FMHH12", "%-I"),
2940 ("FMDDD", "%-j"),
2941 ("TMMonth", "%B"),
2942 ("TMMon", "%b"),
2943 ("TMDay", "%A"),
2944 ("TMDy", "%a"),
2945 ("YYYY", "%Y"),
2946 ("yyyy", "%Y"),
2947 ("HH24", "%H"),
2948 ("HH12", "%I"),
2949 ("FMDD", "%-d"),
2950 ("FMMM", "%-m"),
2951 ("FMMI", "%-M"),
2952 ("FMSS", "%-S"),
2953 ("DDD", "%j"),
2954 ("ddd", "%j"),
2955 ("YY", "%y"),
2956 ("yy", "%y"),
2957 ("MM", "%m"),
2958 ("mm", "%m"),
2959 ("DD", "%d"),
2960 ("dd", "%d"),
2961 ("MI", "%M"),
2962 ("mi", "%M"),
2963 ("SS", "%S"),
2964 ("ss", "%S"),
2965 ("US", "%f"),
2966 ("OF", "%z"),
2967 ("TZ", "%Z"),
2968 ("WW", "%U"),
2969 ("ww", "%U"),
2970 ("D", "%u"),
2971 ("d", "%u"),
2972 ];
2973 crate::format_tokens::convert_format_tokens(format, POSTGRES_FORMAT_TO_STRFTIME)
2974 .unwrap_or_else(|| format.to_string())
2975 }
2976
2977 fn formatted_str_to_time_or_fallback(
2978 mut args: Vec<Expression>,
2979 original_name: &str,
2980 ) -> Result<Expression> {
2981 let this = args.remove(0);
2982 let format = args.remove(0);
2983 if let Some(format) = Self::literal_string(&format) {
2984 Ok(Expression::StrToTime(Box::new(
2985 crate::expressions::StrToTime {
2986 this: Box::new(this),
2987 format: Self::postgres_format_to_strftime(format),
2988 zone: None,
2989 safe: None,
2990 target_type: Some(Box::new(Expression::DataType(DataType::Custom {
2991 name: "DATETIME2".to_string(),
2992 }))),
2993 },
2994 )))
2995 } else {
2996 Ok(Expression::Function(Box::new(Function::new(
2997 original_name.to_string(),
2998 vec![this, format],
2999 ))))
3000 }
3001 }
3002
3003 fn formatted_str_to_date_or_fallback(
3004 mut args: Vec<Expression>,
3005 original_name: &str,
3006 ) -> Result<Expression> {
3007 let this = args.remove(0);
3008 let format = args.remove(0);
3009 if let Some(format) = Self::literal_string(&format) {
3010 Ok(Expression::StrToDate(Box::new(
3011 crate::expressions::StrToDate {
3012 this: Box::new(this),
3013 format: Some(Self::postgres_format_to_strftime(format)),
3014 safe: None,
3015 },
3016 )))
3017 } else {
3018 Ok(Expression::Function(Box::new(Function::new(
3019 original_name.to_string(),
3020 vec![this, format],
3021 ))))
3022 }
3023 }
3024
3025 fn formatted_time_to_str_or_fallback(
3026 mut args: Vec<Expression>,
3027 original_name: &str,
3028 ) -> Result<Expression> {
3029 let this = args.remove(0);
3030 let format = args.remove(0);
3031 if let Some(format_string) = Self::literal_string(&format).map(str::to_owned) {
3032 if Self::is_explicitly_numeric_expression(&this)
3033 || Self::is_postgres_numeric_to_char_format(&format_string)
3034 {
3035 return Ok(Expression::Function(Box::new(Function::new(
3036 original_name.to_string(),
3037 vec![this, format],
3038 ))));
3039 }
3040
3041 Ok(Expression::TimeToStr(Box::new(
3042 crate::expressions::TimeToStr {
3043 this: Box::new(this),
3044 format: Self::postgres_format_to_strftime(&format_string),
3045 culture: None,
3046 zone: None,
3047 },
3048 )))
3049 } else {
3050 Ok(Expression::Function(Box::new(Function::new(
3051 original_name.to_string(),
3052 vec![this, format],
3053 ))))
3054 }
3055 }
3056
3057 fn transform_aggregate_function(
3058 &self,
3059 mut f: Box<crate::expressions::AggregateFunction>,
3060 ) -> Result<Expression> {
3061 let name_upper = f.name.to_uppercase();
3062 if matches!(
3063 name_upper.as_str(),
3064 "SUM"
3065 | "AVG"
3066 | "MIN"
3067 | "MAX"
3068 | "COUNT"
3069 | "COUNT_BIG"
3070 | "ANY_VALUE"
3071 | "APPROX_COUNT_DISTINCT"
3072 | "STDEV"
3073 | "STDEVP"
3074 | "VAR"
3075 | "VARP"
3076 | "BOOL_AND"
3077 | "BOOL_OR"
3078 | "LOGICAL_AND"
3079 | "LOGICAL_OR"
3080 | "BIT_AND"
3081 | "BIT_OR"
3082 | "BIT_XOR"
3083 ) {
3084 f.order_by.clear();
3085 }
3086
3087 match name_upper.as_str() {
3088 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
3090 Function::new("STRING_AGG".to_string(), f.args),
3091 ))),
3092
3093 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
3095 "STRING_AGG".to_string(),
3096 f.args,
3097 )))),
3098
3099 "ARRAY_AGG" if !f.args.is_empty() => {
3102 Ok(Expression::Function(Box::new(Function::new(
3104 "STRING_AGG".to_string(),
3105 f.args,
3106 ))))
3107 }
3108
3109 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" | "EVERY" if f.args.len() == 1 => {
3111 let mut args = f.args;
3112 Self::transform_logical_aggregate(args.remove(0), f.filter, "MIN")
3113 }
3114 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if f.args.len() == 1 => {
3115 let mut args = f.args;
3116 Self::transform_logical_aggregate(args.remove(0), f.filter, "MAX")
3117 }
3118
3119 _ => Ok(Expression::AggregateFunction(f)),
3121 }
3122 }
3123
3124 fn without_inert_ordering(
3125 mut aggregate: Box<crate::expressions::AggFunc>,
3126 ) -> Box<crate::expressions::AggFunc> {
3127 aggregate.order_by.clear();
3128 aggregate
3129 }
3130
3131 fn transform_cte(&self, cte: Cte) -> Result<Expression> {
3135 Ok(Expression::Cte(Box::new(self.transform_cte_inner(cte))))
3136 }
3137
3138 fn transform_cte_inner(&self, mut cte: Cte) -> Cte {
3140 if cte.columns.is_empty() {
3143 cte.this = self.qualify_derived_table_outputs(cte.this);
3144 }
3145 cte
3146 }
3147
3148 fn transform_subquery(&self, mut subquery: Subquery) -> Result<Expression> {
3152 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
3155 subquery.this = self.qualify_derived_table_outputs(subquery.this);
3156 }
3157 Ok(Expression::Subquery(Box::new(subquery)))
3158 }
3159
3160 fn qualify_derived_table_outputs(&self, expr: Expression) -> Expression {
3164 match expr {
3165 Expression::Select(mut select) => {
3166 let has_from = select.from.is_some();
3169 if !has_from {
3170 select.expressions = select
3171 .expressions
3172 .into_iter()
3173 .map(|e| self.maybe_alias_expression(e))
3174 .collect();
3175 }
3176 Expression::Select(select)
3177 }
3178 Expression::Union(mut u) => {
3180 let left = std::mem::replace(&mut u.left, Expression::Null(Null));
3181 u.left = self.qualify_derived_table_outputs(left);
3182 Expression::Union(u)
3183 }
3184 Expression::Intersect(mut i) => {
3185 let left = std::mem::replace(&mut i.left, Expression::Null(Null));
3186 i.left = self.qualify_derived_table_outputs(left);
3187 Expression::Intersect(i)
3188 }
3189 Expression::Except(mut e) => {
3190 let left = std::mem::replace(&mut e.left, Expression::Null(Null));
3191 e.left = self.qualify_derived_table_outputs(left);
3192 Expression::Except(e)
3193 }
3194 Expression::Subquery(mut s) => {
3196 s.this = self.qualify_derived_table_outputs(s.this);
3197 Expression::Subquery(s)
3198 }
3199 other => other,
3201 }
3202 }
3203
3204 fn maybe_alias_expression(&self, expr: Expression) -> Expression {
3209 match &expr {
3210 Expression::Alias(_) => expr,
3212 Expression::Aliases(_) => expr,
3214 Expression::Star(_) => expr,
3216 _ => {
3221 if let Some(output_name) = self.get_output_name(&expr) {
3222 Expression::Alias(Box::new(Alias {
3223 this: expr,
3224 alias: Identifier {
3225 name: output_name,
3226 quoted: true, trailing_comments: Vec::new(),
3228 span: None,
3229 },
3230 column_aliases: Vec::new(),
3231 alias_explicit_as: false,
3232 alias_keyword: None,
3233 pre_alias_comments: Vec::new(),
3234 trailing_comments: Vec::new(),
3235 inferred_type: None,
3236 }))
3237 } else {
3238 expr
3240 }
3241 }
3242 }
3243 }
3244
3245 fn get_output_name(&self, expr: &Expression) -> Option<String> {
3249 match expr {
3250 Expression::Literal(lit) => match lit.as_ref() {
3252 Literal::Number(n) => Some(n.clone()),
3253 Literal::String(s) => Some(s.clone()),
3254 Literal::HexString(h) => Some(format!("0x{}", h)),
3255 Literal::HexNumber(h) => Some(format!("0x{}", h)),
3256 Literal::BitString(b) => Some(format!("b{}", b)),
3257 Literal::ByteString(b) => Some(format!("b'{}'", b)),
3258 Literal::NationalString(s) => Some(format!("N'{}'", s)),
3259 Literal::Date(d) => Some(d.clone()),
3260 Literal::Time(t) => Some(t.clone()),
3261 Literal::Timestamp(ts) => Some(ts.clone()),
3262 Literal::Datetime(dt) => Some(dt.clone()),
3263 Literal::TripleQuotedString(s, _) => Some(s.clone()),
3264 Literal::EscapeString(s) => Some(s.clone()),
3265 Literal::DollarString(s) => Some(s.clone()),
3266 Literal::RawString(s) => Some(s.clone()),
3267 },
3268 Expression::Column(col) => Some(col.name.name.clone()),
3270 Expression::Identifier(ident) => Some(ident.name.clone()),
3272 Expression::Boolean(b) => Some(if b.value { "1" } else { "0" }.to_string()),
3274 Expression::Null(_) => Some("NULL".to_string()),
3276 Expression::Function(f) => Some(f.name.clone()),
3278 Expression::AggregateFunction(f) => Some(f.name.clone()),
3280 _ => Some(format!("_col_{}", 0)),
3282 }
3283 }
3284
3285 fn uppercase_first_arg_if_identifier(mut args: Vec<Expression>) -> Vec<Expression> {
3287 use crate::expressions::Identifier;
3288 if !args.is_empty() {
3289 match &args[0] {
3290 Expression::Identifier(id) => {
3291 args[0] = Expression::Identifier(Identifier {
3292 name: id.name.to_uppercase(),
3293 quoted: id.quoted,
3294 trailing_comments: id.trailing_comments.clone(),
3295 span: None,
3296 });
3297 }
3298 Expression::Var(v) => {
3299 args[0] = Expression::Identifier(Identifier {
3300 name: v.this.to_uppercase(),
3301 quoted: false,
3302 trailing_comments: Vec::new(),
3303 span: None,
3304 });
3305 }
3306 Expression::Column(col) if col.table.is_none() => {
3307 args[0] = Expression::Identifier(Identifier {
3308 name: col.name.name.to_uppercase(),
3309 quoted: col.name.quoted,
3310 trailing_comments: col.name.trailing_comments.clone(),
3311 span: None,
3312 });
3313 }
3314 _ => {}
3315 }
3316 }
3317 args
3318 }
3319}
3320
3321#[cfg(test)]
3322mod tests {
3323 use super::*;
3324 use crate::dialects::Dialect;
3325
3326 fn transpile_to_tsql(sql: &str) -> String {
3327 let dialect = Dialect::get(DialectType::Generic);
3328 let result = dialect
3329 .transpile(sql, DialectType::TSQL)
3330 .expect("Transpile failed");
3331 result[0].clone()
3332 }
3333
3334 #[test]
3335 fn test_nvl_to_isnull() {
3336 let result = transpile_to_tsql("SELECT NVL(a, b)");
3337 assert!(
3338 result.contains("ISNULL"),
3339 "Expected ISNULL, got: {}",
3340 result
3341 );
3342 }
3343
3344 #[test]
3345 fn test_coalesce_to_isnull() {
3346 let result = transpile_to_tsql("SELECT COALESCE(a, b)");
3347 assert!(
3348 result.contains("ISNULL"),
3349 "Expected ISNULL, got: {}",
3350 result
3351 );
3352 }
3353
3354 #[test]
3355 fn test_basic_select() {
3356 let result = transpile_to_tsql("SELECT a, b FROM users WHERE id = 1");
3357 assert!(result.contains("SELECT"));
3358 assert!(result.contains("FROM users"));
3359 }
3360
3361 #[test]
3362 fn test_length_to_len() {
3363 let result = transpile_to_tsql("SELECT LENGTH(name)");
3364 assert!(result.contains("LEN"), "Expected LEN, got: {}", result);
3365 }
3366
3367 #[test]
3368 fn test_now_to_getdate() {
3369 let result = transpile_to_tsql("SELECT NOW()");
3370 assert!(
3371 result.contains("GETDATE"),
3372 "Expected GETDATE, got: {}",
3373 result
3374 );
3375 }
3376
3377 #[test]
3378 fn test_group_concat_to_string_agg() {
3379 let result = transpile_to_tsql("SELECT GROUP_CONCAT(name)");
3380 assert!(
3381 result.contains("STRING_AGG"),
3382 "Expected STRING_AGG, got: {}",
3383 result
3384 );
3385 }
3386
3387 #[test]
3388 fn test_listagg_to_string_agg() {
3389 let result = transpile_to_tsql("SELECT LISTAGG(name)");
3390 assert!(
3391 result.contains("STRING_AGG"),
3392 "Expected STRING_AGG, got: {}",
3393 result
3394 );
3395 }
3396
3397 #[test]
3398 fn test_ln_to_log() {
3399 let result = transpile_to_tsql("SELECT LN(x)");
3400 assert!(result.contains("LOG"), "Expected LOG, got: {}", result);
3401 }
3402
3403 #[test]
3404 fn test_stddev_to_stdev() {
3405 let result = transpile_to_tsql("SELECT STDDEV(x)");
3406 assert!(result.contains("STDEV"), "Expected STDEV, got: {}", result);
3407 }
3408
3409 #[test]
3410 fn test_bracket_identifiers() {
3411 let dialect = Dialect::get(DialectType::TSQL);
3413 let config = dialect.generator_config();
3414 assert_eq!(config.identifier_quote, '[');
3415 }
3416
3417 #[test]
3418 fn test_json_query_isnull_wrapper_simple() {
3419 let dialect = Dialect::get(DialectType::TSQL);
3421 let result = dialect
3422 .transpile(r#"JSON_QUERY(x, '$')"#, DialectType::TSQL)
3423 .expect("transpile failed");
3424 assert!(
3425 result[0].contains("ISNULL"),
3426 "JSON_QUERY should be wrapped with ISNULL: {}",
3427 result[0]
3428 );
3429 }
3430
3431 #[test]
3432 fn test_json_query_isnull_wrapper_nested() {
3433 let dialect = Dialect::get(DialectType::TSQL);
3434 let result = dialect
3435 .transpile(
3436 r#"JSON_QUERY(REPLACE(REPLACE(x, '''', '"'), '""', '"'))"#,
3437 DialectType::TSQL,
3438 )
3439 .expect("transpile failed");
3440 let expected = r#"ISNULL(JSON_QUERY(REPLACE(REPLACE(x, '''', '"'), '""', '"'), '$'), JSON_VALUE(REPLACE(REPLACE(x, '''', '"'), '""', '"'), '$'))"#;
3441 assert_eq!(
3442 result[0], expected,
3443 "JSON_QUERY should be wrapped with ISNULL"
3444 );
3445 }
3446}