1use super::{DialectImpl, DialectType};
14use crate::error::Result;
15use crate::expressions::{
16 Alias, BinaryOp, Cast, Column, Cte, DataType, Exists, Expression, Function, Identifier, In,
17 Join, JoinKind, LikeOp, Literal, Null, Over, Paren, QuantifiedOp, Select, Star, StringAggFunc,
18 Subquery, TrimFunc, TrimPosition, UnaryFunc, Where,
19};
20#[cfg(feature = "generate")]
21use crate::generator::GeneratorConfig;
22use crate::tokens::TokenizerConfig;
23use std::collections::HashMap;
24
25pub struct TSQLDialect;
27
28impl DialectImpl for TSQLDialect {
29 fn dialect_type(&self) -> DialectType {
30 DialectType::TSQL
31 }
32
33 fn tokenizer_config(&self) -> TokenizerConfig {
34 let mut config = TokenizerConfig::default();
35 config.identifiers.insert('[', ']');
37 config.identifiers.insert('"', '"');
39 config.hex_number_strings = true;
41 config
42 }
43
44 #[cfg(feature = "generate")]
45
46 fn generator_config(&self) -> GeneratorConfig {
47 use crate::generator::IdentifierQuoteStyle;
48 GeneratorConfig {
49 identifier_quote: '[',
51 identifier_quote_style: IdentifierQuoteStyle::BRACKET,
52 dialect: Some(DialectType::TSQL),
53 limit_fetch_style: crate::generator::LimitFetchStyle::FetchFirst,
56 null_ordering_supported: false,
58 aggregate_filter_supported: false,
60 supports_select_into: true,
62 alter_table_include_column_keyword: false,
64 computed_column_with_type: false,
66 cte_recursive_keyword_required: false,
68 ensure_bools: true,
70 supports_single_arg_concat: false,
72 tablesample_seed_keyword: "REPEATABLE",
74 json_path_bracketed_key_supported: false,
76 supports_to_number: false,
78 set_op_modifiers: false,
80 copy_params_eq_required: true,
82 except_intersect_support_all_clause: false,
84 alter_set_wrapped: true,
86 try_supported: true,
88 nvl2_supported: false,
90 parameter_default_equals: true,
92 supports_window_exclude: false,
94 multi_arg_distinct: false,
96 locking_reads_supported: false,
98 ..Default::default()
99 }
100 }
101
102 #[cfg(feature = "transpile")]
103
104 fn transform_expr(&self, expr: Expression) -> Result<Expression> {
105 if let Expression::CreateTable(mut ct) = expr {
107 for col in &mut ct.columns {
108 if let Ok(Expression::DataType(new_dt)) =
109 self.transform_data_type(col.data_type.clone())
110 {
111 col.data_type = new_dt;
112 }
113 }
114 return Ok(Expression::CreateTable(ct));
115 }
116
117 match expr {
118 Expression::Select(mut select) => {
123 select.expressions = select
124 .expressions
125 .into_iter()
126 .map(|e| {
127 match e {
128 Expression::Eq(op) => {
129 match &op.left {
132 Expression::Column(col)
133 if col.table.is_none()
134 && !col.name.name.starts_with('@') =>
135 {
136 Expression::Alias(Box::new(Alias {
137 this: op.right,
138 alias: col.name.clone(),
139 column_aliases: Vec::new(),
140 alias_explicit_as: false,
141 alias_keyword: None,
142 pre_alias_comments: Vec::new(),
143 trailing_comments: Vec::new(),
144 inferred_type: None,
145 }))
146 }
147 Expression::Identifier(ident)
148 if !ident.name.starts_with('@') =>
149 {
150 Expression::Alias(Box::new(Alias {
151 this: op.right,
152 alias: ident.clone(),
153 column_aliases: Vec::new(),
154 alias_explicit_as: false,
155 alias_keyword: None,
156 pre_alias_comments: Vec::new(),
157 trailing_comments: Vec::new(),
158 inferred_type: None,
159 }))
160 }
161 _ => Expression::Eq(op),
162 }
163 }
164 other => other,
165 }
166 })
167 .collect();
168
169 Self::normalize_frame_incompatible_window_functions(&mut select);
170
171 let outer_qualifier = Self::single_select_source_qualifier(&select);
172
173 select.expressions = select
174 .expressions
175 .into_iter()
176 .map(|expression| {
177 Self::rewrite_tuple_in_subquery_predicates(
178 expression,
179 outer_qualifier.as_ref(),
180 false,
181 )
182 })
183 .collect();
184
185 for join in &mut select.joins {
186 if let Some(on) = join.on.take() {
187 join.on = Some(Self::rewrite_tuple_in_subquery_predicates(
188 on,
189 outer_qualifier.as_ref(),
190 false,
191 ));
192 }
193 if let Some(match_condition) = join.match_condition.take() {
194 join.match_condition = Some(Self::rewrite_tuple_in_subquery_predicates(
195 match_condition,
196 outer_qualifier.as_ref(),
197 false,
198 ));
199 }
200 }
201
202 if let Some(ref mut prewhere) = select.prewhere {
203 *prewhere = Self::rewrite_tuple_in_subquery_predicates(
204 std::mem::replace(prewhere, Expression::Null(Null)),
205 outer_qualifier.as_ref(),
206 false,
207 );
208 }
209
210 if let Some(ref mut where_clause) = select.where_clause {
211 where_clause.this = Self::rewrite_tuple_in_subquery_predicates(
212 std::mem::replace(&mut where_clause.this, Expression::Null(Null)),
213 outer_qualifier.as_ref(),
214 false,
215 );
216 }
217
218 if let Some(ref mut having) = select.having {
219 having.this = Self::rewrite_tuple_in_subquery_predicates(
220 std::mem::replace(&mut having.this, Expression::Null(Null)),
221 outer_qualifier.as_ref(),
222 false,
223 );
224 }
225
226 if let Some(ref mut qualify) = select.qualify {
227 qualify.this = Self::rewrite_tuple_in_subquery_predicates(
228 std::mem::replace(&mut qualify.this, Expression::Null(Null)),
229 outer_qualifier.as_ref(),
230 false,
231 );
232 }
233
234 if let Some(ref mut with) = select.with {
236 with.ctes = with
237 .ctes
238 .drain(..)
239 .map(|cte| self.transform_cte_inner(cte))
240 .collect();
241 }
242
243 Self::rewrite_comma_lateral_sources_to_joins(&mut select);
244
245 Ok(Expression::Select(select))
246 }
247
248 Expression::DataType(dt) => self.transform_data_type(dt),
250
251 Expression::IsTrue(it) => Ok(Self::boolean_test_predicate(it.this, true, it.not)),
255 Expression::IsFalse(it) => Ok(Self::boolean_test_predicate(it.this, false, it.not)),
256
257 Expression::In(mut in_expr) if in_expr.not => {
261 in_expr.not = false;
262 Ok(Expression::Not(Box::new(crate::expressions::UnaryOp {
263 this: Expression::In(in_expr),
264 inferred_type: None,
265 })))
266 }
267
268 Expression::Coalesce(f) if f.expressions.len() == 2 => Ok(Expression::Function(
271 Box::new(Function::new("ISNULL".to_string(), f.expressions)),
272 )),
273
274 Expression::Nvl(f) => Ok(Expression::Function(Box::new(Function::new(
276 "ISNULL".to_string(),
277 vec![f.this, f.expression],
278 )))),
279
280 Expression::GroupConcat(f) => Ok(Expression::StringAgg(Box::new(StringAggFunc {
282 this: f.this,
283 separator: f.separator,
284 order_by: f.order_by,
285 distinct: f.distinct,
286 filter: f.filter,
287 limit: None,
288 inferred_type: None,
289 }))),
290
291 Expression::ListAgg(f) => Ok(Expression::StringAgg(Box::new(StringAggFunc {
293 this: f.this,
294 separator: f.separator,
295 order_by: f.order_by,
296 distinct: f.distinct,
297 filter: f.filter,
298 limit: None,
299 inferred_type: None,
300 }))),
301
302 Expression::LogicalAnd(f) => Self::transform_logical_aggregate(f.this, f.filter, "MIN"),
305 Expression::LogicalOr(f) => Self::transform_logical_aggregate(f.this, f.filter, "MAX"),
306
307 Expression::TryCast(c) => Ok(Expression::TryCast(c)),
309
310 Expression::SafeCast(c) => Ok(Expression::TryCast(c)),
312
313 Expression::ILike(op) => {
315 let lower_left = Expression::Lower(Box::new(UnaryFunc::new(op.left)));
318 let lower_right = Expression::Lower(Box::new(UnaryFunc::new(op.right)));
319 Ok(Expression::Like(Box::new(LikeOp {
320 left: lower_left,
321 right: lower_right,
322 escape: op.escape,
323 quantifier: op.quantifier,
324 inferred_type: None,
325 })))
326 }
327
328 Expression::Concat(op) => {
331 Ok(Expression::Add(op))
333 }
334
335 Expression::Random(_) => Ok(Expression::Rand(Box::new(crate::expressions::Rand {
337 seed: None,
338 lower: None,
339 upper: None,
340 }))),
341
342 Expression::Unnest(f) => {
344 Ok(Expression::Function(Box::new(Function::new(
347 "OPENJSON".to_string(),
348 vec![f.this],
349 ))))
350 }
351
352 Expression::Explode(f) => Ok(Expression::Function(Box::new(Function::new(
354 "OPENJSON".to_string(),
355 vec![f.this],
356 )))),
357
358 Expression::Join(join) => Ok(Expression::Join(Box::new(
360 Self::transform_lateral_join_to_apply(*join)?,
361 ))),
362
363 Expression::Length(f) => Ok(Expression::Function(Box::new(Function::new(
365 "LEN".to_string(),
366 vec![f.this],
367 )))),
368
369 Expression::Stddev(f) => Ok(Expression::Function(Box::new(Function::new(
371 "STDEV".to_string(),
372 vec![f.this],
373 )))),
374 Expression::StddevSamp(f) => Ok(Expression::Function(Box::new(Function::new(
375 "STDEV".to_string(),
376 vec![f.this],
377 )))),
378 Expression::StddevPop(f) => Ok(Expression::Function(Box::new(Function::new(
379 "STDEVP".to_string(),
380 vec![f.this],
381 )))),
382
383 Expression::Boolean(b) => {
385 let value = if b.value { 1 } else { 0 };
386 Ok(Expression::Literal(Box::new(
387 crate::expressions::Literal::Number(value.to_string()),
388 )))
389 }
390
391 Expression::Ln(f) => Ok(Expression::Function(Box::new(Function::new(
393 "LOG".to_string(),
394 vec![f.this],
395 )))),
396
397 Expression::CurrentDate(_) => Ok(Self::cast_getdate_to(DataType::Date)),
400
401 Expression::CurrentTime(_) => Ok(Self::cast_getdate_to(DataType::Time {
403 precision: None,
404 timezone: false,
405 })),
406
407 Expression::CurrentTimestamp(_) => Ok(Self::getdate()),
409
410 Expression::Localtimestamp(_) => Ok(Self::getdate()),
412
413 Expression::MakeDate(f) => Ok(Self::function(
415 "DATEFROMPARTS",
416 vec![f.year, f.month, f.day],
417 )),
418
419 Expression::DateDiff(f) => {
421 let unit_str = match f.unit {
423 Some(crate::expressions::IntervalUnit::Year) => "YEAR",
424 Some(crate::expressions::IntervalUnit::Quarter) => "QUARTER",
425 Some(crate::expressions::IntervalUnit::Month) => "MONTH",
426 Some(crate::expressions::IntervalUnit::Week) => "WEEK",
427 Some(crate::expressions::IntervalUnit::Day) => "DAY",
428 Some(crate::expressions::IntervalUnit::Hour) => "HOUR",
429 Some(crate::expressions::IntervalUnit::Minute) => "MINUTE",
430 Some(crate::expressions::IntervalUnit::Second) => "SECOND",
431 Some(crate::expressions::IntervalUnit::Millisecond) => "MILLISECOND",
432 Some(crate::expressions::IntervalUnit::Microsecond) => "MICROSECOND",
433 Some(crate::expressions::IntervalUnit::Nanosecond) => "NANOSECOND",
434 None => "DAY",
435 };
436 let unit = Expression::Identifier(crate::expressions::Identifier {
437 name: unit_str.to_string(),
438 quoted: false,
439 trailing_comments: Vec::new(),
440 span: None,
441 });
442 Ok(Expression::Function(Box::new(Function::new(
443 "DATEDIFF".to_string(),
444 vec![unit, f.expression, f.this], ))))
446 }
447
448 Expression::DateAdd(f) => {
450 let unit_str = match f.unit {
451 crate::expressions::IntervalUnit::Year => "YEAR",
452 crate::expressions::IntervalUnit::Quarter => "QUARTER",
453 crate::expressions::IntervalUnit::Month => "MONTH",
454 crate::expressions::IntervalUnit::Week => "WEEK",
455 crate::expressions::IntervalUnit::Day => "DAY",
456 crate::expressions::IntervalUnit::Hour => "HOUR",
457 crate::expressions::IntervalUnit::Minute => "MINUTE",
458 crate::expressions::IntervalUnit::Second => "SECOND",
459 crate::expressions::IntervalUnit::Millisecond => "MILLISECOND",
460 crate::expressions::IntervalUnit::Microsecond => "MICROSECOND",
461 crate::expressions::IntervalUnit::Nanosecond => "NANOSECOND",
462 };
463 let unit = Expression::Identifier(crate::expressions::Identifier {
464 name: unit_str.to_string(),
465 quoted: false,
466 trailing_comments: Vec::new(),
467 span: None,
468 });
469 Ok(Expression::Function(Box::new(Function::new(
470 "DATEADD".to_string(),
471 vec![unit, f.interval, f.this],
472 ))))
473 }
474
475 Expression::Uuid(_) => Ok(Expression::Function(Box::new(Function::new(
478 "NEWID".to_string(),
479 vec![],
480 )))),
481
482 Expression::IfFunc(f) => {
485 let false_val = f
486 .false_value
487 .unwrap_or(Expression::Null(crate::expressions::Null));
488 Ok(Expression::Function(Box::new(Function::new(
489 "IIF".to_string(),
490 vec![f.condition, f.true_value, false_val],
491 ))))
492 }
493
494 Expression::StringAgg(f) => Ok(Expression::StringAgg(f)),
497
498 Expression::LastDay(f) => Ok(Expression::Function(Box::new(Function::new(
500 "EOMONTH".to_string(),
501 vec![f.this.clone()],
502 )))),
503
504 Expression::Ceil(f) => Ok(Expression::Function(Box::new(Function::new(
506 "CEILING".to_string(),
507 vec![f.this],
508 )))),
509
510 Expression::Repeat(f) => Ok(Expression::Function(Box::new(Function::new(
512 "REPLICATE".to_string(),
513 vec![f.this, f.times],
514 )))),
515
516 Expression::Chr(f) => Ok(Expression::Function(Box::new(Function::new(
518 "CHAR".to_string(),
519 vec![f.this],
520 )))),
521
522 Expression::Overlay(f) => Ok(Self::overlay_to_stuff(*f)),
524
525 Expression::StartsWith(f) => Ok(Self::starts_with_predicate(f.this, f.expression)),
528
529 Expression::ToNumber(f) => Ok(Self::to_number_or_fallback(*f)),
532
533 Expression::VarPop(f) => Ok(Expression::Function(Box::new(Function::new(
536 "VARP".to_string(),
537 vec![f.this],
538 )))),
539
540 Expression::Variance(f) => Ok(Expression::Function(Box::new(Function::new(
542 "VAR".to_string(),
543 vec![f.this],
544 )))),
545 Expression::VarSamp(f) => Ok(Expression::Function(Box::new(Function::new(
546 "VAR".to_string(),
547 vec![f.this],
548 )))),
549
550 Expression::MD5Digest(f) => Ok(Expression::Function(Box::new(Function::new(
553 "HASHBYTES".to_string(),
554 vec![Expression::string("MD5"), *f.this],
555 )))),
556
557 Expression::SHA(f) => Ok(Expression::Function(Box::new(Function::new(
559 "HASHBYTES".to_string(),
560 vec![Expression::string("SHA1"), f.this],
561 )))),
562
563 Expression::SHA1Digest(f) => Ok(Expression::Function(Box::new(Function::new(
565 "HASHBYTES".to_string(),
566 vec![Expression::string("SHA1"), f.this],
567 )))),
568
569 Expression::ArrayToString(f) => Ok(Expression::Function(Box::new(Function::new(
572 "STRING_AGG".to_string(),
573 vec![f.this],
574 )))),
575
576 Expression::AutoIncrementColumnConstraint(_) => Ok(Expression::Function(Box::new(
579 Function::new("IDENTITY".to_string(), vec![]),
580 ))),
581
582 Expression::CreateView(mut view) => {
586 view.name.catalog = None;
588 Ok(Expression::CreateView(view))
589 }
590
591 Expression::DropView(mut view) => {
592 view.name.catalog = None;
594 Ok(Expression::DropView(view))
595 }
596
597 Expression::JSONExtract(e) if e.variant_extract.is_some() => {
601 let path = match *e.expression {
602 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
603 let Literal::String(s) = lit.as_ref() else {
604 unreachable!()
605 };
606 let normalized = if s.starts_with('$') {
607 s.clone()
608 } else if s.starts_with('[') {
609 format!("${}", s)
610 } else {
611 format!("$.{}", s)
612 };
613 Expression::Literal(Box::new(Literal::String(normalized)))
614 }
615 other => other,
616 };
617 let json_query = Expression::Function(Box::new(Function::new(
618 "JSON_QUERY".to_string(),
619 vec![(*e.this).clone(), path.clone()],
620 )));
621 let json_value = Expression::Function(Box::new(Function::new(
622 "JSON_VALUE".to_string(),
623 vec![*e.this, path],
624 )));
625 Ok(Expression::Function(Box::new(Function::new(
626 "ISNULL".to_string(),
627 vec![json_query, json_value],
628 ))))
629 }
630
631 Expression::Function(f) => self.transform_function(*f),
633
634 Expression::AggregateFunction(f) => self.transform_aggregate_function(f),
636
637 Expression::Cte(cte) => self.transform_cte(*cte),
640
641 Expression::Subquery(subquery) => self.transform_subquery(*subquery),
644
645 Expression::JsonQuery(f) => {
647 let json_query = Expression::Function(Box::new(Function::new(
648 "JSON_QUERY".to_string(),
649 vec![f.this.clone(), f.path.clone()],
650 )));
651 let json_value = Expression::Function(Box::new(Function::new(
652 "JSON_VALUE".to_string(),
653 vec![f.this, f.path],
654 )));
655 Ok(Expression::Function(Box::new(Function::new(
656 "ISNULL".to_string(),
657 vec![json_query, json_value],
658 ))))
659 }
660 Expression::JsonValue(f) => Ok(Expression::Function(Box::new(Function::new(
662 "JSON_VALUE".to_string(),
663 vec![f.this, f.path],
664 )))),
665
666 Expression::Any(ref q) if matches!(&q.op, Some(QuantifiedOp::Eq)) => {
669 match Self::scalar_array_comparison_values(&q.subquery) {
670 Some(expressions) if expressions.is_empty() => {
671 Ok(Expression::Eq(Box::new(crate::expressions::BinaryOp::new(
672 Expression::Literal(Box::new(Literal::Number("1".to_string()))),
673 Expression::Literal(Box::new(Literal::Number("0".to_string()))),
674 ))))
675 }
676 Some(expressions) => Ok(Expression::In(Box::new(In {
677 this: q.this.clone(),
678 expressions,
679 query: None,
680 not: false,
681 global: false,
682 unnest: None,
683 is_field: false,
684 }))),
685 None => Ok(expr.clone()),
686 }
687 }
688
689 _ => Ok(expr),
691 }
692 }
693}
694
695#[cfg(feature = "transpile")]
696impl TSQLDialect {
697 fn getdate() -> Expression {
698 Expression::Function(Box::new(Function::new("GETDATE".to_string(), vec![])))
699 }
700
701 fn cast_getdate_to(to: DataType) -> Expression {
702 Expression::Cast(Box::new(Cast {
703 this: Self::getdate(),
704 to,
705 trailing_comments: Vec::new(),
706 double_colon_syntax: false,
707 format: None,
708 default: None,
709 inferred_type: None,
710 }))
711 }
712
713 fn cast(this: Expression, to: DataType) -> Expression {
714 Expression::Cast(Box::new(Cast {
715 this,
716 to,
717 trailing_comments: Vec::new(),
718 double_colon_syntax: false,
719 format: None,
720 default: None,
721 inferred_type: None,
722 }))
723 }
724
725 fn function(name: impl Into<String>, args: Vec<Expression>) -> Expression {
726 Expression::Function(Box::new(Function::new(name, args)))
727 }
728
729 fn lower(this: Expression) -> Expression {
730 Expression::Lower(Box::new(UnaryFunc::new(this)))
731 }
732
733 fn tsql_convert(to: DataType, expression: Expression, style: Option<i64>) -> Expression {
734 let mut args = vec![Expression::DataType(to), expression];
735 if let Some(style) = style {
736 args.push(Expression::number(style));
737 }
738 Self::function("CONVERT", args)
739 }
740
741 fn tsql_hex_text(expression: Expression, varchar_type: DataType) -> Expression {
742 Self::lower(Self::tsql_convert(varchar_type, expression, Some(2)))
743 }
744
745 fn tsql_hex_from_varbinary(expression: Expression) -> Expression {
746 Self::tsql_hex_text(
747 Self::cast(
748 expression,
749 DataType::Custom {
750 name: "VARBINARY(MAX)".to_string(),
751 },
752 ),
753 DataType::Text,
754 )
755 }
756
757 fn tsql_md5_hex(expression: Expression) -> Expression {
758 let hashbytes = Self::function("HASHBYTES", vec![Expression::string("MD5"), expression]);
759 Self::tsql_hex_text(
760 hashbytes,
761 DataType::VarChar {
762 length: Some(32),
763 parenthesized_length: false,
764 },
765 )
766 }
767
768 fn overlay_to_stuff(f: crate::expressions::OverlayFunc) -> Expression {
769 let length = f
770 .length
771 .unwrap_or_else(|| Self::function("LEN", vec![f.replacement.clone()]));
772 Self::function("STUFF", vec![f.this, f.from, length, f.replacement])
773 }
774
775 fn starts_with_predicate(this: Expression, prefix: Expression) -> Expression {
776 let prefix_len = Self::function("LEN", vec![prefix.clone()]);
777 let left_prefix = Self::function("LEFT", vec![this, prefix_len]);
778 Self::eq(left_prefix, prefix)
779 }
780
781 fn to_number_or_fallback(f: crate::expressions::ToNumber) -> Expression {
782 let crate::expressions::ToNumber {
783 this,
784 format,
785 nlsparam,
786 precision,
787 scale,
788 safe,
789 safe_name,
790 } = f;
791
792 if nlsparam.is_none()
793 && precision.is_none()
794 && scale.is_none()
795 && safe.is_none()
796 && safe_name.is_none()
797 {
798 if let Some(format) = format.as_deref() {
799 if let Some(scale) = Self::simple_to_number_scale(format) {
800 return Self::function(
801 "TRY_CONVERT",
802 vec![
803 Expression::DataType(DataType::Decimal {
804 precision: Some(18),
805 scale: Some(scale),
806 }),
807 *this,
808 ],
809 );
810 }
811 }
812 }
813
814 Expression::ToNumber(Box::new(crate::expressions::ToNumber {
815 this,
816 format,
817 nlsparam,
818 precision,
819 scale,
820 safe,
821 safe_name,
822 }))
823 }
824
825 fn simple_to_number_scale(format: &Expression) -> Option<u32> {
826 let format = Self::literal_string(format)?;
827 let format = format.strip_prefix("FM").unwrap_or(format);
828 let mut saw_digit = false;
829 let mut saw_decimal = false;
830 let mut scale = 0u32;
831
832 for ch in format.chars() {
833 match ch {
834 '9' | '0' => {
835 saw_digit = true;
836 if saw_decimal {
837 scale = scale.checked_add(1)?;
838 }
839 }
840 '.' if !saw_decimal => saw_decimal = true,
841 ',' | ' ' => {}
842 _ => return None,
843 }
844 }
845
846 saw_digit.then_some(scale)
847 }
848
849 fn binary(
850 left: Expression,
851 right: Expression,
852 op: fn(Box<BinaryOp>) -> Expression,
853 ) -> Expression {
854 op(Box::new(BinaryOp {
855 left,
856 right,
857 left_comments: Vec::new(),
858 operator_comments: Vec::new(),
859 trailing_comments: Vec::new(),
860 inferred_type: None,
861 }))
862 }
863
864 fn eq(left: Expression, right: Expression) -> Expression {
865 Self::binary(left, right, Expression::Eq)
866 }
867
868 fn or(left: Expression, right: Expression) -> Expression {
869 Self::binary(left, right, Expression::Or)
870 }
871
872 fn not(this: Expression) -> Expression {
873 Expression::Not(Box::new(crate::expressions::UnaryOp {
874 this,
875 inferred_type: None,
876 }))
877 }
878
879 fn is_null(this: Expression) -> Expression {
880 Expression::IsNull(Box::new(crate::expressions::IsNull {
881 this,
882 not: false,
883 postfix_form: false,
884 }))
885 }
886
887 fn paren(this: Expression) -> Expression {
888 Expression::Paren(Box::new(Paren {
889 this,
890 trailing_comments: Vec::new(),
891 }))
892 }
893
894 fn boolean_test_case_for_predicate(
895 predicate: Expression,
896 test_true: bool,
897 negated: bool,
898 ) -> Expression {
899 let condition = match (test_true, negated) {
900 (true, false) => predicate,
901 (false, false) => Self::not(predicate),
902 (true, true) => {
903 return Expression::Case(Box::new(crate::expressions::Case {
904 operand: None,
905 whens: vec![(predicate, Expression::number(0))],
906 else_: Some(Expression::number(1)),
907 comments: Vec::new(),
908 inferred_type: None,
909 }))
910 }
911 (false, true) => {
912 return Expression::Case(Box::new(crate::expressions::Case {
913 operand: None,
914 whens: vec![(Self::not(predicate), Expression::number(0))],
915 else_: Some(Expression::number(1)),
916 comments: Vec::new(),
917 inferred_type: None,
918 }))
919 }
920 };
921
922 Expression::Case(Box::new(crate::expressions::Case {
923 operand: None,
924 whens: vec![(condition, Expression::number(1))],
925 else_: Some(Expression::number(0)),
926 comments: Vec::new(),
927 inferred_type: None,
928 }))
929 }
930
931 fn boolean_test_predicate(operand: Expression, test_true: bool, negated: bool) -> Expression {
932 if Self::is_boolean_predicate_operand(&operand) {
933 return match (test_true, negated) {
934 (true, false) => operand,
935 (false, false) => Self::not(operand),
936 _ => Self::eq(
937 Self::boolean_test_case_for_predicate(operand, test_true, negated),
938 Expression::number(1),
939 ),
940 };
941 }
942
943 match (test_true, negated) {
944 (true, false) => Self::eq(operand, Expression::number(1)),
945 (false, false) => Self::eq(operand, Expression::number(0)),
946 (true, true) => Self::or(
947 Self::eq(operand.clone(), Expression::number(0)),
948 Self::is_null(operand),
949 ),
950 (false, true) => Self::or(
951 Self::eq(operand.clone(), Expression::number(1)),
952 Self::is_null(operand),
953 ),
954 }
955 }
956
957 fn is_boolean_predicate_operand(expr: &Expression) -> bool {
958 match expr {
959 Expression::Paren(paren) => Self::is_boolean_predicate_operand(&paren.this),
960 Expression::Eq(_)
961 | Expression::Neq(_)
962 | Expression::Lt(_)
963 | Expression::Lte(_)
964 | Expression::Gt(_)
965 | Expression::Gte(_)
966 | Expression::Is(_)
967 | Expression::IsNull(_)
968 | Expression::IsTrue(_)
969 | Expression::IsFalse(_)
970 | Expression::Like(_)
971 | Expression::ILike(_)
972 | Expression::SimilarTo(_)
973 | Expression::Glob(_)
974 | Expression::RegexpLike(_)
975 | Expression::In(_)
976 | Expression::Between(_)
977 | Expression::Exists(_)
978 | Expression::And(_)
979 | Expression::Or(_)
980 | Expression::Not(_)
981 | Expression::Any(_)
982 | Expression::All(_)
983 | Expression::EqualNull(_) => true,
984 _ => false,
985 }
986 }
987
988 fn scalar_array_comparison_values(expr: &Expression) -> Option<Vec<Expression>> {
989 let (mut values, element_type) = Self::scalar_array_comparison_values_inner(expr)?;
990 if let Some(to) = element_type {
991 values = values
992 .into_iter()
993 .map(|value| Self::cast_scalar_array_comparison_value(value, to.clone()))
994 .collect();
995 }
996 Some(values)
997 }
998
999 fn scalar_array_comparison_values_inner(
1000 expr: &Expression,
1001 ) -> Option<(Vec<Expression>, Option<DataType>)> {
1002 match expr {
1003 Expression::ArrayFunc(a) => Some((a.expressions.clone(), None)),
1004 Expression::Array(a) => Some((a.expressions.clone(), None)),
1005 Expression::Tuple(t) => Some((t.expressions.clone(), None)),
1006 Expression::Paren(p) => Self::scalar_array_comparison_values_inner(&p.this),
1007 Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
1008 let DataType::Array { element_type, .. } = &c.to else {
1009 return None;
1010 };
1011 let (values, _) = Self::scalar_array_comparison_values_inner(&c.this)?;
1012 Some((values, Some((**element_type).clone())))
1013 }
1014 _ => None,
1015 }
1016 }
1017
1018 fn cast_scalar_array_comparison_value(value: Expression, to: DataType) -> Expression {
1019 if matches!(&value, Expression::Cast(c) if c.to == to) {
1020 return value;
1021 }
1022
1023 Expression::Cast(Box::new(Cast {
1024 this: value,
1025 to,
1026 trailing_comments: Vec::new(),
1027 double_colon_syntax: false,
1028 format: None,
1029 default: None,
1030 inferred_type: None,
1031 }))
1032 }
1033
1034 fn normalize_frame_incompatible_window_functions(select: &mut Select) {
1035 let window_map: HashMap<String, Over> = select
1036 .windows
1037 .as_ref()
1038 .map(|windows| {
1039 windows
1040 .iter()
1041 .map(|window| (window.name.name.to_lowercase(), window.spec.clone()))
1042 .collect()
1043 })
1044 .unwrap_or_default();
1045
1046 for expr in &mut select.expressions {
1047 Self::normalize_frame_incompatible_window_expr(expr, &window_map);
1048 }
1049
1050 if let Some(order_by) = &mut select.order_by {
1051 for ordered in &mut order_by.expressions {
1052 Self::normalize_frame_incompatible_window_expr(&mut ordered.this, &window_map);
1053 }
1054 }
1055
1056 if let Some(qualify) = &mut select.qualify {
1057 Self::normalize_frame_incompatible_window_expr(&mut qualify.this, &window_map);
1058 }
1059 }
1060
1061 fn normalize_frame_incompatible_window_expr(
1062 expr: &mut Expression,
1063 window_map: &HashMap<String, Over>,
1064 ) {
1065 match expr {
1066 Expression::WindowFunction(wf) => {
1067 Self::normalize_frame_incompatible_window_expr(&mut wf.this, window_map);
1068
1069 if !Self::is_tsql_frame_incompatible_window_function(&wf.this) {
1070 return;
1071 }
1072
1073 wf.over.frame = None;
1074
1075 let Some(window_name) = wf.over.window_name.clone() else {
1076 return;
1077 };
1078 let Some(named_spec) =
1079 Self::resolve_named_window_spec(&window_name.name, window_map, &mut Vec::new())
1080 else {
1081 return;
1082 };
1083
1084 if named_spec.frame.is_none() {
1085 return;
1086 }
1087
1088 if wf.over.partition_by.is_empty() {
1089 wf.over.partition_by = named_spec.partition_by;
1090 }
1091 if wf.over.order_by.is_empty() {
1092 wf.over.order_by = named_spec.order_by;
1093 }
1094 wf.over.window_name = None;
1095 wf.over.frame = None;
1096 }
1097 Expression::Alias(alias) => {
1098 Self::normalize_frame_incompatible_window_expr(&mut alias.this, window_map);
1099 }
1100 Expression::Paren(paren) => {
1101 Self::normalize_frame_incompatible_window_expr(&mut paren.this, window_map);
1102 }
1103 Expression::Cast(cast) | Expression::TryCast(cast) | Expression::SafeCast(cast) => {
1104 Self::normalize_frame_incompatible_window_expr(&mut cast.this, window_map);
1105 }
1106 Expression::Function(function) => {
1107 for arg in &mut function.args {
1108 Self::normalize_frame_incompatible_window_expr(arg, window_map);
1109 }
1110 }
1111 Expression::Case(case) => {
1112 if let Some(operand) = &mut case.operand {
1113 Self::normalize_frame_incompatible_window_expr(operand, window_map);
1114 }
1115 for (condition, result) in &mut case.whens {
1116 Self::normalize_frame_incompatible_window_expr(condition, window_map);
1117 Self::normalize_frame_incompatible_window_expr(result, window_map);
1118 }
1119 if let Some(else_expr) = &mut case.else_ {
1120 Self::normalize_frame_incompatible_window_expr(else_expr, window_map);
1121 }
1122 }
1123 Expression::And(op)
1124 | Expression::Or(op)
1125 | Expression::Add(op)
1126 | Expression::Sub(op)
1127 | Expression::Mul(op)
1128 | Expression::Div(op)
1129 | Expression::Mod(op)
1130 | Expression::Eq(op)
1131 | Expression::Neq(op)
1132 | Expression::Lt(op)
1133 | Expression::Lte(op)
1134 | Expression::Gt(op)
1135 | Expression::Gte(op)
1136 | Expression::Match(op)
1137 | Expression::BitwiseAnd(op)
1138 | Expression::BitwiseOr(op)
1139 | Expression::BitwiseXor(op)
1140 | Expression::Concat(op)
1141 | Expression::Adjacent(op)
1142 | Expression::TsMatch(op)
1143 | Expression::PropertyEQ(op)
1144 | Expression::ArrayContainsAll(op)
1145 | Expression::ArrayContainedBy(op)
1146 | Expression::ArrayOverlaps(op)
1147 | Expression::JSONBContainsAllTopKeys(op)
1148 | Expression::JSONBContainsAnyTopKeys(op)
1149 | Expression::JSONBDeleteAtPath(op)
1150 | Expression::ExtendsLeft(op)
1151 | Expression::ExtendsRight(op)
1152 | Expression::Is(op)
1153 | Expression::MemberOf(op) => {
1154 Self::normalize_frame_incompatible_window_expr(&mut op.left, window_map);
1155 Self::normalize_frame_incompatible_window_expr(&mut op.right, window_map);
1156 }
1157 Expression::Like(op) | Expression::ILike(op) => {
1158 Self::normalize_frame_incompatible_window_expr(&mut op.left, window_map);
1159 Self::normalize_frame_incompatible_window_expr(&mut op.right, window_map);
1160 if let Some(escape) = &mut op.escape {
1161 Self::normalize_frame_incompatible_window_expr(escape, window_map);
1162 }
1163 }
1164 Expression::Not(op) | Expression::Neg(op) | Expression::BitwiseNot(op) => {
1165 Self::normalize_frame_incompatible_window_expr(&mut op.this, window_map);
1166 }
1167 Expression::In(in_expr) => {
1168 Self::normalize_frame_incompatible_window_expr(&mut in_expr.this, window_map);
1169 for value in &mut in_expr.expressions {
1170 Self::normalize_frame_incompatible_window_expr(value, window_map);
1171 }
1172 }
1173 Expression::Between(between) => {
1174 Self::normalize_frame_incompatible_window_expr(&mut between.this, window_map);
1175 Self::normalize_frame_incompatible_window_expr(&mut between.low, window_map);
1176 Self::normalize_frame_incompatible_window_expr(&mut between.high, window_map);
1177 }
1178 Expression::IsNull(is_null) => {
1179 Self::normalize_frame_incompatible_window_expr(&mut is_null.this, window_map);
1180 }
1181 Expression::IsTrue(is_true) | Expression::IsFalse(is_true) => {
1182 Self::normalize_frame_incompatible_window_expr(&mut is_true.this, window_map);
1183 }
1184 _ => {}
1185 }
1186 }
1187
1188 fn is_tsql_frame_incompatible_window_function(expr: &Expression) -> bool {
1189 matches!(
1190 expr,
1191 Expression::RowNumber(_)
1192 | Expression::Rank(_)
1193 | Expression::DenseRank(_)
1194 | Expression::NTile(_)
1195 | Expression::Ntile(_)
1196 | Expression::Lead(_)
1197 | Expression::Lag(_)
1198 | Expression::PercentRank(_)
1199 | Expression::CumeDist(_)
1200 )
1201 }
1202
1203 fn resolve_named_window_spec(
1204 name: &str,
1205 window_map: &HashMap<String, Over>,
1206 seen: &mut Vec<String>,
1207 ) -> Option<Over> {
1208 let key = name.to_lowercase();
1209 if seen.iter().any(|seen_name| seen_name == &key) {
1210 return None;
1211 }
1212
1213 let named_spec = window_map.get(&key)?.clone();
1214 seen.push(key);
1215
1216 let mut resolved = if let Some(base_window) = &named_spec.window_name {
1217 Self::resolve_named_window_spec(&base_window.name, window_map, seen)
1218 .unwrap_or_else(Self::empty_over)
1219 } else {
1220 Self::empty_over()
1221 };
1222
1223 if !named_spec.partition_by.is_empty() {
1224 resolved.partition_by = named_spec.partition_by;
1225 }
1226 if !named_spec.order_by.is_empty() {
1227 resolved.order_by = named_spec.order_by;
1228 }
1229 if named_spec.frame.is_some() {
1230 resolved.frame = named_spec.frame;
1231 }
1232
1233 Some(resolved)
1234 }
1235
1236 fn empty_over() -> Over {
1237 Over {
1238 window_name: None,
1239 partition_by: Vec::new(),
1240 order_by: Vec::new(),
1241 frame: None,
1242 alias: None,
1243 }
1244 }
1245
1246 const LATERAL_WRAPPER_SOURCE_ALIAS: &'static str = "_polyglot_lateral_source";
1247 const LATERAL_WRAPPER_OUTPUT_ALIAS: &'static str = "_polyglot_lateral";
1248
1249 fn transform_lateral_join_to_apply(mut join: Join) -> Result<Join> {
1250 let Some(apply_kind) = Self::lateral_apply_kind(&join) else {
1251 return Ok(join);
1252 };
1253
1254 let original_alias = Self::table_expression_alias(&join.this);
1255 let on = join.on.take();
1256 let rhs = Self::remove_lateral_marker(join.this);
1257 join.this = if on
1258 .as_ref()
1259 .is_some_and(|expr| !Self::is_true_condition(expr))
1260 {
1261 Self::wrap_lateral_apply_rhs(rhs, on.expect("checked as Some"), original_alias)?
1262 } else {
1263 rhs
1264 };
1265 join.using.clear();
1266 join.kind = apply_kind;
1267 join.use_inner_keyword = false;
1268 join.use_outer_keyword = false;
1269 join.deferred_condition = false;
1270 join.join_hint = None;
1271 join.match_condition = None;
1272 join.directed = false;
1273 Ok(join)
1274 }
1275
1276 fn rewrite_comma_lateral_sources_to_joins(select: &mut Select) {
1277 let Some(from) = select.from.as_mut() else {
1278 return;
1279 };
1280 if from.expressions.len() < 2
1281 || !from
1282 .expressions
1283 .iter()
1284 .skip(1)
1285 .any(Self::is_lateral_table_expression)
1286 {
1287 return;
1288 }
1289
1290 let mut expressions = std::mem::take(&mut from.expressions).into_iter();
1291 let Some(first) = expressions.next() else {
1292 return;
1293 };
1294 from.expressions = vec![first];
1295
1296 let mut joins = expressions
1297 .map(|source| {
1298 if Self::is_lateral_table_expression(&source) {
1299 Self::new_join(Self::remove_lateral_marker(source), JoinKind::CrossApply)
1300 } else {
1301 Self::new_join(source, JoinKind::Cross)
1302 }
1303 })
1304 .collect::<Vec<_>>();
1305 joins.append(&mut select.joins);
1306 select.joins = joins;
1307 }
1308
1309 fn new_join(this: Expression, kind: JoinKind) -> Join {
1310 Join {
1311 this,
1312 on: None,
1313 using: Vec::new(),
1314 kind,
1315 use_inner_keyword: false,
1316 use_outer_keyword: false,
1317 deferred_condition: false,
1318 join_hint: None,
1319 match_condition: None,
1320 pivots: Vec::new(),
1321 comments: Vec::new(),
1322 nesting_group: 0,
1323 directed: false,
1324 }
1325 }
1326
1327 fn lateral_apply_kind(join: &Join) -> Option<JoinKind> {
1328 if !join.using.is_empty() {
1329 return None;
1330 }
1331
1332 match join.kind {
1333 JoinKind::Lateral => Some(JoinKind::CrossApply),
1334 JoinKind::LeftLateral => Some(JoinKind::OuterApply),
1335 JoinKind::Cross | JoinKind::Inner | JoinKind::Implicit
1336 if Self::is_lateral_table_expression(&join.this) =>
1337 {
1338 Some(JoinKind::CrossApply)
1339 }
1340 JoinKind::Left if Self::is_lateral_table_expression(&join.this) => {
1341 Some(JoinKind::OuterApply)
1342 }
1343 _ => None,
1344 }
1345 }
1346
1347 fn is_true_condition(expr: &Expression) -> bool {
1348 match expr {
1349 Expression::Boolean(boolean) => boolean.value,
1350 Expression::Literal(lit) => {
1351 matches!(lit.as_ref(), Literal::Number(value) if value.trim() == "1")
1352 }
1353 Expression::Eq(op) => {
1354 Self::is_true_condition(&op.left) && Self::is_true_condition(&op.right)
1355 }
1356 Expression::Paren(paren) => Self::is_true_condition(&paren.this),
1357 _ => false,
1358 }
1359 }
1360
1361 fn table_expression_alias(expr: &Expression) -> Option<(Identifier, Vec<Identifier>)> {
1362 match expr {
1363 Expression::Subquery(subquery) => subquery
1364 .alias
1365 .clone()
1366 .map(|alias| (alias, subquery.column_aliases.clone())),
1367 Expression::Alias(alias) if !alias.alias.is_empty() => {
1368 Some((alias.alias.clone(), alias.column_aliases.clone()))
1369 }
1370 Expression::Lateral(lateral) => lateral.alias.as_ref().map(|alias| {
1371 (
1372 if lateral.alias_quoted {
1373 Identifier::quoted(alias)
1374 } else {
1375 Identifier::new(alias)
1376 },
1377 lateral
1378 .column_aliases
1379 .iter()
1380 .map(|column| Identifier::new(column.clone()))
1381 .collect(),
1382 )
1383 }),
1384 _ => None,
1385 }
1386 }
1387
1388 fn wrap_lateral_apply_rhs(
1389 rhs: Expression,
1390 predicate: Expression,
1391 original_alias: Option<(Identifier, Vec<Identifier>)>,
1392 ) -> Result<Expression> {
1393 let (outer_alias, column_aliases) = original_alias.unwrap_or_else(|| {
1394 (
1395 Identifier::new(Self::LATERAL_WRAPPER_OUTPUT_ALIAS),
1396 Vec::new(),
1397 )
1398 });
1399 let inner_alias = Identifier::new(Self::LATERAL_WRAPPER_SOURCE_ALIAS);
1400 let source =
1401 Self::with_table_expression_alias(rhs, inner_alias.clone(), column_aliases.clone());
1402 let predicate = Self::rewrite_column_qualifier(predicate, &outer_alias, &inner_alias)?;
1403
1404 let mut select = Select::new();
1405 select.expressions = vec![Expression::Star(Star {
1406 table: None,
1407 except: None,
1408 replace: None,
1409 rename: None,
1410 trailing_comments: Vec::new(),
1411 span: None,
1412 })];
1413 select.from = Some(crate::expressions::From {
1414 expressions: vec![source],
1415 });
1416 select.where_clause = Some(Where { this: predicate });
1417
1418 Ok(Expression::Subquery(Box::new(Subquery {
1419 this: Expression::Select(Box::new(select)),
1420 alias: Some(outer_alias),
1421 column_aliases,
1422 alias_explicit_as: true,
1423 alias_keyword: None,
1424 order_by: None,
1425 limit: None,
1426 offset: None,
1427 distribute_by: None,
1428 sort_by: None,
1429 cluster_by: None,
1430 lateral: false,
1431 modifiers_inside: false,
1432 trailing_comments: Vec::new(),
1433 inferred_type: None,
1434 })))
1435 }
1436
1437 fn with_table_expression_alias(
1438 expr: Expression,
1439 alias: Identifier,
1440 column_aliases: Vec<Identifier>,
1441 ) -> Expression {
1442 match expr {
1443 Expression::Subquery(mut subquery) => {
1444 subquery.alias = Some(alias);
1445 subquery.column_aliases = column_aliases;
1446 subquery.alias_explicit_as = true;
1447 subquery.alias_keyword = None;
1448 Expression::Subquery(subquery)
1449 }
1450 Expression::Alias(mut aliased) => {
1451 aliased.alias = alias;
1452 aliased.column_aliases = column_aliases;
1453 aliased.alias_explicit_as = true;
1454 aliased.alias_keyword = None;
1455 Expression::Alias(aliased)
1456 }
1457 Expression::Table(mut table) => {
1458 table.alias = Some(alias);
1459 table.alias_explicit_as = true;
1460 table.column_aliases = column_aliases;
1461 Expression::Table(table)
1462 }
1463 other => Expression::Alias(Box::new(Alias {
1464 this: other,
1465 alias,
1466 column_aliases,
1467 alias_explicit_as: true,
1468 alias_keyword: None,
1469 pre_alias_comments: Vec::new(),
1470 trailing_comments: Vec::new(),
1471 inferred_type: None,
1472 })),
1473 }
1474 }
1475
1476 fn rewrite_column_qualifier(
1477 expr: Expression,
1478 from: &Identifier,
1479 to: &Identifier,
1480 ) -> Result<Expression> {
1481 super::transform_recursive(expr, &|expr| {
1482 Ok(match expr {
1483 Expression::Column(mut column)
1484 if column
1485 .table
1486 .as_ref()
1487 .is_some_and(|table| Self::same_identifier(table, from)) =>
1488 {
1489 column.table = Some(to.clone());
1490 Expression::Column(column)
1491 }
1492 other => other,
1493 })
1494 })
1495 }
1496
1497 fn same_identifier(left: &Identifier, right: &Identifier) -> bool {
1498 if left.quoted || right.quoted {
1499 left.quoted == right.quoted && left.name == right.name
1500 } else {
1501 left.name.eq_ignore_ascii_case(&right.name)
1502 }
1503 }
1504
1505 fn is_lateral_table_expression(expr: &Expression) -> bool {
1506 match expr {
1507 Expression::Subquery(subquery) => subquery.lateral,
1508 Expression::Lateral(_) => true,
1509 Expression::Alias(alias) => Self::is_lateral_table_expression(&alias.this),
1510 _ => false,
1511 }
1512 }
1513
1514 fn remove_lateral_marker(expr: Expression) -> Expression {
1515 match expr {
1516 Expression::Subquery(mut subquery) => {
1517 subquery.lateral = false;
1518 Expression::Subquery(subquery)
1519 }
1520 Expression::Lateral(lateral) => Self::lateral_to_table_expression(*lateral),
1521 Expression::Alias(mut alias) => {
1522 alias.this = Self::remove_lateral_marker(alias.this);
1523 Expression::Alias(alias)
1524 }
1525 other => other,
1526 }
1527 }
1528
1529 fn lateral_to_table_expression(lateral: crate::expressions::Lateral) -> Expression {
1530 let expr = *lateral.this;
1531 let Some(alias) = lateral.alias else {
1532 return expr;
1533 };
1534
1535 Expression::Alias(Box::new(Alias {
1536 this: expr,
1537 alias: if lateral.alias_quoted {
1538 Identifier::quoted(alias)
1539 } else {
1540 Identifier::new(alias)
1541 },
1542 column_aliases: lateral
1543 .column_aliases
1544 .into_iter()
1545 .map(Identifier::new)
1546 .collect(),
1547 alias_explicit_as: true,
1548 alias_keyword: None,
1549 pre_alias_comments: Vec::new(),
1550 trailing_comments: Vec::new(),
1551 inferred_type: None,
1552 }))
1553 }
1554
1555 fn rewrite_tuple_in_subquery_predicates(
1556 expr: Expression,
1557 outer_qualifier: Option<&Identifier>,
1558 under_not: bool,
1559 ) -> Expression {
1560 match expr {
1561 Expression::In(in_expr) if !under_not => {
1562 let in_expr = *in_expr;
1563 Self::tuple_in_subquery_to_exists(&in_expr, outer_qualifier, in_expr.not)
1564 .unwrap_or_else(|| Expression::In(Box::new(in_expr)))
1565 }
1566 Expression::Eq(op) if !under_not => {
1567 let op = *op;
1568 Self::tuple_subquery_eq_to_exists(&op, outer_qualifier)
1569 .unwrap_or_else(|| Expression::Eq(Box::new(op)))
1570 }
1571 Expression::And(mut op) => {
1572 op.left =
1573 Self::rewrite_tuple_in_subquery_predicates(op.left, outer_qualifier, under_not);
1574 op.right = Self::rewrite_tuple_in_subquery_predicates(
1575 op.right,
1576 outer_qualifier,
1577 under_not,
1578 );
1579 Expression::And(op)
1580 }
1581 Expression::Or(mut op) => {
1582 op.left =
1583 Self::rewrite_tuple_in_subquery_predicates(op.left, outer_qualifier, under_not);
1584 op.right = Self::rewrite_tuple_in_subquery_predicates(
1585 op.right,
1586 outer_qualifier,
1587 under_not,
1588 );
1589 Expression::Or(op)
1590 }
1591 Expression::Paren(mut paren) => {
1592 paren.this = Self::rewrite_tuple_in_subquery_predicates(
1593 paren.this,
1594 outer_qualifier,
1595 under_not,
1596 );
1597 Expression::Paren(paren)
1598 }
1599 Expression::Not(mut not) => {
1600 if let Some(rewritten) = Self::direct_tuple_subquery_predicate_to_exists(
1601 ¬.this,
1602 outer_qualifier,
1603 true,
1604 ) {
1605 rewritten
1606 } else {
1607 not.this =
1608 Self::rewrite_tuple_in_subquery_predicates(not.this, outer_qualifier, true);
1609 Expression::Not(not)
1610 }
1611 }
1612 Expression::Alias(mut alias) => {
1613 alias.this = Self::rewrite_tuple_in_subquery_predicates(
1614 alias.this,
1615 outer_qualifier,
1616 under_not,
1617 );
1618 Expression::Alias(alias)
1619 }
1620 Expression::Cast(mut cast) => {
1621 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1622 cast.this,
1623 outer_qualifier,
1624 under_not,
1625 );
1626 if let Some(format) = cast.format.take() {
1627 cast.format = Some(Box::new(Self::rewrite_tuple_in_subquery_predicates(
1628 *format,
1629 outer_qualifier,
1630 under_not,
1631 )));
1632 }
1633 if let Some(default) = cast.default.take() {
1634 cast.default = Some(Box::new(Self::rewrite_tuple_in_subquery_predicates(
1635 *default,
1636 outer_qualifier,
1637 under_not,
1638 )));
1639 }
1640 Expression::Cast(cast)
1641 }
1642 Expression::TryCast(mut cast) => {
1643 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1644 cast.this,
1645 outer_qualifier,
1646 under_not,
1647 );
1648 Expression::TryCast(cast)
1649 }
1650 Expression::SafeCast(mut cast) => {
1651 cast.this = Self::rewrite_tuple_in_subquery_predicates(
1652 cast.this,
1653 outer_qualifier,
1654 under_not,
1655 );
1656 Expression::SafeCast(cast)
1657 }
1658 Expression::Case(mut case) => {
1659 if let Some(operand) = case.operand.take() {
1660 case.operand = Some(Self::rewrite_tuple_in_subquery_predicates(
1661 operand,
1662 outer_qualifier,
1663 under_not,
1664 ));
1665 }
1666 case.whens = case
1667 .whens
1668 .into_iter()
1669 .map(|(condition, result)| {
1670 (
1671 Self::rewrite_tuple_in_subquery_predicates(
1672 condition,
1673 outer_qualifier,
1674 false,
1675 ),
1676 Self::rewrite_tuple_in_subquery_predicates(
1677 result,
1678 outer_qualifier,
1679 under_not,
1680 ),
1681 )
1682 })
1683 .collect();
1684 if let Some(else_) = case.else_.take() {
1685 case.else_ = Some(Self::rewrite_tuple_in_subquery_predicates(
1686 else_,
1687 outer_qualifier,
1688 under_not,
1689 ));
1690 }
1691 Expression::Case(case)
1692 }
1693 Expression::IfFunc(mut if_func) => {
1694 if_func.condition = Self::rewrite_tuple_in_subquery_predicates(
1695 if_func.condition,
1696 outer_qualifier,
1697 false,
1698 );
1699 if_func.true_value = Self::rewrite_tuple_in_subquery_predicates(
1700 if_func.true_value,
1701 outer_qualifier,
1702 under_not,
1703 );
1704 if let Some(false_value) = if_func.false_value.take() {
1705 if_func.false_value = Some(Self::rewrite_tuple_in_subquery_predicates(
1706 false_value,
1707 outer_qualifier,
1708 under_not,
1709 ));
1710 }
1711 Expression::IfFunc(if_func)
1712 }
1713 other => other,
1714 }
1715 }
1716
1717 fn direct_tuple_subquery_predicate_to_exists(
1718 expr: &Expression,
1719 outer_qualifier: Option<&Identifier>,
1720 negated: bool,
1721 ) -> Option<Expression> {
1722 match expr {
1723 Expression::In(in_expr) => {
1724 Self::tuple_in_subquery_to_exists(in_expr, outer_qualifier, negated ^ in_expr.not)
1725 }
1726 Expression::Paren(paren) => Self::direct_tuple_subquery_predicate_to_exists(
1727 &paren.this,
1728 outer_qualifier,
1729 negated,
1730 ),
1731 _ => None,
1732 }
1733 }
1734
1735 fn tuple_in_subquery_to_exists(
1736 in_expr: &In,
1737 outer_qualifier: Option<&Identifier>,
1738 negated: bool,
1739 ) -> Option<Expression> {
1740 if in_expr.unnest.is_some() {
1741 return None;
1742 }
1743
1744 let left_expressions = Self::tuple_expressions(&in_expr.this)?;
1745 let mut select = Self::select_from_in_rhs(in_expr)?;
1746
1747 if left_expressions.len() != select.expressions.len() || left_expressions.is_empty() {
1748 return None;
1749 }
1750
1751 let inner_qualifier = Self::single_select_source_qualifier(&select);
1752 let mut predicates = Vec::with_capacity(left_expressions.len() + 1);
1753 for (projection, left) in select
1754 .expressions
1755 .iter()
1756 .cloned()
1757 .zip(left_expressions.iter().cloned())
1758 {
1759 let inner = Self::tuple_in_projection_expr(projection, inner_qualifier.as_ref())?;
1760 let outer = Self::qualify_tuple_operand(left, outer_qualifier);
1761 predicates.push(if negated {
1762 Self::tuple_component_may_match(inner, outer)
1763 } else {
1764 Expression::Eq(Box::new(BinaryOp::new(inner, outer)))
1765 });
1766 }
1767
1768 if let Some(where_clause) = select.where_clause.take() {
1769 predicates.push(where_clause.this);
1770 }
1771
1772 select.expressions = vec![Expression::number(1)];
1773 select.where_clause = Some(Where {
1774 this: Self::and_all(predicates)?,
1775 });
1776
1777 Some(Expression::Exists(Box::new(Exists {
1778 this: Expression::Select(Box::new(select)),
1779 not: negated,
1780 })))
1781 }
1782
1783 fn tuple_subquery_eq_to_exists(
1784 op: &BinaryOp,
1785 outer_qualifier: Option<&Identifier>,
1786 ) -> Option<Expression> {
1787 if let Some((tuple_expr, query_expr)) = Self::tuple_and_query_operands(&op.left, &op.right)
1788 {
1789 return Self::tuple_subquery_eq_to_exists_inner(
1790 tuple_expr,
1791 query_expr,
1792 outer_qualifier,
1793 );
1794 }
1795
1796 if let Some((tuple_expr, query_expr)) = Self::tuple_and_query_operands(&op.right, &op.left)
1797 {
1798 return Self::tuple_subquery_eq_to_exists_inner(
1799 tuple_expr,
1800 query_expr,
1801 outer_qualifier,
1802 );
1803 }
1804
1805 None
1806 }
1807
1808 fn tuple_subquery_eq_to_exists_inner(
1809 tuple_expr: &Expression,
1810 query_expr: &Expression,
1811 outer_qualifier: Option<&Identifier>,
1812 ) -> Option<Expression> {
1813 let tuple_expressions = Self::tuple_expressions(tuple_expr)?;
1814 let mut select = Self::select_from_query_expression(query_expr)?;
1815
1816 if tuple_expressions.len() != select.expressions.len() || tuple_expressions.is_empty() {
1817 return None;
1818 }
1819
1820 let inner_qualifier = Self::single_select_source_qualifier(&select);
1821 let mut predicates = Vec::with_capacity(tuple_expressions.len() + 1);
1822 for (projection, tuple_operand) in select
1823 .expressions
1824 .iter()
1825 .cloned()
1826 .zip(tuple_expressions.iter().cloned())
1827 {
1828 let inner = Self::tuple_in_projection_expr(projection, inner_qualifier.as_ref())?;
1829 let outer = Self::qualify_tuple_operand(tuple_operand, outer_qualifier);
1830 predicates.push(Expression::Eq(Box::new(BinaryOp::new(inner, outer))));
1831 }
1832
1833 if let Some(where_clause) = select.where_clause.take() {
1834 predicates.push(where_clause.this);
1835 }
1836
1837 select.expressions = vec![Expression::number(1)];
1838 select.where_clause = Some(Where {
1839 this: Self::and_all(predicates)?,
1840 });
1841
1842 Some(Expression::Exists(Box::new(Exists {
1843 this: Expression::Select(Box::new(select)),
1844 not: false,
1845 })))
1846 }
1847
1848 fn tuple_and_query_operands<'a>(
1849 tuple_candidate: &'a Expression,
1850 query_candidate: &'a Expression,
1851 ) -> Option<(&'a Expression, &'a Expression)> {
1852 if Self::tuple_expressions(tuple_candidate).is_some()
1853 && Self::select_from_query_expression(query_candidate).is_some()
1854 {
1855 Some((tuple_candidate, query_candidate))
1856 } else {
1857 None
1858 }
1859 }
1860
1861 fn select_from_query_expression(expr: &Expression) -> Option<Select> {
1862 match expr {
1863 Expression::Select(select) => Some((**select).clone()),
1864 Expression::Subquery(subquery) => Self::select_from_query_expression(&subquery.this),
1865 Expression::Paren(paren) => Self::select_from_query_expression(&paren.this),
1866 _ => None,
1867 }
1868 }
1869
1870 fn select_from_in_rhs(in_expr: &In) -> Option<Select> {
1871 if let Some(query) = &in_expr.query {
1872 return if in_expr.expressions.is_empty() {
1873 Self::select_from_query_expression(query)
1874 } else {
1875 None
1876 };
1877 }
1878
1879 if in_expr.expressions.len() == 1 {
1880 Self::select_from_query_expression(&in_expr.expressions[0])
1881 } else {
1882 None
1883 }
1884 }
1885
1886 fn tuple_expressions(expr: &Expression) -> Option<&[Expression]> {
1887 match expr {
1888 Expression::Tuple(tuple) => Some(&tuple.expressions),
1889 Expression::Function(function) if function.name.eq_ignore_ascii_case("ROW") => {
1890 Some(&function.args)
1891 }
1892 Expression::Paren(paren) => Self::tuple_expressions(&paren.this),
1893 _ => None,
1894 }
1895 }
1896
1897 fn tuple_in_projection_expr(
1898 expr: Expression,
1899 qualifier: Option<&Identifier>,
1900 ) -> Option<Expression> {
1901 match expr {
1902 Expression::Alias(alias) => Self::tuple_in_projection_expr(alias.this, qualifier),
1903 Expression::Column(mut column) => {
1904 if column.table.is_none() {
1905 column.table = qualifier.cloned();
1906 }
1907 Some(Expression::Column(column))
1908 }
1909 Expression::Identifier(identifier) => {
1910 Some(Self::column_from_identifier(identifier, qualifier.cloned()))
1911 }
1912 Expression::Dot(_) => Some(expr),
1913 other => Some(Self::qualify_tuple_expression(other, qualifier)),
1914 }
1915 }
1916
1917 fn qualify_tuple_operand(expr: Expression, qualifier: Option<&Identifier>) -> Expression {
1918 Self::qualify_tuple_expression(expr, qualifier)
1919 }
1920
1921 fn qualify_tuple_expression(expr: Expression, qualifier: Option<&Identifier>) -> Expression {
1922 match expr {
1923 Expression::Column(mut column) => {
1924 if column.table.is_none() {
1925 column.table = qualifier.cloned();
1926 }
1927 Expression::Column(column)
1928 }
1929 Expression::Identifier(identifier) => {
1930 Self::column_from_identifier(identifier, qualifier.cloned())
1931 }
1932 Expression::Alias(mut alias) => {
1933 alias.this = Self::qualify_tuple_expression(alias.this, qualifier);
1934 Expression::Alias(alias)
1935 }
1936 Expression::Paren(mut paren) => {
1937 paren.this = Self::qualify_tuple_expression(paren.this, qualifier);
1938 Expression::Paren(paren)
1939 }
1940 Expression::Cast(mut cast) => {
1941 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
1942 if let Some(format) = cast.format.take() {
1943 cast.format =
1944 Some(Box::new(Self::qualify_tuple_expression(*format, qualifier)));
1945 }
1946 if let Some(default) = cast.default.take() {
1947 cast.default = Some(Box::new(Self::qualify_tuple_expression(
1948 *default, qualifier,
1949 )));
1950 }
1951 Expression::Cast(cast)
1952 }
1953 Expression::TryCast(mut cast) => {
1954 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
1955 Expression::TryCast(cast)
1956 }
1957 Expression::SafeCast(mut cast) => {
1958 cast.this = Self::qualify_tuple_expression(cast.this, qualifier);
1959 Expression::SafeCast(cast)
1960 }
1961 Expression::Function(mut function) => {
1962 function.args = function
1963 .args
1964 .into_iter()
1965 .map(|arg| Self::qualify_tuple_expression(arg, qualifier))
1966 .collect();
1967 Expression::Function(function)
1968 }
1969 Expression::Add(mut op) => {
1970 op.left = Self::qualify_tuple_expression(op.left, qualifier);
1971 op.right = Self::qualify_tuple_expression(op.right, qualifier);
1972 Expression::Add(op)
1973 }
1974 Expression::Sub(mut op) => {
1975 op.left = Self::qualify_tuple_expression(op.left, qualifier);
1976 op.right = Self::qualify_tuple_expression(op.right, qualifier);
1977 Expression::Sub(op)
1978 }
1979 Expression::Mul(mut op) => {
1980 op.left = Self::qualify_tuple_expression(op.left, qualifier);
1981 op.right = Self::qualify_tuple_expression(op.right, qualifier);
1982 Expression::Mul(op)
1983 }
1984 Expression::Div(mut op) => {
1985 op.left = Self::qualify_tuple_expression(op.left, qualifier);
1986 op.right = Self::qualify_tuple_expression(op.right, qualifier);
1987 Expression::Div(op)
1988 }
1989 Expression::Mod(mut op) => {
1990 op.left = Self::qualify_tuple_expression(op.left, qualifier);
1991 op.right = Self::qualify_tuple_expression(op.right, qualifier);
1992 Expression::Mod(op)
1993 }
1994 other => other,
1995 }
1996 }
1997
1998 fn tuple_component_may_match(inner: Expression, outer: Expression) -> Expression {
1999 Self::paren(
2000 Self::or_all(vec![
2001 Expression::Eq(Box::new(BinaryOp::new(inner.clone(), outer.clone()))),
2002 Self::is_null(inner),
2003 Self::is_null(outer),
2004 ])
2005 .expect("tuple component match condition is non-empty"),
2006 )
2007 }
2008
2009 fn column_from_identifier(identifier: Identifier, table: Option<Identifier>) -> Expression {
2010 Expression::Column(Box::new(Column {
2011 name: identifier,
2012 table,
2013 join_mark: false,
2014 trailing_comments: Vec::new(),
2015 span: None,
2016 inferred_type: None,
2017 }))
2018 }
2019
2020 fn single_select_source_qualifier(select: &Select) -> Option<Identifier> {
2021 if !select.joins.is_empty() {
2022 return None;
2023 }
2024
2025 let from = select.from.as_ref()?;
2026 if from.expressions.len() != 1 {
2027 return None;
2028 }
2029
2030 Self::source_qualifier(&from.expressions[0])
2031 }
2032
2033 fn source_qualifier(source: &Expression) -> Option<Identifier> {
2034 match source {
2035 Expression::Table(table) => table.alias.clone().or_else(|| Some(table.name.clone())),
2036 Expression::Subquery(subquery) => subquery.alias.clone(),
2037 _ => None,
2038 }
2039 }
2040
2041 fn and_all(mut predicates: Vec<Expression>) -> Option<Expression> {
2042 if predicates.is_empty() {
2043 return None;
2044 }
2045
2046 let first = predicates.remove(0);
2047 Some(predicates.into_iter().fold(first, |left, right| {
2048 Expression::And(Box::new(BinaryOp::new(left, right)))
2049 }))
2050 }
2051
2052 fn or_all(mut predicates: Vec<Expression>) -> Option<Expression> {
2053 if predicates.is_empty() {
2054 return None;
2055 }
2056
2057 let first = predicates.remove(0);
2058 Some(predicates.into_iter().fold(first, |left, right| {
2059 Expression::Or(Box::new(BinaryOp::new(left, right)))
2060 }))
2061 }
2062
2063 pub(super) fn transform_data_type(
2065 &self,
2066 dt: crate::expressions::DataType,
2067 ) -> Result<Expression> {
2068 use crate::expressions::DataType;
2069 let transformed = match dt {
2070 DataType::Boolean => DataType::Custom {
2072 name: "BIT".to_string(),
2073 },
2074 DataType::Int { .. } => dt,
2076 DataType::Decimal { precision, scale } => DataType::Custom {
2079 name: if let (Some(p), Some(s)) = (&precision, &scale) {
2080 format!("NUMERIC({}, {})", p, s)
2081 } else if let Some(p) = &precision {
2082 format!("NUMERIC({})", p)
2083 } else {
2084 "NUMERIC".to_string()
2085 },
2086 },
2087 DataType::Text => DataType::Custom {
2089 name: "VARCHAR(MAX)".to_string(),
2090 },
2091 DataType::Timestamp { .. } => DataType::Custom {
2093 name: "DATETIME2".to_string(),
2094 },
2095 DataType::Uuid => DataType::Custom {
2097 name: "UNIQUEIDENTIFIER".to_string(),
2098 },
2099 DataType::Custom { ref name } => {
2101 let upper = name.trim().to_uppercase();
2102 let (base_name, precision, _scale) = Self::parse_type_precision_and_scale(&upper);
2103 match base_name.as_str() {
2104 "DOUBLE PRECISION" => DataType::Custom {
2106 name: "FLOAT".to_string(),
2107 },
2108 "BPCHAR" => {
2110 if let Some(len) = precision {
2111 DataType::Char { length: Some(len) }
2112 } else {
2113 DataType::Char { length: None }
2114 }
2115 }
2116 _ => dt,
2117 }
2118 }
2119 other => other,
2121 };
2122 Ok(Expression::DataType(transformed))
2123 }
2124
2125 pub(super) fn parse_type_precision_and_scale(name: &str) -> (String, Option<u32>, Option<u32>) {
2127 if let Some(paren_pos) = name.find('(') {
2128 let base = name[..paren_pos].to_string();
2129 let rest = &name[paren_pos + 1..];
2130 if let Some(close_pos) = rest.find(')') {
2131 let args = &rest[..close_pos];
2132 let parts: Vec<&str> = args.split(',').map(|s| s.trim()).collect();
2133 let precision = parts.first().and_then(|s| s.parse::<u32>().ok());
2134 let scale = parts.get(1).and_then(|s| s.parse::<u32>().ok());
2135 return (base, precision, scale);
2136 }
2137 (base, None, None)
2138 } else {
2139 (name.to_string(), None, None)
2140 }
2141 }
2142
2143 fn transform_logical_aggregate(
2144 condition: Expression,
2145 filter: Option<Expression>,
2146 aggregate_name: &str,
2147 ) -> Result<Expression> {
2148 let false_condition = Expression::Not(Box::new(crate::expressions::UnaryOp {
2149 this: condition.clone(),
2150 inferred_type: None,
2151 }));
2152 let true_condition = Self::apply_aggregate_filter(condition, filter.clone());
2153 let false_condition = Self::apply_aggregate_filter(false_condition, filter);
2154
2155 let case_expr = Expression::Case(Box::new(crate::expressions::Case {
2156 operand: None,
2157 whens: vec![
2158 (true_condition, Expression::number(1)),
2159 (false_condition, Expression::number(0)),
2160 ],
2161 else_: Some(Expression::null()),
2162 comments: Vec::new(),
2163 inferred_type: None,
2164 }));
2165
2166 let case_expr = crate::transforms::ensure_bools(case_expr)?;
2167 let aggregate = Expression::Function(Box::new(Function::new(
2168 aggregate_name.to_string(),
2169 vec![case_expr],
2170 )));
2171
2172 Ok(Expression::Cast(Box::new(Cast {
2173 this: aggregate,
2174 to: DataType::Custom {
2175 name: "BIT".to_string(),
2176 },
2177 trailing_comments: Vec::new(),
2178 double_colon_syntax: false,
2179 format: None,
2180 default: None,
2181 inferred_type: None,
2182 })))
2183 }
2184
2185 fn apply_aggregate_filter(condition: Expression, filter: Option<Expression>) -> Expression {
2186 match filter {
2187 Some(filter) => Expression::And(Box::new(crate::expressions::BinaryOp::new(
2188 filter, condition,
2189 ))),
2190 None => condition,
2191 }
2192 }
2193
2194 fn transform_function(&self, f: Function) -> Result<Expression> {
2195 let name_upper = f.name.to_uppercase();
2196 match name_upper.as_str() {
2197 "COALESCE" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2199 "ISNULL".to_string(),
2200 f.args,
2201 )))),
2202
2203 "NVL" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2205 "ISNULL".to_string(),
2206 f.args,
2207 )))),
2208
2209 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
2211 Function::new("STRING_AGG".to_string(), f.args),
2212 ))),
2213
2214 "STRING_AGG" => Ok(Expression::Function(Box::new(f))),
2216
2217 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
2219 "STRING_AGG".to_string(),
2220 f.args,
2221 )))),
2222
2223 "SUBSTR" => Ok(Expression::Function(Box::new(Function::new(
2225 "SUBSTRING".to_string(),
2226 f.args,
2227 )))),
2228
2229 "LENGTH" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2231 "LEN".to_string(),
2232 f.args,
2233 )))),
2234
2235 "BTRIM" if f.args.len() == 1 || f.args.len() == 2 => {
2237 let mut args = f.args;
2238 let this = args.remove(0);
2239 let characters = if args.is_empty() {
2240 None
2241 } else {
2242 Some(args.remove(0))
2243 };
2244 Ok(Expression::Trim(Box::new(TrimFunc {
2245 this,
2246 sql_standard_syntax: characters.is_some(),
2247 characters,
2248 position: TrimPosition::Both,
2249 position_explicit: false,
2250 })))
2251 }
2252
2253 "MD5" if f.args.len() == 1 => {
2255 let mut args = f.args;
2256 Ok(Self::tsql_md5_hex(args.remove(0)))
2257 }
2258
2259 "OCTET_LENGTH" if f.args.len() == 1 => Ok(Self::function("DATALENGTH", f.args)),
2261
2262 "BIT_LENGTH" if f.args.len() == 1 => {
2264 let mut args = f.args;
2265 Ok(Expression::Mul(Box::new(BinaryOp::new(
2266 Self::function("DATALENGTH", vec![args.remove(0)]),
2267 Expression::number(8),
2268 ))))
2269 }
2270
2271 "TO_HEX" if f.args.len() == 1 => {
2275 let mut args = f.args;
2276 Ok(Self::tsql_hex_from_varbinary(args.remove(0)))
2277 }
2278
2279 "ENCODE" if f.args.len() == 2 => {
2281 let mut args = f.args;
2282 let this = args.remove(0);
2283 let encoding = args.remove(0);
2284 if Self::literal_string(&encoding)
2285 .is_some_and(|encoding| encoding.eq_ignore_ascii_case("hex"))
2286 {
2287 Ok(Self::tsql_hex_from_varbinary(this))
2288 } else {
2289 Ok(Expression::Function(Box::new(Function::new(
2290 "ENCODE".to_string(),
2291 vec![this, encoding],
2292 ))))
2293 }
2294 }
2295
2296 "REPEAT" if f.args.len() == 2 => Ok(Expression::Function(Box::new(Function::new(
2298 "REPLICATE".to_string(),
2299 f.args,
2300 )))),
2301
2302 "CHR" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2304 "CHAR".to_string(),
2305 f.args,
2306 )))),
2307
2308 "RANDOM" => Ok(Expression::Rand(Box::new(crate::expressions::Rand {
2310 seed: None,
2311 lower: None,
2312 upper: None,
2313 }))),
2314
2315 "NOW" => Ok(Self::getdate()),
2317
2318 "CURRENT_TIMESTAMP" => Ok(Self::getdate()),
2320
2321 "CURRENT_DATE" => Ok(Self::cast_getdate_to(DataType::Date)),
2323
2324 "CURRENT_TIME" => Ok(Self::cast_getdate_to(DataType::Time {
2326 precision: None,
2327 timezone: false,
2328 })),
2329
2330 "LOCALTIMESTAMP" => Ok(Self::getdate()),
2332
2333 "CLOCK_TIMESTAMP" if f.args.is_empty() => Ok(Self::function("SYSDATETIME", vec![])),
2335
2336 "MAKE_DATE" if f.args.len() == 3 => Ok(Self::function("DATEFROMPARTS", f.args)),
2338
2339 "TO_DATE" if f.args.len() == 2 => {
2343 Self::formatted_str_to_date_or_fallback(f.args, "TO_DATE")
2344 }
2345
2346 "TO_DATE" if f.args.len() == 1 => {
2348 let mut args = f.args;
2349 Ok(Expression::Cast(Box::new(Cast {
2350 this: args.remove(0),
2351 to: DataType::Date,
2352 trailing_comments: Vec::new(),
2353 double_colon_syntax: false,
2354 format: None,
2355 default: None,
2356 inferred_type: None,
2357 })))
2358 }
2359
2360 "TO_TIMESTAMP" if f.args.len() == 2 => {
2363 Self::formatted_str_to_time_or_fallback(f.args, "TO_TIMESTAMP")
2364 }
2365
2366 "TO_TIMESTAMP" if f.args.len() == 1 => {
2368 let mut args = f.args;
2369 Ok(Expression::UnixToTime(Box::new(
2370 crate::expressions::UnixToTime {
2371 this: Box::new(args.remove(0)),
2372 scale: Some(0),
2373 zone: None,
2374 hours: None,
2375 minutes: None,
2376 format: None,
2377 target_type: None,
2378 },
2379 )))
2380 }
2381
2382 "TO_CHAR" if f.args.len() == 2 => {
2385 Self::formatted_time_to_str_or_fallback(f.args, "TO_CHAR")
2386 }
2387
2388 "TO_CHAR" => Ok(Expression::Function(Box::new(Function::new(
2390 "FORMAT".to_string(),
2391 f.args,
2392 )))),
2393
2394 "DATE_FORMAT" => Ok(Expression::Function(Box::new(Function::new(
2396 "FORMAT".to_string(),
2397 f.args,
2398 )))),
2399
2400 "DATE_TRUNC" | "DATETRUNC" => {
2403 let mut args = Self::uppercase_first_arg_if_identifier(f.args);
2404 if args.len() >= 2 {
2406 if let Expression::Literal(lit) = &args[1] {
2407 if let Literal::String(_) = lit.as_ref() {
2408 args[1] = Expression::Cast(Box::new(Cast {
2409 this: args[1].clone(),
2410 to: DataType::Custom {
2411 name: "DATETIME2".to_string(),
2412 },
2413 trailing_comments: Vec::new(),
2414 double_colon_syntax: false,
2415 format: None,
2416 default: None,
2417 inferred_type: None,
2418 }));
2419 }
2420 }
2421 }
2422 Ok(Expression::Function(Box::new(Function::new(
2423 "DATETRUNC".to_string(),
2424 args,
2425 ))))
2426 }
2427
2428 "DATEADD" => {
2430 let args = Self::uppercase_first_arg_if_identifier(f.args);
2431 Ok(Expression::Function(Box::new(Function::new(
2432 "DATEADD".to_string(),
2433 args,
2434 ))))
2435 }
2436
2437 "DATEDIFF" => {
2439 let args = Self::uppercase_first_arg_if_identifier(f.args);
2440 Ok(Expression::Function(Box::new(Function::new(
2441 "DATEDIFF".to_string(),
2442 args,
2443 ))))
2444 }
2445
2446 "EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2448 "DATEPART".to_string(),
2449 f.args,
2450 )))),
2451
2452 "STRPOS" | "POSITION" if f.args.len() >= 2 => {
2454 Ok(Expression::Function(Box::new(Function::new(
2456 "CHARINDEX".to_string(),
2457 f.args,
2458 ))))
2459 }
2460
2461 "CHARINDEX" => Ok(Expression::Function(Box::new(f))),
2463
2464 "CEILING" | "CEIL" if f.args.len() == 1 => Ok(Expression::Function(Box::new(
2466 Function::new("CEILING".to_string(), f.args),
2467 ))),
2468
2469 "JSON_EXTRACT" => Ok(Expression::Function(Box::new(Function::new(
2474 "JSON_VALUE".to_string(),
2475 f.args,
2476 )))),
2477
2478 "JSON_EXTRACT_SCALAR" => Ok(Expression::Function(Box::new(Function::new(
2480 "JSON_VALUE".to_string(),
2481 f.args,
2482 )))),
2483
2484 "PARSE_JSON" if f.args.len() == 1 => Ok(f.args.into_iter().next().unwrap()),
2486
2487 "GET_PATH" if f.args.len() == 2 => {
2489 let mut args = f.args;
2490 let this = args.remove(0);
2491 let path = args.remove(0);
2492 let json_path = match &path {
2493 Expression::Literal(lit) if matches!(lit.as_ref(), Literal::String(_)) => {
2494 let Literal::String(s) = lit.as_ref() else {
2495 unreachable!()
2496 };
2497 let normalized = if s.starts_with('$') {
2498 s.clone()
2499 } else if s.starts_with('[') {
2500 format!("${}", s)
2501 } else {
2502 format!("$.{}", s)
2503 };
2504 Expression::Literal(Box::new(Literal::String(normalized)))
2505 }
2506 _ => path,
2507 };
2508 let json_query = Expression::Function(Box::new(Function::new(
2510 "JSON_QUERY".to_string(),
2511 vec![this.clone(), json_path.clone()],
2512 )));
2513 let json_value = Expression::Function(Box::new(Function::new(
2514 "JSON_VALUE".to_string(),
2515 vec![this, json_path],
2516 )));
2517 Ok(Expression::Function(Box::new(Function::new(
2518 "ISNULL".to_string(),
2519 vec![json_query, json_value],
2520 ))))
2521 }
2522
2523 "JSON_QUERY" if f.args.len() == 1 => {
2526 let this = f.args.into_iter().next().unwrap();
2527 let path = Expression::Literal(Box::new(Literal::String("$".to_string())));
2528 let json_query = Expression::Function(Box::new(Function::new(
2529 "JSON_QUERY".to_string(),
2530 vec![this.clone(), path.clone()],
2531 )));
2532 let json_value = Expression::Function(Box::new(Function::new(
2533 "JSON_VALUE".to_string(),
2534 vec![this, path],
2535 )));
2536 Ok(Expression::Function(Box::new(Function::new(
2537 "ISNULL".to_string(),
2538 vec![json_query, json_value],
2539 ))))
2540 }
2541
2542 "SPLIT" => Ok(Expression::Function(Box::new(Function::new(
2544 "STRING_SPLIT".to_string(),
2545 f.args,
2546 )))),
2547
2548 "REGEXP_LIKE" => {
2551 Ok(Expression::Function(Box::new(Function::new(
2553 "PATINDEX".to_string(),
2554 f.args,
2555 ))))
2556 }
2557
2558 "LN" if f.args.len() == 1 => Ok(Expression::Function(Box::new(Function::new(
2560 "LOG".to_string(),
2561 f.args,
2562 )))),
2563
2564 "STDDEV" | "STDDEV_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2569 "STDEV".to_string(),
2570 f.args,
2571 )))),
2572
2573 "STDDEV_POP" => Ok(Expression::Function(Box::new(Function::new(
2575 "STDEVP".to_string(),
2576 f.args,
2577 )))),
2578
2579 "VARIANCE" | "VAR_SAMP" => Ok(Expression::Function(Box::new(Function::new(
2581 "VAR".to_string(),
2582 f.args,
2583 )))),
2584
2585 "VAR_POP" => Ok(Expression::Function(Box::new(Function::new(
2587 "VARP".to_string(),
2588 f.args,
2589 )))),
2590
2591 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" | "EVERY" if f.args.len() == 1 => {
2593 let mut args = f.args;
2594 Self::transform_logical_aggregate(args.remove(0), None, "MIN")
2595 }
2596 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if f.args.len() == 1 => {
2597 let mut args = f.args;
2598 Self::transform_logical_aggregate(args.remove(0), None, "MAX")
2599 }
2600
2601 "DATE_ADD" => {
2603 if f.args.len() == 2 {
2604 let mut args = f.args;
2605 let date = args.remove(0);
2606 let interval = args.remove(0);
2607 let unit = Expression::Identifier(crate::expressions::Identifier {
2608 name: "DAY".to_string(),
2609 quoted: false,
2610 trailing_comments: Vec::new(),
2611 span: None,
2612 });
2613 Ok(Expression::Function(Box::new(Function::new(
2614 "DATEADD".to_string(),
2615 vec![unit, interval, date],
2616 ))))
2617 } else {
2618 let args = Self::uppercase_first_arg_if_identifier(f.args);
2619 Ok(Expression::Function(Box::new(Function::new(
2620 "DATEADD".to_string(),
2621 args,
2622 ))))
2623 }
2624 }
2625
2626 "INSERT" => Ok(Expression::Function(Box::new(Function::new(
2628 "STUFF".to_string(),
2629 f.args,
2630 )))),
2631
2632 "SUSER_NAME" | "SUSER_SNAME" | "SYSTEM_USER" => Ok(Expression::CurrentUser(Box::new(
2634 crate::expressions::CurrentUser { this: None },
2635 ))),
2636
2637 _ => Ok(Expression::Function(Box::new(f))),
2639 }
2640 }
2641
2642 fn literal_string(expr: &Expression) -> Option<&str> {
2643 match expr {
2644 Expression::Literal(lit) => match lit.as_ref() {
2645 Literal::String(s) => Some(s),
2646 _ => None,
2647 },
2648 _ => None,
2649 }
2650 }
2651
2652 fn postgres_format_to_strftime(format: &str) -> String {
2653 const POSTGRES_FORMAT_TO_STRFTIME: &[(&str, &str)] = &[
2654 ("FMHH24", "%-H"),
2655 ("FMHH12", "%-I"),
2656 ("FMDDD", "%-j"),
2657 ("TMMonth", "%B"),
2658 ("TMMon", "%b"),
2659 ("TMDay", "%A"),
2660 ("TMDy", "%a"),
2661 ("YYYY", "%Y"),
2662 ("yyyy", "%Y"),
2663 ("HH24", "%H"),
2664 ("HH12", "%I"),
2665 ("FMDD", "%-d"),
2666 ("FMMM", "%-m"),
2667 ("FMMI", "%-M"),
2668 ("FMSS", "%-S"),
2669 ("DDD", "%j"),
2670 ("ddd", "%j"),
2671 ("YY", "%y"),
2672 ("yy", "%y"),
2673 ("MM", "%m"),
2674 ("mm", "%m"),
2675 ("DD", "%d"),
2676 ("dd", "%d"),
2677 ("MI", "%M"),
2678 ("mi", "%M"),
2679 ("SS", "%S"),
2680 ("ss", "%S"),
2681 ("US", "%f"),
2682 ("OF", "%z"),
2683 ("TZ", "%Z"),
2684 ("WW", "%U"),
2685 ("ww", "%U"),
2686 ("D", "%u"),
2687 ("d", "%u"),
2688 ];
2689 crate::format_tokens::convert_format_tokens(format, POSTGRES_FORMAT_TO_STRFTIME)
2690 .unwrap_or_else(|| format.to_string())
2691 }
2692
2693 fn formatted_str_to_time_or_fallback(
2694 mut args: Vec<Expression>,
2695 original_name: &str,
2696 ) -> Result<Expression> {
2697 let this = args.remove(0);
2698 let format = args.remove(0);
2699 if let Some(format) = Self::literal_string(&format) {
2700 Ok(Expression::StrToTime(Box::new(
2701 crate::expressions::StrToTime {
2702 this: Box::new(this),
2703 format: Self::postgres_format_to_strftime(format),
2704 zone: None,
2705 safe: None,
2706 target_type: Some(Box::new(Expression::DataType(DataType::Custom {
2707 name: "DATETIME2".to_string(),
2708 }))),
2709 },
2710 )))
2711 } else {
2712 Ok(Expression::Function(Box::new(Function::new(
2713 original_name.to_string(),
2714 vec![this, format],
2715 ))))
2716 }
2717 }
2718
2719 fn formatted_str_to_date_or_fallback(
2720 mut args: Vec<Expression>,
2721 original_name: &str,
2722 ) -> Result<Expression> {
2723 let this = args.remove(0);
2724 let format = args.remove(0);
2725 if let Some(format) = Self::literal_string(&format) {
2726 Ok(Expression::StrToDate(Box::new(
2727 crate::expressions::StrToDate {
2728 this: Box::new(this),
2729 format: Some(Self::postgres_format_to_strftime(format)),
2730 safe: None,
2731 },
2732 )))
2733 } else {
2734 Ok(Expression::Function(Box::new(Function::new(
2735 original_name.to_string(),
2736 vec![this, format],
2737 ))))
2738 }
2739 }
2740
2741 fn formatted_time_to_str_or_fallback(
2742 mut args: Vec<Expression>,
2743 original_name: &str,
2744 ) -> Result<Expression> {
2745 let this = args.remove(0);
2746 let format = args.remove(0);
2747 if let Some(format) = Self::literal_string(&format) {
2748 Ok(Expression::TimeToStr(Box::new(
2749 crate::expressions::TimeToStr {
2750 this: Box::new(this),
2751 format: Self::postgres_format_to_strftime(format),
2752 culture: None,
2753 zone: None,
2754 },
2755 )))
2756 } else {
2757 Ok(Expression::Function(Box::new(Function::new(
2758 original_name.to_string(),
2759 vec![this, format],
2760 ))))
2761 }
2762 }
2763
2764 fn transform_aggregate_function(
2765 &self,
2766 f: Box<crate::expressions::AggregateFunction>,
2767 ) -> Result<Expression> {
2768 let name_upper = f.name.to_uppercase();
2769 match name_upper.as_str() {
2770 "GROUP_CONCAT" if !f.args.is_empty() => Ok(Expression::Function(Box::new(
2772 Function::new("STRING_AGG".to_string(), f.args),
2773 ))),
2774
2775 "LISTAGG" if !f.args.is_empty() => Ok(Expression::Function(Box::new(Function::new(
2777 "STRING_AGG".to_string(),
2778 f.args,
2779 )))),
2780
2781 "ARRAY_AGG" if !f.args.is_empty() => {
2784 Ok(Expression::Function(Box::new(Function::new(
2786 "STRING_AGG".to_string(),
2787 f.args,
2788 ))))
2789 }
2790
2791 "BOOL_AND" | "LOGICAL_AND" | "BOOLAND_AGG" | "EVERY" if f.args.len() == 1 => {
2793 let mut args = f.args;
2794 Self::transform_logical_aggregate(args.remove(0), f.filter, "MIN")
2795 }
2796 "BOOL_OR" | "LOGICAL_OR" | "BOOLOR_AGG" if f.args.len() == 1 => {
2797 let mut args = f.args;
2798 Self::transform_logical_aggregate(args.remove(0), f.filter, "MAX")
2799 }
2800
2801 _ => Ok(Expression::AggregateFunction(f)),
2803 }
2804 }
2805
2806 fn transform_cte(&self, cte: Cte) -> Result<Expression> {
2810 Ok(Expression::Cte(Box::new(self.transform_cte_inner(cte))))
2811 }
2812
2813 fn transform_cte_inner(&self, mut cte: Cte) -> Cte {
2815 if cte.columns.is_empty() {
2818 cte.this = self.qualify_derived_table_outputs(cte.this);
2819 }
2820 cte
2821 }
2822
2823 fn transform_subquery(&self, mut subquery: Subquery) -> Result<Expression> {
2827 if subquery.alias.is_some() && subquery.column_aliases.is_empty() {
2830 subquery.this = self.qualify_derived_table_outputs(subquery.this);
2831 }
2832 Ok(Expression::Subquery(Box::new(subquery)))
2833 }
2834
2835 fn qualify_derived_table_outputs(&self, expr: Expression) -> Expression {
2839 match expr {
2840 Expression::Select(mut select) => {
2841 let has_from = select.from.is_some();
2844 if !has_from {
2845 select.expressions = select
2846 .expressions
2847 .into_iter()
2848 .map(|e| self.maybe_alias_expression(e))
2849 .collect();
2850 }
2851 Expression::Select(select)
2852 }
2853 Expression::Union(mut u) => {
2855 let left = std::mem::replace(&mut u.left, Expression::Null(Null));
2856 u.left = self.qualify_derived_table_outputs(left);
2857 Expression::Union(u)
2858 }
2859 Expression::Intersect(mut i) => {
2860 let left = std::mem::replace(&mut i.left, Expression::Null(Null));
2861 i.left = self.qualify_derived_table_outputs(left);
2862 Expression::Intersect(i)
2863 }
2864 Expression::Except(mut e) => {
2865 let left = std::mem::replace(&mut e.left, Expression::Null(Null));
2866 e.left = self.qualify_derived_table_outputs(left);
2867 Expression::Except(e)
2868 }
2869 Expression::Subquery(mut s) => {
2871 s.this = self.qualify_derived_table_outputs(s.this);
2872 Expression::Subquery(s)
2873 }
2874 other => other,
2876 }
2877 }
2878
2879 fn maybe_alias_expression(&self, expr: Expression) -> Expression {
2884 match &expr {
2885 Expression::Alias(_) => expr,
2887 Expression::Aliases(_) => expr,
2889 Expression::Star(_) => expr,
2891 _ => {
2896 if let Some(output_name) = self.get_output_name(&expr) {
2897 Expression::Alias(Box::new(Alias {
2898 this: expr,
2899 alias: Identifier {
2900 name: output_name,
2901 quoted: true, trailing_comments: Vec::new(),
2903 span: None,
2904 },
2905 column_aliases: Vec::new(),
2906 alias_explicit_as: false,
2907 alias_keyword: None,
2908 pre_alias_comments: Vec::new(),
2909 trailing_comments: Vec::new(),
2910 inferred_type: None,
2911 }))
2912 } else {
2913 expr
2915 }
2916 }
2917 }
2918 }
2919
2920 fn get_output_name(&self, expr: &Expression) -> Option<String> {
2924 match expr {
2925 Expression::Literal(lit) => match lit.as_ref() {
2927 Literal::Number(n) => Some(n.clone()),
2928 Literal::String(s) => Some(s.clone()),
2929 Literal::HexString(h) => Some(format!("0x{}", h)),
2930 Literal::HexNumber(h) => Some(format!("0x{}", h)),
2931 Literal::BitString(b) => Some(format!("b{}", b)),
2932 Literal::ByteString(b) => Some(format!("b'{}'", b)),
2933 Literal::NationalString(s) => Some(format!("N'{}'", s)),
2934 Literal::Date(d) => Some(d.clone()),
2935 Literal::Time(t) => Some(t.clone()),
2936 Literal::Timestamp(ts) => Some(ts.clone()),
2937 Literal::Datetime(dt) => Some(dt.clone()),
2938 Literal::TripleQuotedString(s, _) => Some(s.clone()),
2939 Literal::EscapeString(s) => Some(s.clone()),
2940 Literal::DollarString(s) => Some(s.clone()),
2941 Literal::RawString(s) => Some(s.clone()),
2942 },
2943 Expression::Column(col) => Some(col.name.name.clone()),
2945 Expression::Identifier(ident) => Some(ident.name.clone()),
2947 Expression::Boolean(b) => Some(if b.value { "1" } else { "0" }.to_string()),
2949 Expression::Null(_) => Some("NULL".to_string()),
2951 Expression::Function(f) => Some(f.name.clone()),
2953 Expression::AggregateFunction(f) => Some(f.name.clone()),
2955 _ => Some(format!("_col_{}", 0)),
2957 }
2958 }
2959
2960 fn uppercase_first_arg_if_identifier(mut args: Vec<Expression>) -> Vec<Expression> {
2962 use crate::expressions::Identifier;
2963 if !args.is_empty() {
2964 match &args[0] {
2965 Expression::Identifier(id) => {
2966 args[0] = Expression::Identifier(Identifier {
2967 name: id.name.to_uppercase(),
2968 quoted: id.quoted,
2969 trailing_comments: id.trailing_comments.clone(),
2970 span: None,
2971 });
2972 }
2973 Expression::Var(v) => {
2974 args[0] = Expression::Identifier(Identifier {
2975 name: v.this.to_uppercase(),
2976 quoted: false,
2977 trailing_comments: Vec::new(),
2978 span: None,
2979 });
2980 }
2981 Expression::Column(col) if col.table.is_none() => {
2982 args[0] = Expression::Identifier(Identifier {
2983 name: col.name.name.to_uppercase(),
2984 quoted: col.name.quoted,
2985 trailing_comments: col.name.trailing_comments.clone(),
2986 span: None,
2987 });
2988 }
2989 _ => {}
2990 }
2991 }
2992 args
2993 }
2994}
2995
2996#[cfg(test)]
2997mod tests {
2998 use super::*;
2999 use crate::dialects::Dialect;
3000
3001 fn transpile_to_tsql(sql: &str) -> String {
3002 let dialect = Dialect::get(DialectType::Generic);
3003 let result = dialect
3004 .transpile(sql, DialectType::TSQL)
3005 .expect("Transpile failed");
3006 result[0].clone()
3007 }
3008
3009 #[test]
3010 fn test_nvl_to_isnull() {
3011 let result = transpile_to_tsql("SELECT NVL(a, b)");
3012 assert!(
3013 result.contains("ISNULL"),
3014 "Expected ISNULL, got: {}",
3015 result
3016 );
3017 }
3018
3019 #[test]
3020 fn test_coalesce_to_isnull() {
3021 let result = transpile_to_tsql("SELECT COALESCE(a, b)");
3022 assert!(
3023 result.contains("ISNULL"),
3024 "Expected ISNULL, got: {}",
3025 result
3026 );
3027 }
3028
3029 #[test]
3030 fn test_basic_select() {
3031 let result = transpile_to_tsql("SELECT a, b FROM users WHERE id = 1");
3032 assert!(result.contains("SELECT"));
3033 assert!(result.contains("FROM users"));
3034 }
3035
3036 #[test]
3037 fn test_length_to_len() {
3038 let result = transpile_to_tsql("SELECT LENGTH(name)");
3039 assert!(result.contains("LEN"), "Expected LEN, got: {}", result);
3040 }
3041
3042 #[test]
3043 fn test_now_to_getdate() {
3044 let result = transpile_to_tsql("SELECT NOW()");
3045 assert!(
3046 result.contains("GETDATE"),
3047 "Expected GETDATE, got: {}",
3048 result
3049 );
3050 }
3051
3052 #[test]
3053 fn test_group_concat_to_string_agg() {
3054 let result = transpile_to_tsql("SELECT GROUP_CONCAT(name)");
3055 assert!(
3056 result.contains("STRING_AGG"),
3057 "Expected STRING_AGG, got: {}",
3058 result
3059 );
3060 }
3061
3062 #[test]
3063 fn test_listagg_to_string_agg() {
3064 let result = transpile_to_tsql("SELECT LISTAGG(name)");
3065 assert!(
3066 result.contains("STRING_AGG"),
3067 "Expected STRING_AGG, got: {}",
3068 result
3069 );
3070 }
3071
3072 #[test]
3073 fn test_ln_to_log() {
3074 let result = transpile_to_tsql("SELECT LN(x)");
3075 assert!(result.contains("LOG"), "Expected LOG, got: {}", result);
3076 }
3077
3078 #[test]
3079 fn test_stddev_to_stdev() {
3080 let result = transpile_to_tsql("SELECT STDDEV(x)");
3081 assert!(result.contains("STDEV"), "Expected STDEV, got: {}", result);
3082 }
3083
3084 #[test]
3085 fn test_bracket_identifiers() {
3086 let dialect = Dialect::get(DialectType::TSQL);
3088 let config = dialect.generator_config();
3089 assert_eq!(config.identifier_quote, '[');
3090 }
3091
3092 #[test]
3093 fn test_json_query_isnull_wrapper_simple() {
3094 let dialect = Dialect::get(DialectType::TSQL);
3096 let result = dialect
3097 .transpile(r#"JSON_QUERY(x, '$')"#, DialectType::TSQL)
3098 .expect("transpile failed");
3099 assert!(
3100 result[0].contains("ISNULL"),
3101 "JSON_QUERY should be wrapped with ISNULL: {}",
3102 result[0]
3103 );
3104 }
3105
3106 #[test]
3107 fn test_json_query_isnull_wrapper_nested() {
3108 let dialect = Dialect::get(DialectType::TSQL);
3109 let result = dialect
3110 .transpile(
3111 r#"JSON_QUERY(REPLACE(REPLACE(x, '''', '"'), '""', '"'))"#,
3112 DialectType::TSQL,
3113 )
3114 .expect("transpile failed");
3115 let expected = r#"ISNULL(JSON_QUERY(REPLACE(REPLACE(x, '''', '"'), '""', '"'), '$'), JSON_VALUE(REPLACE(REPLACE(x, '''', '"'), '""', '"'), '$'))"#;
3116 assert_eq!(
3117 result[0], expected,
3118 "JSON_QUERY should be wrapped with ISNULL"
3119 );
3120 }
3121}