summaryrefslogtreecommitdiffstats
path: root/sqlglot/dialects/snowflake.py
diff options
context:
space:
mode:
Diffstat (limited to 'sqlglot/dialects/snowflake.py')
-rw-r--r--sqlglot/dialects/snowflake.py60
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)})"