Skip to content

Commit

Permalink
fix(snowflake): Allow parsing of TO_TIME (#4631)
Browse files Browse the repository at this point in the history
  • Loading branch information
VaggelisD authored Jan 16, 2025
1 parent 59d886d commit 6107661
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 11 deletions.
9 changes: 7 additions & 2 deletions sqlglot/dialects/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,9 @@ def _builder(args: t.List) -> exp.Func:
expr.set("safe", safe)
return expr

if kind == exp.DataType.Type.DATE and not int_value:
formatted_exp = build_formatted_time(exp.TsOrDsToDate, "snowflake")(args)
if kind in (exp.DataType.Type.DATE, exp.DataType.Type.TIME) and not int_value:
klass = exp.TsOrDsToDate if kind == exp.DataType.Type.DATE else exp.TsOrDsToTime
formatted_exp = build_formatted_time(klass, "snowflake")(args)
formatted_exp.set("safe", safe)
return formatted_exp

Expand Down Expand Up @@ -449,6 +450,7 @@ class Parser(parser.Parser):
"TIMESTAMP_NTZ_FROM_PARTS": build_timestamp_from_parts,
"TRY_PARSE_JSON": lambda args: exp.ParseJSON(this=seq_get(args, 0), safe=True),
"TRY_TO_DATE": _build_datetime("TRY_TO_DATE", exp.DataType.Type.DATE, safe=True),
"TRY_TO_TIME": _build_datetime("TRY_TO_TIME", exp.DataType.Type.TIME, safe=True),
"TRY_TO_TIMESTAMP": _build_datetime(
"TRY_TO_TIMESTAMP", exp.DataType.Type.TIMESTAMP, safe=True
),
Expand Down Expand Up @@ -979,6 +981,9 @@ class Generator(generator.Generator):
exp.TsOrDsToDate: lambda self, e: self.func(
"TRY_TO_DATE" if e.args.get("safe") else "TO_DATE", e.this, self.format_time(e)
),
exp.TsOrDsToTime: lambda self, e: self.func(
"TRY_TO_TIME" if e.args.get("safe") else "TO_TIME", e.this, self.format_time(e)
),
exp.UnixToTime: rename_func("TO_TIMESTAMP"),
exp.Uuid: rename_func("UUID_STRING"),
exp.VarMap: lambda self, e: var_map_sql(self, e, "OBJECT_CONSTRUCT"),
Expand Down
2 changes: 1 addition & 1 deletion sqlglot/expressions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6654,7 +6654,7 @@ class TsOrDsToDatetime(Func):


class TsOrDsToTime(Func):
pass
arg_types = {"this": True, "format": False, "safe": False}


class TsOrDsToTimestamp(Func):
Expand Down
10 changes: 10 additions & 0 deletions sqlglot/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3934,6 +3934,16 @@ def toarray_sql(self, expression: exp.ToArray) -> str:

def tsordstotime_sql(self, expression: exp.TsOrDsToTime) -> str:
this = expression.this
time_format = self.format_time(expression)

if time_format:
return self.sql(
exp.cast(
exp.StrToTime(this=this, format=expression.args["format"]),
exp.DataType.Type.TIME,
)
)

if isinstance(this, exp.TsOrDsToTime) or this.is_type(exp.DataType.Type.TIME):
return self.sql(this)

Expand Down
39 changes: 31 additions & 8 deletions tests/dialects/test_snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ def test_snowflake(self):
self.validate_identity("SELECT CAST(obj AS OBJECT(x CHAR) RENAME FIELDS)")
self.validate_identity("SELECT CAST(obj AS OBJECT(x CHAR, y VARCHAR) ADD FIELDS)")
self.validate_identity("SELECT TO_TIMESTAMP(123.4)").selects[0].assert_is(exp.Anonymous)
self.validate_identity("SELECT TO_TIME(x) FROM t")
self.validate_identity("SELECT TO_TIMESTAMP(x) FROM t")
self.validate_identity("SELECT TO_TIMESTAMP_NTZ(x) FROM t")
self.validate_identity("SELECT TO_TIMESTAMP_LTZ(x) FROM t")
Expand Down Expand Up @@ -730,13 +729,6 @@ def test_snowflake(self):
"spark": "SELECT CAST('2013-04-05 01:02:03' AS TIMESTAMP)",
},
)
self.validate_all(
"SELECT TO_TIME('12:05:00')",
write={
"bigquery": "SELECT CAST('12:05:00' AS TIME)",
"snowflake": "SELECT CAST('12:05:00' AS TIME)",
},
)
self.validate_all(
"SELECT TO_TIMESTAMP('04/05/2013 01:02:03', 'mm/DD/yyyy hh24:mi:ss')",
read={
Expand Down Expand Up @@ -1296,6 +1288,37 @@ def test_timestamps(self):
},
)

self.validate_identity("SELECT TO_TIME(x) FROM t")
self.validate_all(
"SELECT TO_TIME('12:05:00')",
write={
"bigquery": "SELECT CAST('12:05:00' AS TIME)",
"snowflake": "SELECT CAST('12:05:00' AS TIME)",
"duckdb": "SELECT CAST('12:05:00' AS TIME)",
},
)
self.validate_all(
"SELECT TO_TIME(CONVERT_TIMEZONE('UTC', 'US/Pacific', '2024-08-06 09:10:00.000')) AS pst_time",
write={
"snowflake": "SELECT TO_TIME(CONVERT_TIMEZONE('UTC', 'US/Pacific', '2024-08-06 09:10:00.000')) AS pst_time",
"duckdb": "SELECT CAST(CAST('2024-08-06 09:10:00.000' AS TIMESTAMP) AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific' AS TIME) AS pst_time",
},
)
self.validate_all(
"SELECT TO_TIME('11.15.00', 'hh24.mi.ss')",
write={
"snowflake": "SELECT TO_TIME('11.15.00', 'hh24.mi.ss')",
"duckdb": "SELECT CAST(STRPTIME('11.15.00', '%H.%M.%S') AS TIME)",
},
)
self.validate_all(
"SELECT TRY_TO_TIME('11.15.00', 'hh24.mi.ss')",
write={
"snowflake": "SELECT TRY_TO_TIME('11.15.00', 'hh24.mi.ss')",
"duckdb": "SELECT CAST(STRPTIME('11.15.00', '%H.%M.%S') AS TIME)",
},
)

def test_semi_structured_types(self):
self.validate_identity("SELECT CAST(a AS VARIANT)")
self.validate_identity("SELECT CAST(a AS ARRAY)")
Expand Down

0 comments on commit 6107661

Please sign in to comment.