Skip to content

Commit c8a9ce5

Browse files
Address review comments: remove redundant casting and fix test cases
- Remove redundant TIMESTAMP_NS casting in _timediff_sql (lines 268-271) * Previously cast to TIMESTAMP_NS before calling _handle_nanosecond_diff * _handle_nanosecond_diff already handles casting via exp.cast (which avoids recasting) * Now passes expressions directly, matching _date_diff_sql pattern - Fix TIMEDIFF test case to use valid Snowflake syntax * Changed from TIME literal '10:00:00.000000000' * To TIMESTAMP with CAST: CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP) * TIME literals don't work with TIMEDIFF in Snowflake - Fix TIMEADD test case to use valid Snowflake syntax * Changed from TIME literal '10:00:00.000000000' * To TIMESTAMP with CAST: CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP) * TIME literals don't work with TIMEADD in Snowflake Addresses review comments from VaggelisD on PR #6617
1 parent 1fa600a commit c8a9ce5

File tree

2 files changed

+16
-13
lines changed

2 files changed

+16
-13
lines changed

sqlglot/dialects/duckdb.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,16 @@ def _last_day_sql(self: DuckDB.Generator, expression: exp.LastDay) -> str:
144144

145145

146146
def _unwrap_cast(expr: exp.Expression) -> exp.Expression:
147-
"""Unwrap Cast expression to avoid double-casting that loses nanosecond precision.
147+
"""Unwrap Cast expression to avoid nested casts when recasting to different types.
148148
149-
Nested casts can lose precision when converting between
150-
timestamp types. By unwrapping the inner cast, we go directly from the source
151-
expression to TIMESTAMP_NS, preserving nanosecond precision.
149+
While exp.cast avoids recasting to the SAME type, it doesn't unwrap casts to
150+
DIFFERENT types. This helper extracts the inner expression before casting to
151+
avoid nested casts like CAST(CAST(x AS TIMESTAMP) AS TIMESTAMP_NS).
152+
153+
Example:
154+
Input: CAST('2023-01-01' AS TIMESTAMP)
155+
Without unwrap: CAST(CAST('2023-01-01' AS TIMESTAMP) AS TIMESTAMP_NS)
156+
With unwrap: CAST('2023-01-01' AS TIMESTAMP_NS)
152157
"""
153158
return expr.this if isinstance(expr, exp.Cast) else expr
154159

@@ -266,9 +271,7 @@ def _timediff_sql(self: DuckDB.Generator, expression: exp.TimeDiff) -> str:
266271
unit = expression.args.get("unit")
267272

268273
if _is_nanosecond_unit(unit):
269-
this_ts = exp.cast(expression.this, exp.DataType.Type.TIMESTAMP_NS)
270-
expr_ts = exp.cast(expression.expression, exp.DataType.Type.TIMESTAMP_NS)
271-
return _handle_nanosecond_diff(self, expr_ts, this_ts)
274+
return _handle_nanosecond_diff(self, expression.expression, expression.this)
272275

273276
this = exp.cast(expression.this, exp.DataType.Type.TIME)
274277
expr = exp.cast(expression.expression, exp.DataType.Type.TIME)

tests/dialects/test_snowflake.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2493,10 +2493,10 @@ def test_timestamps(self):
24932493

24942494
# Test TIMEDIFF with NANOSECOND - DuckDB uses EPOCH_NS for nanosecond precision
24952495
self.validate_all(
2496-
"TIMEDIFF(NANOSECOND, '10:00:00.000000000', '10:00:00.123456789')",
2496+
"TIMEDIFF(NANOSECOND, CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP), CAST('2023-01-01 10:00:00.123456789' AS TIMESTAMP))",
24972497
write={
2498-
"duckdb": "EPOCH_NS(CAST('10:00:00.123456789' AS TIMESTAMP_NS)) - EPOCH_NS(CAST('10:00:00.000000000' AS TIMESTAMP_NS))",
2499-
"snowflake": "DATEDIFF(NANOSECOND, '10:00:00.000000000', '10:00:00.123456789')",
2498+
"duckdb": "EPOCH_NS(CAST('2023-01-01 10:00:00.123456789' AS TIMESTAMP_NS)) - EPOCH_NS(CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP_NS))",
2499+
"snowflake": "DATEDIFF(NANOSECOND, CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP), CAST('2023-01-01 10:00:00.123456789' AS TIMESTAMP))",
25002500
},
25012501
)
25022502

@@ -2518,10 +2518,10 @@ def test_timestamps(self):
25182518

25192519
# Test TIMEADD with NANOSECOND - DuckDB uses MAKE_TIMESTAMP_NS
25202520
self.validate_all(
2521-
"TIMEADD(NANOSECOND, 123456789, '10:00:00.000000000')",
2521+
"TIMEADD(NANOSECOND, 123456789, CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP))",
25222522
write={
2523-
"duckdb": "MAKE_TIMESTAMP_NS(EPOCH_NS(CAST('10:00:00.000000000' AS TIMESTAMP_NS)) + 123456789)",
2524-
"snowflake": "TIMEADD(NANOSECOND, 123456789, '10:00:00.000000000')",
2523+
"duckdb": "MAKE_TIMESTAMP_NS(EPOCH_NS(CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP_NS)) + 123456789)",
2524+
"snowflake": "TIMEADD(NANOSECOND, 123456789, CAST('2023-01-01 10:00:00.000000000' AS TIMESTAMP))",
25252525
},
25262526
)
25272527

0 commit comments

Comments
 (0)