diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py index 71fb084457..f130f3e475 100644 --- a/sqlglot/dialects/tsql.py +++ b/sqlglot/dialects/tsql.py @@ -351,12 +351,13 @@ def _timestrtotime_sql(self: TSQL.Generator, expression: exp.TimeStrToTime): class TSQL(Dialect): - NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE - TIME_FORMAT = "'yyyy-mm-dd hh:mm:ss'" SUPPORTS_SEMI_ANTI_JOIN = False LOG_BASE_FIRST = False TYPED_DIVISION = True CONCAT_COALESCE = True + NORMALIZATION_STRATEGY = NormalizationStrategy.CASE_INSENSITIVE + + TIME_FORMAT = "'yyyy-mm-dd hh:mm:ss'" TIME_MAPPING = { "year": "%Y", diff --git a/sqlglot/generator.py b/sqlglot/generator.py index 7796d23907..2921d2bd25 100644 --- a/sqlglot/generator.py +++ b/sqlglot/generator.py @@ -2888,7 +2888,12 @@ def reference_sql(self, expression: exp.Reference) -> str: return f"REFERENCES {this}{expressions}{options}" def anonymous_sql(self, expression: exp.Anonymous) -> str: - return self.func(self.sql(expression, "this"), *expression.expressions) + # We don't normalize qualified functions such as a.b.foo(), because they can be case-sensitive + parent = expression.parent + is_qualified = isinstance(parent, exp.Dot) and expression is parent.expression + return self.func( + self.sql(expression, "this"), *expression.expressions, normalize=not is_qualified + ) def paren_sql(self, expression: exp.Paren) -> str: sql = self.seg(self.indent(self.sql(expression, "this")), sep="") @@ -3397,8 +3402,10 @@ def func( *args: t.Optional[exp.Expression | str], prefix: str = "(", suffix: str = ")", + normalize: bool = True, ) -> str: - return f"{self.normalize_func(name)}{prefix}{self.format_args(*args)}{suffix}" + name = self.normalize_func(name) if normalize else name + return f"{name}{prefix}{self.format_args(*args)}{suffix}" def format_args(self, *args: t.Optional[str | exp.Expression]) -> str: arg_sqls = tuple( diff --git a/tests/dialects/test_oracle.py b/tests/dialects/test_oracle.py index 60d584291c..922722d41e 100644 --- a/tests/dialects/test_oracle.py +++ b/tests/dialects/test_oracle.py @@ -362,7 +362,7 @@ def test_xml_table(self): FROM XMLTABLE( 'ROWSET/ROW' PASSING - dbms_xmlgen.GETXMLTYPE('SELECT table_name, column_name, data_default FROM user_tab_columns') + dbms_xmlgen.getxmltype('SELECT table_name, column_name, data_default FROM user_tab_columns') COLUMNS table_name VARCHAR2(128) PATH '*[1]', column_name VARCHAR2(128) PATH '*[2]', diff --git a/tests/dialects/test_tsql.py b/tests/dialects/test_tsql.py index ad189819e6..1da1a385e2 100644 --- a/tests/dialects/test_tsql.py +++ b/tests/dialects/test_tsql.py @@ -31,6 +31,9 @@ def test_tsql(self): self.validate_identity("1 AND true", "1 <> 0 AND (1 = 1)") self.validate_identity("CAST(x AS int) OR y", "CAST(x AS INTEGER) <> 0 OR y <> 0") self.validate_identity("TRUNCATE TABLE t1 WITH (PARTITIONS(1, 2 TO 5, 10 TO 20, 84))") + self.validate_identity( + "SELECT TOP 10 s.RECORDID, n.c.value('(/*:FORM_ROOT/*:SOME_TAG)[1]', 'float') AS SOME_TAG_VALUE FROM source_table.dbo.source_data AS s(nolock) CROSS APPLY FormContent.nodes('/*:FORM_ROOT') AS N(C)" + ) self.validate_identity( "CREATE CLUSTERED INDEX [IX_OfficeTagDetail_TagDetailID] ON [dbo].[OfficeTagDetail]([TagDetailID] ASC)" ) @@ -1577,8 +1580,8 @@ def test_lateral_table_valued_function(self): self.validate_all( "SELECT t.x, y.z FROM x OUTER APPLY a.b.tvfTest(t.x)y(z)", write={ - "spark": "SELECT t.x, y.z FROM x LEFT JOIN LATERAL a.b.TVFTEST(t.x) AS y(z)", - "tsql": "SELECT t.x, y.z FROM x OUTER APPLY a.b.TVFTEST(t.x) AS y(z)", + "spark": "SELECT t.x, y.z FROM x LEFT JOIN LATERAL a.b.tvfTest(t.x) AS y(z)", + "tsql": "SELECT t.x, y.z FROM x OUTER APPLY a.b.tvfTest(t.x) AS y(z)", }, )