diff options
Diffstat (limited to 'sqlglot/dialects/snowflake.py')
-rw-r--r-- | sqlglot/dialects/snowflake.py | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py index a8e4a42..281167d 100644 --- a/sqlglot/dialects/snowflake.py +++ b/sqlglot/dialects/snowflake.py @@ -3,7 +3,6 @@ from __future__ import annotations import typing as t from sqlglot import exp, generator, parser, tokens, transforms -from sqlglot._typing import E from sqlglot.dialects.dialect import ( Dialect, NormalizationStrategy, @@ -25,6 +24,9 @@ from sqlglot.expressions import Literal from sqlglot.helper import seq_get from sqlglot.tokens import TokenType +if t.TYPE_CHECKING: + from sqlglot._typing import E + def _check_int(s: str) -> bool: if s[0] in ("-", "+"): @@ -297,10 +299,7 @@ def _parse_colon_get_path( if not self._match(TokenType.COLON): break - if self._match_set(self.RANGE_PARSERS): - this = self.RANGE_PARSERS[self._prev.token_type](self, this) or this - - return this + return self._parse_range(this) def _parse_timestamp_from_parts(args: t.List) -> exp.Func: @@ -376,7 +375,7 @@ class Snowflake(Dialect): and isinstance(expression.parent, exp.Table) and expression.name.lower() == "dual" ): - return t.cast(E, expression) + return expression # type: ignore return super().quote_identifier(expression, identify=identify) @@ -471,6 +470,10 @@ class Snowflake(Dialect): } SHOW_PARSERS = { + "SCHEMAS": _show_parser("SCHEMAS"), + "TERSE SCHEMAS": _show_parser("SCHEMAS"), + "OBJECTS": _show_parser("OBJECTS"), + "TERSE OBJECTS": _show_parser("OBJECTS"), "PRIMARY KEYS": _show_parser("PRIMARY KEYS"), "TERSE PRIMARY KEYS": _show_parser("PRIMARY KEYS"), "COLUMNS": _show_parser("COLUMNS"), @@ -580,21 +583,35 @@ class Snowflake(Dialect): scope = None scope_kind = None + # will identity SHOW TERSE SCHEMAS but not SHOW TERSE PRIMARY KEYS + # which is syntactically valid but has no effect on the output + terse = self._tokens[self._index - 2].text.upper() == "TERSE" + like = self._parse_string() if self._match(TokenType.LIKE) else None if self._match(TokenType.IN): if self._match_text_seq("ACCOUNT"): scope_kind = "ACCOUNT" elif self._match_set(self.DB_CREATABLES): - scope_kind = self._prev.text + scope_kind = self._prev.text.upper() if self._curr: - scope = self._parse_table() + scope = self._parse_table_parts() elif self._curr: - scope_kind = "TABLE" - scope = self._parse_table() + scope_kind = "SCHEMA" if this == "OBJECTS" else "TABLE" + scope = self._parse_table_parts() return self.expression( - exp.Show, this=this, like=like, scope=scope, scope_kind=scope_kind + exp.Show, + **{ + "terse": terse, + "this": this, + "like": like, + "scope": scope, + "scope_kind": scope_kind, + "starts_with": self._match_text_seq("STARTS", "WITH") and self._parse_string(), + "limit": self._parse_limit(), + "from": self._parse_string() if self._match(TokenType.FROM) else None, + }, ) def _parse_alter_table_swap(self) -> exp.SwapTable: @@ -690,6 +707,9 @@ class Snowflake(Dialect): exp.DayOfYear: rename_func("DAYOFYEAR"), exp.Explode: rename_func("FLATTEN"), exp.Extract: rename_func("DATE_PART"), + exp.FromTimeZone: lambda self, e: self.func( + "CONVERT_TIMEZONE", e.args.get("zone"), "'UTC'", e.this + ), exp.GenerateSeries: lambda self, e: self.func( "ARRAY_GENERATE_RANGE", e.args["start"], e.args["end"] + 1, e.args.get("step") ), @@ -820,6 +840,7 @@ class Snowflake(Dialect): return f"{explode}{alias}" def show_sql(self, expression: exp.Show) -> str: + terse = "TERSE " if expression.args.get("terse") else "" like = self.sql(expression, "like") like = f" LIKE {like}" if like else "" @@ -830,7 +851,19 @@ class Snowflake(Dialect): if scope_kind: scope_kind = f" IN {scope_kind}" - return f"SHOW {expression.name}{like}{scope_kind}{scope}" + starts_with = self.sql(expression, "starts_with") + if starts_with: + starts_with = f" STARTS WITH {starts_with}" + + limit = self.sql(expression, "limit") + + from_ = self.sql(expression, "from") + if from_: + from_ = f" FROM {from_}" + + return ( + f"SHOW {terse}{expression.name}{like}{scope_kind}{scope}{starts_with}{limit}{from_}" + ) def regexpextract_sql(self, expression: exp.RegexpExtract) -> str: # Other dialects don't support all of the following parameters, so we need to @@ -884,3 +917,6 @@ class Snowflake(Dialect): def with_properties(self, properties: exp.Properties) -> str: return self.properties(properties, wrapped=False, prefix=self.seg(""), sep=" ") + + def cluster_sql(self, expression: exp.Cluster) -> str: + return f"CLUSTER BY ({self.expressions(expression, flat=True)})" |