Skip to content

Commit 4bb0b78

Browse files
authored
fix(snowflake/bigquery/athena): ensure that timestamp casting works (#11135)
1 parent c0d06c4 commit 4bb0b78

File tree

4 files changed

+25
-2
lines changed

4 files changed

+25
-2
lines changed

ibis/backends/sql/compilers/athena.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from sqlglot.dialects import Athena
66

7+
import ibis.expr.datatypes as dt
78
import ibis.expr.operations as ops
89
from ibis.backends.sql.compilers.trino import TrinoCompiler
910
from ibis.backends.sql.datatypes import AthenaType
@@ -36,5 +37,16 @@ class AthenaCompiler(TrinoCompiler):
3637
def _gen_valid_name(name: str) -> str:
3738
return "_".join(map(str.strip, _NAME_REGEX.findall(name))) or "tmp"
3839

40+
def visit_Cast(self, op, *, arg, to):
41+
from_ = op.arg.dtype
42+
if from_.is_numeric() and to.is_timestamp():
43+
if from_.is_integer():
44+
return self.f.from_unixtime(arg)
45+
elif from_.is_floating():
46+
return self.f.from_unixtime(self.cast(arg, dt.Decimal(38, 9)))
47+
else:
48+
return self.f.from_unixtime(arg)
49+
return super().visit_Cast(op, arg=arg, to=to)
50+
3951

4052
compiler = AthenaCompiler()

ibis/backends/sql/compilers/bigquery/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ def visit_Cast(self, op, *, arg, to):
610610
elif from_.is_numeric() and to.is_timestamp():
611611
if from_.is_integer():
612612
return self.f.timestamp_seconds(arg)
613-
return self.f.timestamp_micros(arg * 1_000_000)
613+
return self.f.timestamp_micros(self.cast(arg * 1_000_000, dt.int64))
614614
elif from_.is_interval() and to.is_integer():
615615
if from_.unit in {
616616
IntervalUnit.WEEK,

ibis/backends/sql/compilers/snowflake.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,10 +300,15 @@ def visit_Arbitrary(self, op, *, arg, where):
300300
return self.f.get(self.agg.array_agg(arg, where=where), 0)
301301

302302
def visit_Cast(self, op, *, arg, to):
303+
from_ = op.arg.dtype
303304
if to.is_struct() or to.is_map():
304305
return self.if_(self.f.is_object(arg), arg, NULL)
305306
elif to.is_array():
306307
return self.if_(self.f.is_array(arg), arg, NULL)
308+
elif from_.is_numeric() and to.is_timestamp():
309+
if from_.is_integer():
310+
return self.f.to_timestamp(self.f.to_decimal(arg), 0)
311+
return self.f.to_timestamp(self.f.to_decimal(arg * 1_000_000), 6)
307312
return super().visit_Cast(op, arg=arg, to=to)
308313

309314
def visit_IsNan(self, op, *, arg):

ibis/backends/sql/compilers/trino.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,13 @@ def visit_ArrayIndex(self, op, *, arg, index):
556556
def visit_Cast(self, op, *, arg, to):
557557
from_ = op.arg.dtype
558558
if from_.is_numeric() and to.is_timestamp():
559-
return self.f.from_unixtime(arg, to.timezone or "UTC")
559+
tz = to.timezone or "UTC"
560+
if from_.is_integer():
561+
return self.f.from_unixtime(arg, tz)
562+
else:
563+
return self.f.from_unixtime_nanos(
564+
self.cast(arg, dt.Decimal(38, 9)) * 1_000_000_000
565+
)
560566
return super().visit_Cast(op, arg=arg, to=to)
561567

562568
def visit_CountDistinctStar(self, op, *, arg, where):

0 commit comments

Comments
 (0)