From 9edc984239e058043c03117b7aa43e3ce8bfabd8 Mon Sep 17 00:00:00 2001 From: Phillip Cloud <417981+cpcloud@users.noreply.github.com> Date: Wed, 25 Sep 2024 06:53:38 -0400 Subject: [PATCH] fix(clickhouse): fix truncating to date from a timestamp --- ibis/backends/clickhouse/tests/test_functions.py | 14 ++++++++------ ibis/backends/sql/compilers/clickhouse.py | 10 ++++++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ibis/backends/clickhouse/tests/test_functions.py b/ibis/backends/clickhouse/tests/test_functions.py index e4788026bc95e..2637860c4a745 100644 --- a/ibis/backends/clickhouse/tests/test_functions.py +++ b/ibis/backends/clickhouse/tests/test_functions.py @@ -495,14 +495,16 @@ def my_eq(a: int, b: int) -> bool: ... def test_timestamp_to_start_of_week(con): - expr = ibis.timestamp("2024-02-03 00:00:00") - expr1 = expr.truncate("W") - result = con.to_pyarrow(expr1) - assert result is not None + pytest.importorskip("pyarrow") + + expr = ibis.timestamp("2024-02-03 00:00:00").truncate("W") + result = con.to_pyarrow(expr).as_py() + assert result == datetime(2024, 1, 29, 0, 0, 0) def test_date_to_start_of_day(con): + pytest.importorskip("pyarrow") + expr = ibis.date("2024-02-03") expr1 = expr.truncate("D") - result = con.to_pyarrow(expr1) - assert result is not None + assert con.to_pyarrow(expr1) == con.to_pyarrow(expr) diff --git a/ibis/backends/sql/compilers/clickhouse.py b/ibis/backends/sql/compilers/clickhouse.py index 46201bfff8f49..d80917df0d39d 100644 --- a/ibis/backends/sql/compilers/clickhouse.py +++ b/ibis/backends/sql/compilers/clickhouse.py @@ -383,15 +383,21 @@ def visit_TimestampTruncate(self, op, *, arg, unit): if short in ("s", "ms", "us", "ns"): arg = self.f.toDateTime64(arg, op.arg.dtype.scale or 0) - return self.f[func](arg) + return self.cast(self.f[func](arg), op.dtype) visit_TimeTruncate = visit_TimestampTruncate def visit_DateTruncate(self, op, *, arg, unit): - if unit.short == "W": + if unit.short == "D": + # no op because truncating a date to a date has no effect + return arg + elif unit.short == "W": func = "toMonday" else: func = f"toStartOf{unit.singular.capitalize()}" + + # no cast needed here because all of the allow units here return `Date` + # values return self.f[func](arg) def visit_TimestampBucket(self, op, *, arg, interval, offset):