Skip to content

Commit

Permalink
fix(snowflake): use convert_timezone for timezone conversion instea…
Browse files Browse the repository at this point in the history
…d of invalid postgres `AT TIME ZONE` syntax
  • Loading branch information
cpcloud committed May 24, 2023
1 parent b9aed44 commit 1595e7b
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
23 changes: 23 additions & 0 deletions ibis/backends/snowflake/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
from ibis.backends.base.sql.alchemy.registry import (
fixed_arity,
geospatial_functions,
get_col,
get_sqla_table,
reduction,
unary,
)
Expand Down Expand Up @@ -66,6 +68,26 @@ def _literal(t, op):
return _postgres_literal(t, op)


def _table_column(t, op):
ctx = t.context
table = op.table

sa_table = get_sqla_table(ctx, table)
out_expr = get_col(sa_table, op)

if (dtype := op.output_dtype).is_timestamp() and (
timezone := dtype.timezone
) is not None:
out_expr = sa.func.convert_timezone(timezone, out_expr).label(op.name)

# If the column does not originate from the table set in the current SELECT
# context, we should format as a subquery
if t.permit_subquery and ctx.is_foreign_expr(table):
return sa.select(out_expr)

return out_expr


def _string_find(t, op):
args = [t.translate(op.substr), t.translate(op.arg)]
if (start := op.start) is not None:
Expand Down Expand Up @@ -407,6 +429,7 @@ def _regex_extract(t, op):
ops.Hash: unary(sa.func.hash),
ops.ApproxMedian: reduction(lambda x: sa.func.approx_percentile(x, 0.5)),
ops.Median: reduction(sa.func.median),
ops.TableColumn: _table_column,
}
)

Expand Down
10 changes: 10 additions & 0 deletions ibis/backends/snowflake/tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,13 @@ def test_repeated_memtable_registration(simple_con, mocker):

# assert that we called _register_in_memory_table exactly n times
assert spy.call_count == n


def test_timestamp_tz_column(simple_con):
t = simple_con.create_table(
ibis.util.gen_name("snowflake_timestamp_tz_column"),
schema=ibis.schema({"ts": "string"}),
temp=True,
).mutate(ts=lambda t: t.ts.to_timestamp("YYYY-MM-DD HH24-MI-SS"))
expr = t.ts
assert expr.execute().empty

0 comments on commit 1595e7b

Please sign in to comment.