diff options
Diffstat (limited to 'sqlglot/dialects')
-rw-r--r-- | sqlglot/dialects/__init__.py | 1 | ||||
-rw-r--r-- | sqlglot/dialects/dialect.py | 19 | ||||
-rw-r--r-- | sqlglot/dialects/duckdb.py | 2 | ||||
-rw-r--r-- | sqlglot/dialects/snowflake.py | 20 | ||||
-rw-r--r-- | sqlglot/dialects/spark.py | 1 | ||||
-rw-r--r-- | sqlglot/dialects/tsql.py | 38 |
6 files changed, 77 insertions, 4 deletions
diff --git a/sqlglot/dialects/__init__.py b/sqlglot/dialects/__init__.py index f7d03ad..0f80723 100644 --- a/sqlglot/dialects/__init__.py +++ b/sqlglot/dialects/__init__.py @@ -14,3 +14,4 @@ from sqlglot.dialects.sqlite import SQLite from sqlglot.dialects.starrocks import StarRocks from sqlglot.dialects.tableau import Tableau from sqlglot.dialects.trino import Trino +from sqlglot.dialects.tsql import TSQL diff --git a/sqlglot/dialects/dialect.py b/sqlglot/dialects/dialect.py index f338c81..0120e71 100644 --- a/sqlglot/dialects/dialect.py +++ b/sqlglot/dialects/dialect.py @@ -27,6 +27,7 @@ class Dialects(str, Enum): STARROCKS = "starrocks" TABLEAU = "tableau" TRINO = "trino" + TSQL = "tsql" class _Dialect(type): @@ -53,7 +54,6 @@ class _Dialect(type): klass.parser_class = getattr(klass, "Parser", Parser) klass.generator_class = getattr(klass, "Generator", Generator) - klass.tokenizer = klass.tokenizer_class() klass.quote_start, klass.quote_end = list(klass.tokenizer_class._QUOTES.items())[0] klass.identifier_start, klass.identifier_end = list(klass.tokenizer_class._IDENTIFIERS.items())[0] @@ -95,7 +95,6 @@ class Dialect(metaclass=_Dialect): tokenizer_class = None parser_class = None generator_class = None - tokenizer = None @classmethod def get_or_raise(cls, dialect): @@ -138,6 +137,12 @@ class Dialect(metaclass=_Dialect): def transpile(self, code, **opts): return self.generate(self.parse(code), **opts) + @property + def tokenizer(self): + if not hasattr(self, "_tokenizer"): + self._tokenizer = self.tokenizer_class() + return self._tokenizer + def parser(self, **opts): return self.parser_class( **{ @@ -170,7 +175,15 @@ class Dialect(metaclass=_Dialect): def rename_func(name): - return lambda self, expression: f"{name}({csv(*[self.sql(e) for e in expression.args.values()])})" + def _rename(self, expression): + args = ( + self.expressions(expression, flat=True) + if isinstance(expression, exp.Func) and expression.is_var_len_args + else csv(*[self.sql(e) for e in expression.args.values()]) + ) + return f"{name}({args})" + + return _rename def approx_count_distinct_sql(self, expression): diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py index ff3a8b1..4ca9e84 100644 --- a/sqlglot/dialects/duckdb.py +++ b/sqlglot/dialects/duckdb.py @@ -108,7 +108,7 @@ class DuckDB(Dialect): TRANSFORMS = { **Generator.TRANSFORMS, exp.ApproxDistinct: approx_count_distinct_sql, - exp.Array: lambda self, e: f"LIST_VALUE({self.expressions(e, flat=True)})", + exp.Array: rename_func("LIST_VALUE"), exp.ArraySize: rename_func("ARRAY_LENGTH"), exp.ArraySort: _array_sort_sql, exp.ArraySum: rename_func("LIST_SUM"), diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py index 8d6ee78..b5d4f0a 100644 --- a/sqlglot/dialects/snowflake.py +++ b/sqlglot/dialects/snowflake.py @@ -106,6 +106,11 @@ class Snowflake(Dialect): "TO_TIMESTAMP": _snowflake_to_timestamp, } + FUNCTION_PARSERS = { + **Parser.FUNCTION_PARSERS, + "DATE_PART": lambda self: self._parse_extract(), + } + COLUMN_OPERATORS = { **Parser.COLUMN_OPERATORS, TokenType.COLON: lambda self, this, path: self.expression( @@ -118,10 +123,20 @@ class Snowflake(Dialect): class Tokenizer(Tokenizer): QUOTES = ["'", "$$"] ESCAPE = "\\" + + SINGLE_TOKENS = { + **Tokenizer.SINGLE_TOKENS, + "$": TokenType.DOLLAR, # needed to break for quotes + } + KEYWORDS = { **Tokenizer.KEYWORDS, "QUALIFY": TokenType.QUALIFY, "DOUBLE PRECISION": TokenType.DOUBLE, + "TIMESTAMP_LTZ": TokenType.TIMESTAMPLTZ, + "TIMESTAMP_NTZ": TokenType.TIMESTAMP, + "TIMESTAMP_TZ": TokenType.TIMESTAMPTZ, + "TIMESTAMPNTZ": TokenType.TIMESTAMP, } class Generator(Generator): @@ -132,6 +147,11 @@ class Snowflake(Dialect): exp.UnixToTime: _unix_to_time, } + TYPE_MAPPING = { + **Generator.TYPE_MAPPING, + exp.DataType.Type.TIMESTAMP: "TIMESTAMPNTZ", + } + def except_op(self, expression): if not expression.args.get("distinct", False): self.unsupported("EXCEPT with All is not supported in Snowflake") diff --git a/sqlglot/dialects/spark.py b/sqlglot/dialects/spark.py index a331191..c051178 100644 --- a/sqlglot/dialects/spark.py +++ b/sqlglot/dialects/spark.py @@ -82,6 +82,7 @@ class Spark(Hive): TRANSFORMS = { **{k: v for k, v in Hive.Generator.TRANSFORMS.items() if k not in {exp.ArraySort}}, + exp.FileFormatProperty: lambda self, e: f"USING {e.text('value').upper()}", exp.ArraySum: lambda self, e: f"AGGREGATE({self.sql(e, 'this')}, 0, (acc, x) -> acc + x, acc -> acc)", exp.BitwiseLeftShift: rename_func("SHIFTLEFT"), exp.BitwiseRightShift: rename_func("SHIFTRIGHT"), diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py new file mode 100644 index 0000000..68bb9bd --- /dev/null +++ b/sqlglot/dialects/tsql.py @@ -0,0 +1,38 @@ +from sqlglot import exp +from sqlglot.dialects.dialect import Dialect +from sqlglot.generator import Generator +from sqlglot.tokens import Tokenizer, TokenType + + +class TSQL(Dialect): + null_ordering = "nulls_are_small" + time_format = "'yyyy-mm-dd hh:mm:ss'" + + class Tokenizer(Tokenizer): + IDENTIFIERS = ['"', ("[", "]")] + + KEYWORDS = { + **Tokenizer.KEYWORDS, + "BIT": TokenType.BOOLEAN, + "REAL": TokenType.FLOAT, + "NTEXT": TokenType.TEXT, + "SMALLDATETIME": TokenType.DATETIME, + "DATETIMEOFFSET": TokenType.TIMESTAMPTZ, + "TIME": TokenType.TIMESTAMP, + "VARBINARY": TokenType.BINARY, + "IMAGE": TokenType.IMAGE, + "MONEY": TokenType.MONEY, + "SMALLMONEY": TokenType.SMALLMONEY, + "ROWVERSION": TokenType.ROWVERSION, + "SQL_VARIANT": TokenType.SQL_VARIANT, + "UNIQUEIDENTIFIER": TokenType.UNIQUEIDENTIFIER, + "XML": TokenType.XML, + } + + class Generator(Generator): + TYPE_MAPPING = { + **Generator.TYPE_MAPPING, + exp.DataType.Type.BOOLEAN: "BIT", + exp.DataType.Type.INT: "INTEGER", + exp.DataType.Type.DECIMAL: "NUMERIC", + } |