diff --git a/ibis/backends/clickhouse/compiler.py b/ibis/backends/clickhouse/compiler.py index 3d2eac14d0a2..1dc32322c9d6 100644 --- a/ibis/backends/clickhouse/compiler.py +++ b/ibis/backends/clickhouse/compiler.py @@ -712,18 +712,25 @@ def visit_TableUnnest( def _cleanup_names(self, exprs: Mapping[str, sge.Expression]): """Compose `_gen_valid_name` and `_dedup_name` to clean up names in projections. - ClickHouse has a bug where this fails semantic validation, assuming `s` - has a column called `x`: + ClickHouse has a bug where this fails semantic validation: ```sql - SELECT t.x - FROM (SELECT * FROM s) t + SELECT + "o"."a" + FROM ( + SELECT + "w"."a" + FROM "{name}" AS "s" + INNER JOIN "{name}" AS "w" + USING ("a") + ) AS "o" ``` - so we need to add a redundant aliasing operation to columns + Adding a redundant aliasing operation here (`"w"."a" AS "a"`) helps + ClickHouse. Not entirely clear whether this is an upstream bug. """ - quoted = self.quoted - for name, value in exprs.items(): - name = self._gen_valid_name(name) - yield value.as_(name, quoted=quoted, copy=False) + return ( + value.as_(self._gen_valid_name(name), quoted=quoted, copy=False) + for name, value in exprs.items() + ) diff --git a/ibis/backends/clickhouse/tests/test_client.py b/ibis/backends/clickhouse/tests/test_client.py index a6863d26538a..98e28299bbcf 100644 --- a/ibis/backends/clickhouse/tests/test_client.py +++ b/ibis/backends/clickhouse/tests/test_client.py @@ -351,7 +351,7 @@ def test_create_table_no_syntax_error(con): def test_password_with_bracket(): - password = f'{os.environ.get("IBIS_TEST_CLICKHOUSE_PASSWORD", "")}[' + password = f'{os.environ.get("IBIS_TEST_CLICKHOUSE_PASSWORD", "")}[]' quoted_pass = quote_plus(password) host = os.environ.get("IBIS_TEST_CLICKHOUSE_HOST", "localhost") user = os.environ.get("IBIS_TEST_CLICKHOUSE_USER", "default") @@ -365,25 +365,26 @@ def test_password_with_bracket(): def test_subquery_with_join(con): name = gen_name("clickhouse_tmp_table") - con.create_table(name, ibis.memtable({"a": [1]}), temp=True) + s = con.create_table(name, pa.Table.from_pydict({"a": [1, 2, 3]}), temp=True) sql = f""" - WITH "t12" AS ( - SELECT - "a" - FROM "{name}" - ) SELECT - "t26"."a" + "o"."a" FROM ( SELECT - "t23"."a" - FROM "t12" AS "t22" - INNER JOIN "t12" AS "t23" + "w"."a" + FROM "{name}" AS "s" + INNER JOIN "{name}" AS "w" USING ("a") - ) AS "t26" + ) AS "o" """ with pytest.raises( - ClickHouseDatabaseError, match="Identifier 't26.a' cannot be resolved" + ClickHouseDatabaseError, match="Identifier 'o.a' cannot be resolved" ): con.sql(sql) + + # this works because we add the additional alias in the inner query + w = s.view() + expr = s.join(w, "a").select(a=w.a).select(b=lambda t: t.a + 1) + result = expr.to_pandas() + assert set(result["b"].tolist()) == {2, 3, 4}