ClickHouse / ClickHouse/ClickHouse
`evaluateScalarSubqueryIfNeeded` called too late, missing tuple-rewrite edge case
- Dominant language
- C++
- Stars
- 49.9k
- Forks
- 9k
- Avg merge
- 21h 32m
- Merged PRs (30d)
- 515
Description
_Found via ClickGap automated review. Please close or comment if this is incorrect or needs adjustment._
_Retrospective finding from a historical scan of [PR #66655](https://github.com/ClickHouse/ClickHouse/pull/66655) (merged 2024-07-19). Confirmed on current codebase — close with a note if already fixed._
### Describe what's wrong
Query `SELECT (SELECT 1) IN tuple(x, 2) FROM t` throws `UNSUPPORTED_METHOD: Method getResultType is supported only for correlated query node` instead of returning correct results (1, 0 for x=1,2)
**Root cause:** resolveFunction.cpp:959-967: The scalar subquery evaluation fix is placed AFTER the tuple handling code (lines 916-937) which calls convertTupleToArray. When second argument is a non-constant tuple (e.g., tuple(x, 2)) and first argument is a scalar subquery, the tuple rewriting code is reached before the fix can evaluate the subquery.
**Why we believe this is a bug:** resolveFunction.cpp:935 → convertTupleToArray(tuple_args, in_first_argument, scope) → line 242: arg_types.push_back(in_first_argument->getResultType()) throws for non-correlated QueryNode. The fix at lines 959-967 is placed AFTER this code path.
**Affected locations:**
- `src/Analyzer/Resolve/resolveFunction.cpp:959` — evaluateScalarSubqueryIfNeeded fix location - should be moved earlier
- `src/Analyzer/Resolve/resolveFunction.cpp:935` — convertTupleToArray call that fails for scalar subquery first arg
- `src/Analyzer/Resolve/resolveFunction.cpp:242` — getResultType() call in convertTupleToArray that throws
**Impact:** Users cannot use scalar subqueries in the first argument of IN when the second argument is a non-constant tuple. Query fails with UNSUPPORTED_METHOD error instead of returning correct results.
### Does it reproduce on most recent release?
Yes — confirmed on current `master` (commit `c2f4d729254`).
### How to reproduce
```sql
DROP TABLE IF EXISTS test_scalar_subquery_in_tuple;
CREATE TABLE test_scalar_subquery_in_tuple (x Int32) ENGINE = Memory;
INSERT INTO test_scalar_subquery_in_tuple VALUES (1), (2);
-- This should work: scalar subquery in first arg, non-constant tuple in second arg
SELECT (SELECT 1) IN tuple(x, 2) FROM test_scalar_subquery_in_tuple ORDER BY x;
-- Verify NOT IN also works
SELECT (SELECT 1) NOT IN tuple(x, 2) FROM test_scalar_subquery_in_tuple ORDER BY x;
DROP TABLE test_scalar_subquery_in_tuple;
```
[Try it on ClickHouse Fiddle](https://fiddle.clickhouse.com/c531764b-98f4-45f9-9431-e54ebc8094f7)
### Expected behavior
```
1
0
0
1
```
### Error message and/or stacktrace
```
Received exception from server:
Code: 1. DB::Exception: Method getResultType is supported only for correlated query node. (UNSUPPORTED_METHOD)
```
### Additional context
**Suggested fix:** Move the fix (lines 959-967) to right after line 815 (after `in_first_argument` and `in_second_argument` are defined, and after the correlated subquery check), before any code that might call getResultType() on the first argument. This ensures scalar subqueries are evaluated before tuple-to-array rewriting.
**Analysis details:** Confidence HIGH | Severity P2 | Testability: `STATELESS_SQL`
Found during automated review of [PR #66655](https://github.com/ClickHouse/ClickHouse/pull/66655).
---
_ClickGapAI · Confidence: HIGH · Severity: P2 · Finding: `h_pr66655_001`_
Contributor guide
Assessment
This issue has not been assessed yet.