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(..) method.
The issue affects all scenarios of map usage: top-level value, nested map-in-map, map-in-array, etc.
Steps to reproduce
- 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();
}
}
}
}
- Observe only one value per key returned.
- 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> T getObject(int columnIndex, Class<T> type) and Object getObject(int columnIndex, java.util.Map<String,Class<?>> 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
select map('key', 'X', 'key', 'Y');
Environment
ClickHouse Server
- ClickHouse Server version: 24.5.3.5
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 :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(..) method.
The issue affects all scenarios of map usage: top-level value, nested map-in-map, map-in-array, etc.
Steps to reproduce
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 thejava.sql.ResultSetimplementation (such overloads as<T> T getObject(int columnIndex, Class<T> type)andObject getObject(int columnIndex, java.util.Map<String,Class<?>> map)specifically, including their counterparts havingcolumnLabelinstead ofcolumnIndex):Consider changing the default behavior by the time of a certain upcoming major release.
Code Example
Environment
ClickHouse Server