ClickHouse / ClickHouse/clickhouse-java

Map(K, V) type support issue

未关闭
#3,047 1 条评论 2 个 reaction 已指派 0 人 在 GitHub 查看
bug
主要语言
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

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。