ClickHouse / ClickHouse/ClickHouse

Parameterized views: columns qualified by the view name and unaliased JOIN operands rejected (26.6 -> 26.8)

Open
#119,837 0 comments 0 reactions 1 assignee Claimed by @novikd View on GitHub
comp-query-analyzer replay-finding
Dominant language
C++
Stars
49.9k
Forks
9k
Avg merge
21h 32m
Merged PRs (30d)
515

Description

Caused by: https://github.com/ClickHouse/ClickHouse/pull/68978 (attribution by elimination, see below)

### Description

On 26.8, several valid queries against parameterized views invoked as table functions are rejected at analysis time. All of them succeed on 26.6. Three distinct surfaces reproduce, each on a different unrelated instance:

1. `Code 47 UNKNOWN_IDENTIFIER`: selecting a column qualified by the view's own name.
2. `Code 81 UNKNOWN_DATABASE`: qualifying a column in WHERE by the view's own name, so the analyzer reads the two-part identifier `v1.k1` as `database.table` and looks for a database named `v1`.
3. `Code 206 ALIAS_REQUIRED`: a parameterized view used as a JOIN operand without an explicit alias is treated as a subquery that requires one.

The common factor is that the implicit name of a parameterized-view table function no longer resolves as a table qualifier.

Regression between `26.6.1.2103` (OLD) and `26.8.1.189` (NEW). All three cases below were additionally re-run locally on `clickhouse-local 26.8.1.2745` with generated data only, and all three still fail there.

### How to reproduce

Case 1, `Code 47 UNKNOWN_IDENTIFIER`. The control query on the same view succeeds, which isolates the qualifier as the trigger:

```sql
CREATE DATABASE IF NOT EXISTS d1 ENGINE = Atomic;
CREATE VIEW d1.v1 AS SELECT {p1:String} AS k1, 'x' AS c1;

-- works on both versions
SELECT c1 FROM `d1.v1`(p1 = 'a') LIMIT 1;

-- 26.6 returns 'x', 26.8 raises Code 47
SELECT v1.c1 FROM `d1.v1`(p1 = 'a') LIMIT 1;
```

On 26.8 the second query gives:

```
Code: 47. DB::Exception: Unknown expression identifier `v1.c1` in scope SELECT v1.c1 FROM `d1.v1`(p1 = 'a') LIMIT 1. (UNKNOWN_IDENTIFIER)
```

Case 2, `Code 81 UNKNOWN_DATABASE`:

```sql
CREATE DATABASE IF NOT EXISTS d1 ENGINE = Atomic;
CREATE VIEW d1.v1 AS SELECT arrayJoin({p1:Array(Int64)}) AS k1, 'dev' AS c1;
SELECT c1 FROM `d1.v1`(p1 = [157]) WHERE (v1.k1 IN (157)) LIMIT 100;
```

On 26.8:

```
Code: 81. DB::Exception: Database v1 does not exist. Maybe you meant d1?. (UNKNOWN_DATABASE)
```

Case 3, `Code 206 ALIAS_REQUIRED`:

```sql
CREATE DATABASE IF NOT EXISTS d1 ENGINE = Atomic;
CREATE TABLE d1.t1 (c1 String, c2 Float64) ENGINE = ReplacingMergeTree ORDER BY c1;
INSERT INTO d1.t1 SELECT toString(number % 5), toFloat64(number) FROM numbers(20);
CREATE VIEW d1.v1 AS SELECT c1 AS k1, sum(c2) AS m1 FROM d1.t1 WHERE (length({p1:Array(String)}) = 0) OR (c1 IN ({p1:Array(String)})) GROUP BY c1;
SELECT d1.t1.c1, d1.v1.k1, d1.v1.m1 FROM d1.t1 FINAL INNER JOIN `d1.v1`(p1 = []) ON d1.t1.c1 = d1.v1.k1 ORDER BY m1 DESC LIMIT 200;
```

On 26.8:

```
Code: 206. DB::Exception: JOIN INNER JOIN ... ON d1.t1.c1 = d1.v1.k1 no alias for subquery or table function `d1.v1`(p1 = []). (ALIAS_REQUIRED)
```

### Expected behavior

Case 1 returns `x`. Case 2 returns rows, with `v1.k1` resolving to the parameterized view's column. Case 3 executes and returns rows (5 on the data above) rather than requiring an explicit alias or `joined_subquery_requires_alias=0`. All three behave that way on 26.6.1.2103.

### Cause evidence

This attribution is weaker than a single-commit bisect and is labelled accordingly.

Three instances independently narrowed to the same two-candidate boundary, `254a6f22a906` and `029866f0953b`. The boundary did not collapse further because the commit between them had no downloadable build. The remaining candidate `254a6f22a906` is excluded on content: its first-parent source diff is empty (CI and perf-comparison infrastructure only), so it cannot change SQL name resolution.

That leaves `029866f0953b`, the private sync merge of https://github.com/ClickHouse/ClickHouse/pull/68978 ("Parameterized views: Support DESCRIBE queries & scalar expressions in the analyzer"), whose subject matter matches the symptom directly. Its first-parent diff removes a synthesized `fake_` table name for parameterized views, which is plausibly the qualifier that used to make `v1.c1` resolve.

If a verified single-commit boundary is required, the missing build for the intermediate commit needs to be produced first.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.