Skip to content

Commit

Permalink
Feat!(snowflake): improve transpilation of TO_TIMESTAMP* variants (#4473
Browse files Browse the repository at this point in the history
)

* Feat!(snowflake): improve transpilation of TO_TIMESTAMP* variants

* Use is_int method
  • Loading branch information
georgesittas authored Dec 4, 2024
1 parent a9dca8d commit 65a51d7
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 4 deletions.
11 changes: 7 additions & 4 deletions sqlglot/dialects/snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,12 @@ def _build_datetime(
) -> t.Callable[[t.List], exp.Func]:
def _builder(args: t.List) -> exp.Func:
value = seq_get(args, 0)
scale_or_fmt = seq_get(args, 1)

int_value = value is not None and is_int(value.name)
int_scale_or_fmt = scale_or_fmt is not None and scale_or_fmt.is_int

if isinstance(value, exp.Literal):
if isinstance(value, exp.Literal) or (value and scale_or_fmt):
# Converts calls like `TO_TIME('01:02:03')` into casts
if len(args) == 1 and value.is_string and not int_value:
return (
Expand All @@ -55,11 +58,11 @@ def _builder(args: t.List) -> exp.Func:
# Handles `TO_TIMESTAMP(str, fmt)` and `TO_TIMESTAMP(num, scale)` as special
# cases so we can transpile them, since they're relatively common
if kind == exp.DataType.Type.TIMESTAMP:
if int_value and not safe:
if not safe and (int_value or int_scale_or_fmt):
# TRY_TO_TIMESTAMP('integer') is not parsed into exp.UnixToTime as
# it's not easily transpilable
return exp.UnixToTime(this=value, scale=seq_get(args, 1))
if not is_float(value.this):
return exp.UnixToTime(this=value, scale=scale_or_fmt)
if not int_scale_or_fmt and not is_float(value.name):
expr = build_formatted_time(exp.StrToTime, "snowflake")(args)
expr.set("safe", safe)
return expr
Expand Down
10 changes: 10 additions & 0 deletions tests/dialects/test_snowflake.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def test_snowflake(self):
self.validate_identity(
"SELECT * FROM DATA AS DATA_L ASOF JOIN DATA AS DATA_R MATCH_CONDITION (DATA_L.VAL > DATA_R.VAL) ON DATA_L.ID = DATA_R.ID"
)
self.validate_identity("TO_TIMESTAMP(col, fmt)")
self.validate_identity(
"CAST(x AS GEOGRAPHY)",
"TO_GEOGRAPHY(x)",
Expand Down Expand Up @@ -670,6 +671,15 @@ def test_snowflake(self):
"snowflake": "SELECT a FROM test AS t QUALIFY ROW_NUMBER() OVER (PARTITION BY a ORDER BY Z) = 1",
},
)
self.validate_all(
"SELECT TO_TIMESTAMP(col, 'DD-MM-YYYY HH12:MI:SS') FROM t",
write={
"bigquery": "SELECT PARSE_TIMESTAMP('%d-%m-%Y %I:%M:%S', col) FROM t",
"duckdb": "SELECT STRPTIME(col, '%d-%m-%Y %I:%M:%S') FROM t",
"snowflake": "SELECT TO_TIMESTAMP(col, 'DD-mm-yyyy hh12:mi:ss') FROM t",
"spark": "SELECT TO_TIMESTAMP(col, 'dd-MM-yyyy hh:mm:ss') FROM t",
},
)
self.validate_all(
"SELECT TO_TIMESTAMP(1659981729)",
write={
Expand Down

0 comments on commit 65a51d7

Please sign in to comment.