clickhouse-java icon indicating copy to clipboard operation
clickhouse-java copied to clipboard

[jdbc-v2] embedded Array value not converted to List

Open gfunc opened this issue 8 months ago • 0 comments

Describe your feedback

ATM, it seems jdbc-v2 cannot properly convert the embedded array value returned from the getObject function to java.sql.array types.

For example, if a query fetching data type Map(String, Array(Int8)), the value returned from jdbc driver would be of Java type LinkedHashMap<String, BinaryStreamReader$ArrayValue>. Because the BinaryStreamReader does not have type hint information to handle convertArray, it would return the original ArrayValue type instead.

Perhaps we could:

  1. Return array as java.util.List by default (like map)
  2. Modify AbstractBinaryFormatReader and BinaryStreamReader, and pass the composite ClickHouseDataType to BinaryStreamReader readValue

Code example

    @Test(groups = { "integration" })
    public void testCompositeTypes() throws SQLException {
        runQuery("CREATE TABLE test_composite (order Int8, "
                + "map Map(String, Array(Int8)),"
                + "tuple Tuple(Array(Int8), Map(String, String))"
                + ") ENGINE = MergeTree ORDER BY ()");

        Map<String, List> map = Map.of("mk1", Arrays.asList(11,12,13),
                "mk2", Arrays.asList(21,22,23),
                "mk3", Arrays.asList(31,32,33));
        Tuple tuple = new Tuple(Arrays.asList(1,2,3),
                Map.of("k1","v1","k2","v2","k3","v3"));

        try (Connection conn = getConnection()) {
            try (PreparedStatement stmt = conn.prepareStatement("INSERT INTO test_composite VALUES ( 1, ?, ? )")) {
                stmt.setObject(1, map);
                stmt.setObject(2, tuple);
                stmt.executeUpdate();
            }
        }

        // Check the results
        try (Connection conn = getConnection()) {
            try (Statement stmt = conn.createStatement()) {
                try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_composite ORDER BY order")) {
                    assertTrue(rs.next());
                    Map<Object, Object> mapResult = (Map<Object, Object>) rs.getObject("map");
                    assertEquals(mapResult.size(), 3);
                    for (String key: map.keySet()) {
                        assertEquals(mapResult.get(key), map.get(key));
                    }

                    Object[] tupleResult = (Object[]) rs.getObject("tuple");
                    assertEquals(tupleResult[0], tuple.getValue(0));
                    assertEquals(tupleResult[1], tuple.getValue(1));
                }
            }
        }
    }

gfunc avatar Apr 25 '25 09:04 gfunc