diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-09-25 08:20:09 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2023-09-25 08:20:09 +0000 |
commit | 4554ab4c7d6b2bbbaa6f4d0b810bf477d1a505a6 (patch) | |
tree | 8f4f60a82ab9cd6dcd41397e4ecb2960c332b209 /sqlglot/dialects/tsql.py | |
parent | Releasing debian version 18.5.1-1. (diff) | |
download | sqlglot-4554ab4c7d6b2bbbaa6f4d0b810bf477d1a505a6.tar.xz sqlglot-4554ab4c7d6b2bbbaa6f4d0b810bf477d1a505a6.zip |
Merging upstream version 18.7.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sqlglot/dialects/tsql.py')
-rw-r--r-- | sqlglot/dialects/tsql.py | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py index 2299310..fa62e78 100644 --- a/sqlglot/dialects/tsql.py +++ b/sqlglot/dialects/tsql.py @@ -10,6 +10,7 @@ from sqlglot.dialects.dialect import ( any_value_to_max_sql, max_or_greatest, min_or_least, + move_insert_cte_sql, parse_date_delta, rename_func, timestrtotime_sql, @@ -206,6 +207,8 @@ class TSQL(Dialect): RESOLVES_IDENTIFIERS_AS_UPPERCASE = None NULL_ORDERING = "nulls_are_small" TIME_FORMAT = "'yyyy-mm-dd hh:mm:ss'" + SUPPORTS_SEMI_ANTI_JOIN = False + LOG_BASE_FIRST = False TIME_MAPPING = { "year": "%Y", @@ -345,6 +348,8 @@ class TSQL(Dialect): } class Parser(parser.Parser): + SET_REQUIRES_ASSIGNMENT_DELIMITER = False + FUNCTIONS = { **parser.Parser.FUNCTIONS, "CHARINDEX": lambda args: exp.StrPosition( @@ -396,7 +401,6 @@ class TSQL(Dialect): TokenType.END: lambda self: self._parse_command(), } - LOG_BASE_FIRST = False LOG_DEFAULTS_TO_LN = True CONCAT_NULL_OUTPUTS_STRING = True @@ -609,11 +613,14 @@ class TSQL(Dialect): exp.Extract: rename_func("DATEPART"), exp.GroupConcat: _string_agg_sql, exp.If: rename_func("IIF"), + exp.Insert: move_insert_cte_sql, exp.Max: max_or_greatest, exp.MD5: lambda self, e: self.func("HASHBYTES", exp.Literal.string("MD5"), e.this), exp.Min: min_or_least, exp.NumberToStr: _format_sql, - exp.Select: transforms.preprocess([transforms.eliminate_distinct_on]), + exp.Select: transforms.preprocess( + [transforms.eliminate_distinct_on, transforms.eliminate_semi_and_anti_joins] + ), exp.SHA: lambda self, e: self.func("HASHBYTES", exp.Literal.string("SHA1"), e.this), exp.SHA2: lambda self, e: self.func( "HASHBYTES", @@ -632,6 +639,14 @@ class TSQL(Dialect): exp.VolatileProperty: exp.Properties.Location.UNSUPPORTED, } + def setitem_sql(self, expression: exp.SetItem) -> str: + this = expression.this + if isinstance(this, exp.EQ) and not isinstance(this.left, exp.Parameter): + # T-SQL does not use '=' in SET command, except when the LHS is a variable. + return f"{self.sql(this.left)} {self.sql(this.right)}" + + return super().setitem_sql(expression) + def boolean_sql(self, expression: exp.Boolean) -> str: if type(expression.parent) in BIT_TYPES: return "1" if expression.this else "0" @@ -661,16 +676,27 @@ class TSQL(Dialect): exists = expression.args.pop("exists", None) sql = super().create_sql(expression) + table = expression.find(exp.Table) + + if kind == "TABLE" and expression.expression: + sql = f"SELECT * INTO {self.sql(table)} FROM ({self.sql(expression.expression)}) AS temp" + if exists: - table = expression.find(exp.Table) identifier = self.sql(exp.Literal.string(exp.table_name(table) if table else "")) + sql = self.sql(exp.Literal.string(sql)) if kind == "SCHEMA": - sql = f"""IF NOT EXISTS (SELECT * FROM information_schema.schemata WHERE schema_name = {identifier}) EXEC('{sql}')""" + sql = f"""IF NOT EXISTS (SELECT * FROM information_schema.schemata WHERE schema_name = {identifier}) EXEC({sql})""" elif kind == "TABLE": - sql = f"""IF NOT EXISTS (SELECT * FROM information_schema.tables WHERE table_name = {identifier}) EXEC('{sql}')""" + assert table + where = exp.and_( + exp.column("table_name").eq(table.name), + exp.column("table_schema").eq(table.db) if table.db else None, + exp.column("table_catalog").eq(table.catalog) if table.catalog else None, + ) + sql = f"""IF NOT EXISTS (SELECT * FROM information_schema.tables WHERE {where}) EXEC({sql})""" elif kind == "INDEX": index = self.sql(exp.Literal.string(expression.this.text("this"))) - sql = f"""IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = object_id({identifier}) AND name = {index}) EXEC('{sql}')""" + sql = f"""IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = object_id({identifier}) AND name = {index}) EXEC({sql})""" elif expression.args.get("replace"): sql = sql.replace("CREATE OR REPLACE ", "CREATE OR ALTER ", 1) |