ClickHouse / ClickHouse/clickhouse-java
Map(K, V) type support issue
- 主要语言
- Java
- 星标
- 1.6k
- 派生
- 636
- 平均合并
- 2 天 23 小时
- 30 天内合并 PR
- 29
描述
## Description
In Clickhouse `Map(K, V)` is not a collection of unique-by-key pairs, see https://clickhouse.com/docs/sql-reference/data-types/map :
> i.e. a map can contain two elements with the same key
But there is no way to obtain any representation other than a Map<,> of unique entries.
All the key-value pairs are being delivered by the underlying protocol, but they are effectively merged while reading an instance of a map in the corresponding [readMap(..)](https://github.com/ClickHouse/clickhouse-java/blob/601ade16364d667b71a4982bbabf60ed2d941dc1/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryStreamReader.java#L969) method.
The issue affects all scenarios of map usage: top-level value, nested map-in-map, map-in-array, etc.
### Steps to reproduce
1. Execute minimal reproduction program:
```
public class Program {
public static void main(String[] args) throws SQLException {
String queryText = "select map('key', 'X', 'key', 'Y')";
try (
Connection cnn = DriverManager.getConnection("jdbc:clickhouse://localhost:11049/default", "default", "");
PreparedStatement stmt = cnn.prepareStatement(queryText);
ResultSet rs = stmt.executeQuery()
) {
if (rs.next()) {
System.out.println(rs.getObject(1)); // gives {key=Y}
} else {
throw new IllegalStateException();
}
}
}
}
```
2. Observe only one value per key returned.
3. Any attempt to get other value representations than what `getObject()` does gives the same or results in an exception being thrown.
### Expected Behavior
Supporting existing behavior by default, it is expected to be able to use type hints to affect the actual return value of the `getObject(..)` method of the `java.sql.ResultSet` implementation (such overloads as ` T getObject(int columnIndex, Class type)` and `Object getObject(int columnIndex, java.util.Map> map)` specifically, including their counterparts having `columnLabel` instead of `columnIndex`):
```
public class Program {
public static void main(String[] args) throws SQLException {
String queryText = "select map('key', 'X', 'key', 'Y')";
try (
Connection cnn = DriverManager.getConnection("jdbc:clickhouse://localhost:11049/default", "default", "");
PreparedStatement stmt = cnn.prepareStatement(queryText);
ResultSet rs = stmt.executeQuery()
) {
if (rs.next()) {
System.out.println(rs.getObject(1)); // gives {key=Y} by default
System.out.println(rs.getObject(1, List.class)); // to give [key=X, key=Y] only for top level
System.out.println(rs.getObject(1, Map.of("Map", List.class))); // to give [key=X, key=Y] same as above including nested values
} else {
throw new IllegalStateException();
}
}
}
}
```
Consider changing the default behavior by the time of a certain upcoming major release.
### Code Example
```sql
select map('key', 'X', 'key', 'Y');
```
#### Environment
* [ ] Cloud
* Client version: 0.10.0-rc2
* Language version: 21
* OS: Windows 11
#### ClickHouse Server
* ClickHouse Server version: 24.5.3.5
贡献指南
调研方向
从 client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryStreamReader.java 中的 readMap(..) 开始,然后跟踪 issue 中提到的 JDBC ResultSet getObject 重载。重现包含重复键的查询,并检查顶层 map、嵌套 map 以及数组中包含的 map 是如何读取的。完成的标准是默认行为保持兼容,同时请求的类型提示能在每个所述场景中保留重复的键值条目。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- java
- 领域
- api, database
- Issue 类型
- 缺陷
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 活跃
- 描述清晰度
- 基本清楚
- 新手友好度
- 48/100