summaryrefslogtreecommitdiffstats
path: root/sqlglot/dialects
diff options
context:
space:
mode:
Diffstat (limited to 'sqlglot/dialects')
-rw-r--r--sqlglot/dialects/bigquery.py36
-rw-r--r--sqlglot/dialects/clickhouse.py17
-rw-r--r--sqlglot/dialects/dialect.py1
-rw-r--r--sqlglot/dialects/drill.py1
-rw-r--r--sqlglot/dialects/duckdb.py21
-rw-r--r--sqlglot/dialects/hive.py15
-rw-r--r--sqlglot/dialects/mysql.py29
-rw-r--r--sqlglot/dialects/oracle.py1
-rw-r--r--sqlglot/dialects/postgres.py26
-rw-r--r--sqlglot/dialects/presto.py1
-rw-r--r--sqlglot/dialects/redshift.py1
-rw-r--r--sqlglot/dialects/snowflake.py1
-rw-r--r--sqlglot/dialects/spark2.py3
-rw-r--r--sqlglot/dialects/sqlite.py1
-rw-r--r--sqlglot/dialects/tableau.py1
-rw-r--r--sqlglot/dialects/teradata.py3
-rw-r--r--sqlglot/dialects/tsql.py7
17 files changed, 129 insertions, 36 deletions
diff --git a/sqlglot/dialects/bigquery.py b/sqlglot/dialects/bigquery.py
index c9d6c79..82162b4 100644
--- a/sqlglot/dialects/bigquery.py
+++ b/sqlglot/dialects/bigquery.py
@@ -163,6 +163,17 @@ def _pushdown_cte_column_names(expression: exp.Expression) -> exp.Expression:
return expression
+def _parse_timestamp(args: t.List) -> exp.StrToTime:
+ this = format_time_lambda(exp.StrToTime, "bigquery")([seq_get(args, 1), seq_get(args, 0)])
+ this.set("zone", seq_get(args, 2))
+ return this
+
+
+def _parse_date(args: t.List) -> exp.Date | exp.DateFromParts:
+ expr_type = exp.DateFromParts if len(args) == 3 else exp.Date
+ return expr_type.from_arg_list(args)
+
+
class BigQuery(Dialect):
UNNEST_COLUMN_ONLY = True
@@ -203,8 +214,10 @@ class BigQuery(Dialect):
while isinstance(parent, exp.Dot):
parent = parent.parent
- if not (isinstance(parent, exp.Table) and parent.db) and not expression.meta.get(
- "is_table"
+ if (
+ not isinstance(parent, exp.UserDefinedFunction)
+ and not (isinstance(parent, exp.Table) and parent.db)
+ and not expression.meta.get("is_table")
):
expression.set("this", expression.this.lower())
@@ -251,6 +264,7 @@ class BigQuery(Dialect):
FUNCTIONS = {
**parser.Parser.FUNCTIONS,
+ "DATE": _parse_date,
"DATE_ADD": parse_date_delta_with_interval(exp.DateAdd),
"DATE_SUB": parse_date_delta_with_interval(exp.DateSub),
"DATE_TRUNC": lambda args: exp.DateTrunc(
@@ -264,9 +278,7 @@ class BigQuery(Dialect):
"PARSE_DATE": lambda args: format_time_lambda(exp.StrToDate, "bigquery")(
[seq_get(args, 1), seq_get(args, 0)]
),
- "PARSE_TIMESTAMP": lambda args: format_time_lambda(exp.StrToTime, "bigquery")(
- [seq_get(args, 1), seq_get(args, 0)]
- ),
+ "PARSE_TIMESTAMP": _parse_timestamp,
"REGEXP_CONTAINS": exp.RegexpLike.from_arg_list,
"REGEXP_EXTRACT": lambda args: exp.RegexpExtract(
this=seq_get(args, 0),
@@ -356,9 +368,11 @@ class BigQuery(Dialect):
EXPLICIT_UNION = True
INTERVAL_ALLOWS_PLURAL_FORM = False
JOIN_HINTS = False
+ QUERY_HINTS = False
TABLE_HINTS = False
LIMIT_FETCH = "LIMIT"
RENAME_TABLE_WITH_DB = False
+ ESCAPE_LINE_BREAK = True
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
@@ -367,6 +381,7 @@ class BigQuery(Dialect):
exp.Cast: transforms.preprocess([transforms.remove_precision_parameterized_types]),
exp.CTE: transforms.preprocess([_pushdown_cte_column_names]),
exp.DateAdd: _date_add_sql("DATE", "ADD"),
+ exp.DateFromParts: rename_func("DATE"),
exp.DateSub: _date_add_sql("DATE", "SUB"),
exp.DatetimeAdd: _date_add_sql("DATETIME", "ADD"),
exp.DatetimeSub: _date_add_sql("DATETIME", "SUB"),
@@ -397,7 +412,9 @@ class BigQuery(Dialect):
]
),
exp.StrToDate: lambda self, e: f"PARSE_DATE({self.format_time(e)}, {self.sql(e, 'this')})",
- exp.StrToTime: lambda self, e: f"PARSE_TIMESTAMP({self.format_time(e)}, {self.sql(e, 'this')})",
+ exp.StrToTime: lambda self, e: self.func(
+ "PARSE_TIMESTAMP", self.format_time(e), e.this, e.args.get("zone")
+ ),
exp.TimeAdd: _date_add_sql("TIME", "ADD"),
exp.TimeSub: _date_add_sql("TIME", "SUB"),
exp.TimestampAdd: _date_add_sql("TIMESTAMP", "ADD"),
@@ -548,10 +565,15 @@ class BigQuery(Dialect):
}
def attimezone_sql(self, expression: exp.AtTimeZone) -> str:
- if not isinstance(expression.parent, exp.Cast):
+ parent = expression.parent
+
+ # BigQuery allows CAST(.. AS {STRING|TIMESTAMP} [FORMAT <fmt> [AT TIME ZONE <tz>]]).
+ # Only the TIMESTAMP one should use the below conversion, when AT TIME ZONE is included.
+ if not isinstance(parent, exp.Cast) or not parent.to.is_type("text"):
return self.func(
"TIMESTAMP", self.func("DATETIME", expression.this, expression.args.get("zone"))
)
+
return super().attimezone_sql(expression)
def trycast_sql(self, expression: exp.TryCast) -> str:
diff --git a/sqlglot/dialects/clickhouse.py b/sqlglot/dialects/clickhouse.py
index efaf34c..9126c4b 100644
--- a/sqlglot/dialects/clickhouse.py
+++ b/sqlglot/dialects/clickhouse.py
@@ -109,10 +109,11 @@ class ClickHouse(Dialect):
QUERY_MODIFIER_PARSERS = {
**parser.Parser.QUERY_MODIFIER_PARSERS,
- "settings": lambda self: self._parse_csv(self._parse_conjunction)
- if self._match(TokenType.SETTINGS)
- else None,
- "format": lambda self: self._parse_id_var() if self._match(TokenType.FORMAT) else None,
+ TokenType.SETTINGS: lambda self: (
+ "settings",
+ self._advance() or self._parse_csv(self._parse_conjunction),
+ ),
+ TokenType.FORMAT: lambda self: ("format", self._advance() or self._parse_id_var()),
}
def _parse_conjunction(self) -> t.Optional[exp.Expression]:
@@ -155,9 +156,12 @@ class ClickHouse(Dialect):
return this
def _parse_table(
- self, schema: bool = False, alias_tokens: t.Optional[t.Collection[TokenType]] = None
+ self,
+ schema: bool = False,
+ joins: bool = False,
+ alias_tokens: t.Optional[t.Collection[TokenType]] = None,
) -> t.Optional[exp.Expression]:
- this = super()._parse_table(schema=schema, alias_tokens=alias_tokens)
+ this = super()._parse_table(schema=schema, joins=joins, alias_tokens=alias_tokens)
if self._match(TokenType.FINAL):
this = self.expression(exp.Final, this=this)
@@ -273,6 +277,7 @@ class ClickHouse(Dialect):
return None
class Generator(generator.Generator):
+ QUERY_HINTS = False
STRUCT_DELIMITER = ("(", ")")
TYPE_MAPPING = {
diff --git a/sqlglot/dialects/dialect.py b/sqlglot/dialects/dialect.py
index d258826..4fc93bf 100644
--- a/sqlglot/dialects/dialect.py
+++ b/sqlglot/dialects/dialect.py
@@ -98,7 +98,6 @@ class _Dialect(type):
klass.BIT_START, klass.BIT_END = get_start_end(TokenType.BIT_STRING)
klass.HEX_START, klass.HEX_END = get_start_end(TokenType.HEX_STRING)
klass.BYTE_START, klass.BYTE_END = get_start_end(TokenType.BYTE_STRING)
- klass.RAW_START, klass.RAW_END = get_start_end(TokenType.RAW_STRING)
dialect_properties = {
**{
diff --git a/sqlglot/dialects/drill.py b/sqlglot/dialects/drill.py
index 3cca986..26d09ce 100644
--- a/sqlglot/dialects/drill.py
+++ b/sqlglot/dialects/drill.py
@@ -96,6 +96,7 @@ class Drill(Dialect):
class Generator(generator.Generator):
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py
index 093a01c..d7e5a43 100644
--- a/sqlglot/dialects/duckdb.py
+++ b/sqlglot/dialects/duckdb.py
@@ -8,6 +8,7 @@ from sqlglot.dialects.dialect import (
approx_count_distinct_sql,
arrow_json_extract_scalar_sql,
arrow_json_extract_sql,
+ date_trunc_to_time,
datestrtodate_sql,
format_time_lambda,
no_comment_column_constraint_sql,
@@ -38,6 +39,21 @@ def _date_delta_sql(self: generator.Generator, expression: exp.DateAdd | exp.Dat
return f"{this} {op} {self.sql(exp.Interval(this=expression.expression, unit=unit))}"
+# BigQuery -> DuckDB conversion for the DATE function
+def _date_sql(self: generator.Generator, expression: exp.Date) -> str:
+ result = f"CAST({self.sql(expression, 'this')} AS DATE)"
+ zone = self.sql(expression, "zone")
+
+ if zone:
+ date_str = self.func("STRFTIME", result, "'%d/%m/%Y'")
+ date_str = f"{date_str} || ' ' || {zone}"
+
+ # This will create a TIMESTAMP with time zone information
+ result = self.func("STRPTIME", date_str, "'%d/%m/%Y %Z'")
+
+ return result
+
+
def _array_sort_sql(self: generator.Generator, expression: exp.ArraySort) -> str:
if expression.expression:
self.unsupported("DUCKDB ARRAY_SORT does not support a comparator")
@@ -131,6 +147,8 @@ class DuckDB(Dialect):
"ARRAY_REVERSE_SORT": _sort_array_reverse,
"DATEDIFF": _parse_date_diff,
"DATE_DIFF": _parse_date_diff,
+ "DATE_TRUNC": date_trunc_to_time,
+ "DATETRUNC": date_trunc_to_time,
"EPOCH": exp.TimeToUnix.from_arg_list,
"EPOCH_MS": lambda args: exp.UnixToTime(
this=exp.Div(this=seq_get(args, 0), expression=exp.Literal.number(1000))
@@ -167,6 +185,7 @@ class DuckDB(Dialect):
class Generator(generator.Generator):
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
LIMIT_FETCH = "LIMIT"
STRUCT_DELIMITER = ("(", ")")
RENAME_TABLE_WITH_DB = False
@@ -188,7 +207,9 @@ class DuckDB(Dialect):
exp.DayOfWeek: rename_func("DAYOFWEEK"),
exp.DayOfYear: rename_func("DAYOFYEAR"),
exp.DataType: _datatype_sql,
+ exp.Date: _date_sql,
exp.DateAdd: _date_delta_sql,
+ exp.DateFromParts: rename_func("MAKE_DATE"),
exp.DateSub: _date_delta_sql,
exp.DateDiff: lambda self, e: self.func(
"DATE_DIFF", f"'{e.args.get('unit', 'day')}'", e.expression, e.this
diff --git a/sqlglot/dialects/hive.py b/sqlglot/dialects/hive.py
index 6bca610..1abc0f4 100644
--- a/sqlglot/dialects/hive.py
+++ b/sqlglot/dialects/hive.py
@@ -273,13 +273,6 @@ class Hive(Dialect):
),
}
- QUERY_MODIFIER_PARSERS = {
- **parser.Parser.QUERY_MODIFIER_PARSERS,
- "cluster": lambda self: self._parse_sort(exp.Cluster, TokenType.CLUSTER_BY),
- "distribute": lambda self: self._parse_sort(exp.Distribute, TokenType.DISTRIBUTE_BY),
- "sort": lambda self: self._parse_sort(exp.Sort, TokenType.SORT_BY),
- }
-
def _parse_types(
self, check_func: bool = False, schema: bool = False
) -> t.Optional[exp.Expression]:
@@ -319,6 +312,7 @@ class Hive(Dialect):
TABLESAMPLE_SIZE_IS_PERCENT = True
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
INDEX_ON = "ON TABLE"
TYPE_MAPPING = {
@@ -429,10 +423,3 @@ class Hive(Dialect):
expression = exp.DataType.build(expression.this)
return super().datatype_sql(expression)
-
- def after_having_modifiers(self, expression: exp.Expression) -> t.List[str]:
- return super().after_having_modifiers(expression) + [
- self.sql(expression, "distribute"),
- self.sql(expression, "sort"),
- self.sql(expression, "cluster"),
- ]
diff --git a/sqlglot/dialects/mysql.py b/sqlglot/dialects/mysql.py
index 5f743ee..bae0e50 100644
--- a/sqlglot/dialects/mysql.py
+++ b/sqlglot/dialects/mysql.py
@@ -123,14 +123,15 @@ class MySQL(Dialect):
KEYWORDS = {
**tokens.Tokenizer.KEYWORDS,
"CHARSET": TokenType.CHARACTER_SET,
+ "ENUM": TokenType.ENUM,
"FORCE": TokenType.FORCE,
"IGNORE": TokenType.IGNORE,
"LONGBLOB": TokenType.LONGBLOB,
"LONGTEXT": TokenType.LONGTEXT,
"MEDIUMBLOB": TokenType.MEDIUMBLOB,
"MEDIUMTEXT": TokenType.MEDIUMTEXT,
+ "MEMBER OF": TokenType.MEMBER_OF,
"SEPARATOR": TokenType.SEPARATOR,
- "ENUM": TokenType.ENUM,
"START": TokenType.BEGIN,
"SIGNED": TokenType.BIGINT,
"SIGNED INTEGER": TokenType.BIGINT,
@@ -185,11 +186,26 @@ class MySQL(Dialect):
COMMANDS = tokens.Tokenizer.COMMANDS - {TokenType.SHOW}
class Parser(parser.Parser):
- FUNC_TOKENS = {*parser.Parser.FUNC_TOKENS, TokenType.SCHEMA, TokenType.DATABASE}
+ FUNC_TOKENS = {
+ *parser.Parser.FUNC_TOKENS,
+ TokenType.DATABASE,
+ TokenType.SCHEMA,
+ TokenType.VALUES,
+ }
+
TABLE_ALIAS_TOKENS = (
parser.Parser.TABLE_ALIAS_TOKENS - parser.Parser.TABLE_INDEX_HINT_TOKENS
)
+ RANGE_PARSERS = {
+ **parser.Parser.RANGE_PARSERS,
+ TokenType.MEMBER_OF: lambda self, this: self.expression(
+ exp.JSONArrayContains,
+ this=this,
+ expression=self._parse_wrapped(self._parse_expression),
+ ),
+ }
+
FUNCTIONS = {
**parser.Parser.FUNCTIONS,
"DATE_ADD": parse_date_delta_with_interval(exp.DateAdd),
@@ -207,6 +223,10 @@ class MySQL(Dialect):
this=self._parse_lambda(),
separator=self._match(TokenType.SEPARATOR) and self._parse_field(),
),
+ # https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
+ "VALUES": lambda self: self.expression(
+ exp.Anonymous, this="VALUES", expressions=[self._parse_id_var()]
+ ),
}
STATEMENT_PARSERS = {
@@ -399,6 +419,8 @@ class MySQL(Dialect):
NULL_ORDERING_SUPPORTED = False
JOIN_HINTS = False
TABLE_HINTS = True
+ DUPLICATE_KEY_UPDATE_WITH_SET = False
+ QUERY_HINT_SEP = " "
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
@@ -445,6 +467,9 @@ class MySQL(Dialect):
LIMIT_FETCH = "LIMIT"
+ def jsonarraycontains_sql(self, expression: exp.JSONArrayContains) -> str:
+ return f"{self.sql(expression, 'this')} MEMBER OF({self.sql(expression, 'expression')})"
+
def cast_sql(self, expression: exp.Cast, safe_prefix: t.Optional[str] = None) -> str:
"""(U)BIGINT is not allowed in a CAST expression, so we use (UN)SIGNED instead."""
if expression.to.this == exp.DataType.Type.BIGINT:
diff --git a/sqlglot/dialects/oracle.py b/sqlglot/dialects/oracle.py
index 8d35e92..2b77ef9 100644
--- a/sqlglot/dialects/oracle.py
+++ b/sqlglot/dialects/oracle.py
@@ -121,7 +121,6 @@ class Oracle(Dialect):
"TO_DATE", e.this, exp.Literal.string("YYYY-MM-DD")
),
exp.Group: transforms.preprocess([transforms.unalias_group]),
- exp.Hint: lambda self, e: f" /*+ {self.expressions(e).strip()} */",
exp.ILike: no_ilike_sql,
exp.Coalesce: rename_func("NVL"),
exp.Select: transforms.preprocess([transforms.eliminate_distinct_on]),
diff --git a/sqlglot/dialects/postgres.py b/sqlglot/dialects/postgres.py
index 766b584..6d78a07 100644
--- a/sqlglot/dialects/postgres.py
+++ b/sqlglot/dialects/postgres.py
@@ -183,6 +183,29 @@ def _to_timestamp(args: t.List) -> exp.Expression:
return format_time_lambda(exp.StrToTime, "postgres")(args)
+def _remove_target_from_merge(expression: exp.Expression) -> exp.Expression:
+ """Remove table refs from columns in when statements."""
+ if isinstance(expression, exp.Merge):
+ alias = expression.this.args.get("alias")
+
+ normalize = lambda identifier: Postgres.normalize_identifier(identifier).name
+
+ targets = {normalize(expression.this.this)}
+
+ if alias:
+ targets.add(normalize(alias.this))
+
+ for when in expression.expressions:
+ when.transform(
+ lambda node: exp.column(node.name)
+ if isinstance(node, exp.Column) and normalize(node.args.get("table")) in targets
+ else node,
+ copy=False,
+ )
+
+ return expression
+
+
class Postgres(Dialect):
INDEX_OFFSET = 1
NULL_ORDERING = "nulls_are_large"
@@ -315,6 +338,7 @@ class Postgres(Dialect):
LOCKING_READS_SUPPORTED = True
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
PARAMETER_TOKEN = "$"
TYPE_MAPPING = {
@@ -352,7 +376,7 @@ class Postgres(Dialect):
exp.ArrayOverlaps: lambda self, e: self.binary(e, "&&"),
exp.ArrayContains: lambda self, e: self.binary(e, "@>"),
exp.ArrayContained: lambda self, e: self.binary(e, "<@"),
- exp.Merge: transforms.preprocess([transforms.remove_target_from_merge]),
+ exp.Merge: transforms.preprocess([_remove_target_from_merge]),
exp.Pivot: no_pivot_sql,
exp.RegexpLike: lambda self, e: self.binary(e, "~"),
exp.RegexpILike: lambda self, e: self.binary(e, "~*"),
diff --git a/sqlglot/dialects/presto.py b/sqlglot/dialects/presto.py
index 24c439b..1721588 100644
--- a/sqlglot/dialects/presto.py
+++ b/sqlglot/dialects/presto.py
@@ -232,6 +232,7 @@ class Presto(Dialect):
INTERVAL_ALLOWS_PLURAL_FORM = False
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
IS_BOOL_ALLOWED = False
STRUCT_DELIMITER = ("(", ")")
diff --git a/sqlglot/dialects/redshift.py b/sqlglot/dialects/redshift.py
index 87be42c..09edd55 100644
--- a/sqlglot/dialects/redshift.py
+++ b/sqlglot/dialects/redshift.py
@@ -86,6 +86,7 @@ class Redshift(Postgres):
class Generator(Postgres.Generator):
LOCKING_READS_SUPPORTED = False
RENAME_TABLE_WITH_DB = False
+ QUERY_HINTS = False
TYPE_MAPPING = {
**Postgres.Generator.TYPE_MAPPING,
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py
index 34e4dd0..19924cd 100644
--- a/sqlglot/dialects/snowflake.py
+++ b/sqlglot/dialects/snowflake.py
@@ -326,6 +326,7 @@ class Snowflake(Dialect):
SINGLE_STRING_INTERVAL = True
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
diff --git a/sqlglot/dialects/spark2.py b/sqlglot/dialects/spark2.py
index 3720b8d..afe2482 100644
--- a/sqlglot/dialects/spark2.py
+++ b/sqlglot/dialects/spark2.py
@@ -173,6 +173,8 @@ class Spark2(Hive):
return pivot_column_names(aggregations, dialect="spark")
class Generator(Hive.Generator):
+ QUERY_HINTS = True
+
TYPE_MAPPING = {
**Hive.Generator.TYPE_MAPPING,
exp.DataType.Type.TINYINT: "BYTE",
@@ -203,7 +205,6 @@ class Spark2(Hive):
exp.DayOfYear: rename_func("DAYOFYEAR"),
exp.FileFormatProperty: lambda self, e: f"USING {e.name.upper()}",
exp.From: transforms.preprocess([_unalias_pivot]),
- exp.Hint: lambda self, e: f" /*+ {self.expressions(e).strip()} */",
exp.LogicalAnd: rename_func("BOOL_AND"),
exp.LogicalOr: rename_func("BOOL_OR"),
exp.Map: _map_sql,
diff --git a/sqlglot/dialects/sqlite.py b/sqlglot/dialects/sqlite.py
index 519e62a..5ded6df 100644
--- a/sqlglot/dialects/sqlite.py
+++ b/sqlglot/dialects/sqlite.py
@@ -77,6 +77,7 @@ class SQLite(Dialect):
class Generator(generator.Generator):
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
diff --git a/sqlglot/dialects/tableau.py b/sqlglot/dialects/tableau.py
index 67ef76b..33ec7e1 100644
--- a/sqlglot/dialects/tableau.py
+++ b/sqlglot/dialects/tableau.py
@@ -8,6 +8,7 @@ class Tableau(Dialect):
class Generator(generator.Generator):
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
TRANSFORMS = {
**generator.Generator.TRANSFORMS,
diff --git a/sqlglot/dialects/teradata.py b/sqlglot/dialects/teradata.py
index d9a5417..4e8ffb4 100644
--- a/sqlglot/dialects/teradata.py
+++ b/sqlglot/dialects/teradata.py
@@ -121,7 +121,7 @@ class Teradata(Dialect):
exp.Update,
**{ # type: ignore
"this": self._parse_table(alias_tokens=self.UPDATE_ALIAS_TOKENS),
- "from": self._parse_from(modifiers=True),
+ "from": self._parse_from(joins=True),
"expressions": self._match(TokenType.SET)
and self._parse_csv(self._parse_equality),
"where": self._parse_where(),
@@ -140,6 +140,7 @@ class Teradata(Dialect):
class Generator(generator.Generator):
JOIN_HINTS = False
TABLE_HINTS = False
+ QUERY_HINTS = False
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
diff --git a/sqlglot/dialects/tsql.py b/sqlglot/dialects/tsql.py
index f671630..92bb755 100644
--- a/sqlglot/dialects/tsql.py
+++ b/sqlglot/dialects/tsql.py
@@ -60,10 +60,10 @@ def _format_time_lambda(
assert len(args) == 2
return exp_class(
- this=args[1],
+ this=exp.cast(args[1], "datetime"),
format=exp.Literal.string(
format_time(
- args[0].name,
+ args[0].name.lower(),
{**TSQL.TIME_MAPPING, **FULL_FORMAT_TIME_MAPPING}
if full_format_mapping
else TSQL.TIME_MAPPING,
@@ -467,6 +467,8 @@ class TSQL(Dialect):
class Generator(generator.Generator):
LOCKING_READS_SUPPORTED = True
+ LIMIT_IS_TOP = True
+ QUERY_HINTS = False
TYPE_MAPPING = {
**generator.Generator.TYPE_MAPPING,
@@ -482,6 +484,7 @@ class TSQL(Dialect):
exp.DateDiff: generate_date_delta_with_unit_sql,
exp.CurrentDate: rename_func("GETDATE"),
exp.CurrentTimestamp: rename_func("GETDATE"),
+ exp.Extract: rename_func("DATEPART"),
exp.GroupConcat: _string_agg_sql,
exp.If: rename_func("IIF"),
exp.Max: max_or_greatest,