Skip to content

Commit

Permalink
fix(bigquery): support microseconds in time literals (#9610)
Browse files Browse the repository at this point in the history
Closes #9609.
  • Loading branch information
cpcloud authored Jul 16, 2024
1 parent ca21dbb commit c876abc
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SELECT
TIME_ADD(TIME(12, 34, 56), INTERVAL 789101 MICROSECOND) AS `datetime_time_12_34_56_789101`
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
SELECT
TIME(12, 34, 56) AS `datetime_time_12_34_56`
10 changes: 10 additions & 0 deletions ibis/backends/bigquery/tests/unit/test_compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,3 +667,13 @@ def test_subquery_scalar_params(snapshot):
)
result = ibis.to_sql(expr, params={p: "20140101"}, dialect="bigquery")
snapshot.assert_match(result, "out.sql")


def test_time_from_hms_with_micros(snapshot):
literal = ibis.literal(datetime.time(12, 34, 56, 789101))
result = ibis.to_sql(literal, dialect="bigquery")
snapshot.assert_match(result, "micros.sql")

literal = ibis.literal(datetime.time(12, 34, 56))
result = ibis.to_sql(literal, dialect="bigquery")
snapshot.assert_match(result, "no_micros.sql")
10 changes: 9 additions & 1 deletion ibis/backends/sql/compilers/bigquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,15 @@ def visit_NonNullLiteral(self, op, *, value, dtype):
elif dtype.is_date():
return self.f.date_from_parts(value.year, value.month, value.day)
elif dtype.is_time():
return self.f.time_from_parts(value.hour, value.minute, value.second)
time = self.f.time_from_parts(value.hour, value.minute, value.second)
if micros := value.microsecond:
# bigquery doesn't support `time(12, 34, 56.789101)`, AKA a
# float seconds specifier, so add any non-zero micros to the
# time value
return sge.TimeAdd(
this=time, expression=sge.convert(micros), unit=self.v.MICROSECOND
)
return time
elif dtype.is_binary():
return sge.Cast(
this=sge.convert(value.hex()),
Expand Down

0 comments on commit c876abc

Please sign in to comment.