Skip to content

Commit

Permalink
feat(clickhouse): add support for .sql methods
Browse files Browse the repository at this point in the history
  • Loading branch information
cpcloud committed Sep 29, 2023
1 parent 59b6e37 commit f1d004b
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
26 changes: 26 additions & 0 deletions ibis/backends/clickhouse/__init__.py
@@ -1,6 +1,7 @@
from __future__ import annotations

import ast
import atexit
import glob
import json
from contextlib import closing, suppress
Expand Down Expand Up @@ -167,6 +168,7 @@ def do_connect(
compress=compression,
**kwargs,
)
self._temp_views = set()

@property
def version(self) -> str:
Expand Down Expand Up @@ -733,3 +735,27 @@ def _load_into_cache(self, name, expr):

def _clean_up_cached_table(self, op):
self.drop_table(op.name)

def _create_temp_view(self, table_name, source):
if table_name not in self._temp_views and table_name in self.list_tables():
raise ValueError(
f"{table_name} already exists as a non-temporary table or view"
)
src = sg.exp.Create(
this=sg.table(table_name), # CREATE ... 'table_name'
kind="VIEW", # VIEW
replace=True, # OR REPLACE
expression=source, # AS ...
)
self.raw_sql(src.sql(dialect=self.name, pretty=True))
self._temp_views.add(table_name)
self._register_temp_view_cleanup(table_name)

def _register_temp_view_cleanup(self, name: str) -> None:
def drop(self, name: str, query: str):
self.raw_sql(query)
self._temp_views.discard(name)

src = sg.exp.Drop(this=sg.table(name), kind="VIEW", exists=True)
query = src.sql(self.name, pretty=True)
atexit.register(drop, self, name=name, query=query)
9 changes: 9 additions & 0 deletions ibis/backends/clickhouse/compiler/relations.py
Expand Up @@ -231,3 +231,12 @@ def _dropna(op: ops.DropNa, *, table, how, subset, **_):
def _sql_string_view(op: ops.SQLStringView, query: str, **_: Any):
table = sg.table(op.name)
return sg.select(STAR).from_(table).with_(table, as_=query, dialect="clickhouse")


@translate_rel.register
def _view(op: ops.View, *, child, name: str, **_):
# TODO: find a way to do this without creating a temporary view
backend = op.child.to_expr()._find_backend()
source = sg.select(STAR).from_(child)
backend._create_temp_view(table_name=name, source=source)
return sg.table(name)
9 changes: 3 additions & 6 deletions ibis/backends/tests/test_dot_sql.py
Expand Up @@ -14,9 +14,7 @@
except ImportError:
PolarsComputeError = None

table_dot_sql_notimpl = pytest.mark.notimpl(
["bigquery", "clickhouse", "impala", "druid"]
)
table_dot_sql_notimpl = pytest.mark.notimpl(["bigquery", "impala", "druid"])
dot_sql_notimpl = pytest.mark.notimpl(["datafusion"])
dot_sql_notyet = pytest.mark.notyet(
["snowflake", "oracle"],
Expand Down Expand Up @@ -151,11 +149,11 @@ def test_table_dot_sql_with_join(backend, con):
"""
SELECT
l.fancy_af AS yas,
r.s
r.s AS s
FROM awesome_t AS l
LEFT JOIN ft AS r
ON l.s = r.s
"""
""" # clickhouse needs the r.s AS s, otherwise the column name is returned as r.s
)
.order_by(["s", "yas"])
)
Expand Down Expand Up @@ -250,7 +248,6 @@ def test_dot_sql_reuse_alias_with_different_types(backend, alltypes, df):
*no_sqlglot_dialect,
],
)
@pytest.mark.broken(["clickhouse"], raises=DatabaseError)
@pytest.mark.notyet(["polars"], raises=PolarsComputeError)
@table_dot_sql_notimpl
@dot_sql_notimpl
Expand Down

0 comments on commit f1d004b

Please sign in to comment.