From ff9aeafdb82f35edcf62a0d1c3d69843dc0d4f8f Mon Sep 17 00:00:00 2001 From: mzitnik Date: Tue, 30 Sep 2025 19:03:47 +0300 Subject: [PATCH 1/2] Added getShortArray & getStringArray implementation --- .../ClickHouseBinaryFormatReader.java | 18 +++++++ .../internal/AbstractBinaryFormatReader.java | 30 +++++++++++ .../internal/BinaryReaderBackedRecord.java | 20 ++++++++ .../internal/MapBackedRecord.java | 20 ++++++++ .../client/api/query/GenericRecord.java | 8 +++ .../ClickHouseBinaryFormatReaderTest.java | 51 +++++++++++++++++++ 6 files changed, 147 insertions(+) diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReader.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReader.java index e6a9c2557..7d475e9a1 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReader.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReader.java @@ -293,6 +293,20 @@ public interface ClickHouseBinaryFormatReader extends AutoCloseable { */ boolean[] getBooleanArray(String colName); + /** + * + * @param colName + * @return + */ + short[] getShortArray(String colName); + + /** + * + * @param colName + * @return + */ + String[] getStringArray(String colName); + /** * Reads column with name `colName` as a string. * @@ -517,6 +531,10 @@ public interface ClickHouseBinaryFormatReader extends AutoCloseable { boolean[] getBooleanArray(int index); + short [] getShortArray(int index); + + String[] getStringArray(int index); + Object[] getTuple(int index); Object[] getTuple(String colName); diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java index d393d8503..61fef923b 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java @@ -629,6 +629,26 @@ public boolean[] getBooleanArray(String colName) { } } + @Override + public short[] getShortArray(String colName) { + try { + return getPrimitiveArray(colName, short.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } + } + + @Override + public String[] getStringArray(String colName) { + try { + List l = getList(colName); + String [] a = l.toArray(new String[0]); + return l.toArray(new String[l.size()]); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } + } + @Override public boolean hasValue(int colIndex) { return currentRecord[colIndex - 1] != null; @@ -774,6 +794,16 @@ public boolean[] getBooleanArray(int index) { return getBooleanArray(schema.columnIndexToName(index)); } + @Override + public short[] getShortArray(int index) { + return getShortArray(schema.columnIndexToName(index)); + } + + @Override + public String[] getStringArray(int index) { + return getStringArray(schema.columnIndexToName(index)); + } + @Override public Object[] getTuple(int index) { return readValue(index); diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryReaderBackedRecord.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryReaderBackedRecord.java index 4e6a9ce12..8b534b4fd 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryReaderBackedRecord.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/BinaryReaderBackedRecord.java @@ -165,6 +165,16 @@ public boolean[] getBooleanArray(String colName) { return reader.getBooleanArray(colName); } + @Override + public short[] getShortArray(String colName) { + return reader.getShortArray(colName); + } + + @Override + public String[] getStringArray(String colName) { + return reader.getStringArray(colName); + } + @Override public String getString(int index) { return reader.getString(index); @@ -315,6 +325,16 @@ public boolean[] getBooleanArray(int index) { return reader.getBooleanArray(index); } + @Override + public short[] getShortArray(int index) { + return reader.getShortArray(index); + } + + @Override + public String[] getStringArray(int index) { + return reader.getStringArray(index); + } + @Override public Object[] getTuple(int index) { return reader.getTuple(index); diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java index 23bb5cd07..06d1cfe7b 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/MapBackedRecord.java @@ -262,6 +262,16 @@ public boolean[] getBooleanArray(String colName) { return getPrimitiveArray(colName); } + @Override + public short[] getShortArray(String colName) { + return getPrimitiveArray(colName); + } + + @Override + public String[] getStringArray(String colName) { + return getPrimitiveArray(colName); + } + @Override public boolean hasValue(int colIndex) { return hasValue(schema.columnIndexToName(colIndex)); @@ -407,6 +417,16 @@ public boolean[] getBooleanArray(int index) { return getPrimitiveArray(schema.columnIndexToName(index)); } + @Override + public short[] getShortArray(int index) { + return getPrimitiveArray(schema.columnIndexToName(index)); + } + + @Override + public String[] getStringArray(int index) { + return getPrimitiveArray(schema.columnIndexToName(index)); + } + @Override public Object[] getTuple(int index) { return readValue(index); diff --git a/client-v2/src/main/java/com/clickhouse/client/api/query/GenericRecord.java b/client-v2/src/main/java/com/clickhouse/client/api/query/GenericRecord.java index 4fe4c4106..9f43ea24d 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/query/GenericRecord.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/query/GenericRecord.java @@ -246,6 +246,10 @@ public interface GenericRecord { boolean[] getBooleanArray(String colName); + short[] getShortArray(String colName); + + String[] getStringArray(String colName); + /** * Reads column with name `colName` as a string. * @@ -482,6 +486,10 @@ public interface GenericRecord { boolean[] getBooleanArray(int index); + short[] getShortArray(int index); + + String[] getStringArray(int index); + Object[] getTuple(int index); Object[] getTuple(String colName); diff --git a/client-v2/src/test/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReaderTest.java b/client-v2/src/test/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReaderTest.java index df87d0325..f6206a3a4 100644 --- a/client-v2/src/test/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReaderTest.java +++ b/client-v2/src/test/java/com/clickhouse/client/api/data_formats/ClickHouseBinaryFormatReaderTest.java @@ -195,4 +195,55 @@ public void testReadingAsBoolean() throws Exception { Assert.assertEquals(reader.getString("a"), "true"); Assert.assertEquals(reader.getString("b"), "false"); } + + @Test + public void testReadingArrays() throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + String[] names = new String[]{ "a1", "a2", "a3", "a4", "a5"}; + String[] types = new String[]{"Array(Int8)", "Array(String)", "Array(Int16)", "Array(Int32)", "Array(Int64)"}; + + BinaryStreamUtils.writeVarInt(out, names.length); + for (String name : names) { + BinaryStreamUtils.writeString(out, name); + } + for (String type : types) { + BinaryStreamUtils.writeString(out, type); + } + + // write data + BinaryStreamUtils.writeVarInt(out, 2); + BinaryStreamUtils.writeInt8(out, (byte) 1); + BinaryStreamUtils.writeInt8(out, (byte) 2); + + BinaryStreamUtils.writeVarInt(out, 2); + BinaryStreamUtils.writeString(out, "a"); + BinaryStreamUtils.writeString(out, "b"); + + BinaryStreamUtils.writeVarInt(out, 2); + BinaryStreamUtils.writeInt16(out, (short) 1); + BinaryStreamUtils.writeInt16(out, (short) 2); + + BinaryStreamUtils.writeVarInt(out, 2); + BinaryStreamUtils.writeInt32(out, (int) 1); + BinaryStreamUtils.writeInt32(out, (int) 2); + + BinaryStreamUtils.writeVarInt(out, 2); + BinaryStreamUtils.writeInt64(out, (long) 1); + BinaryStreamUtils.writeInt64(out, (long) 2); + + + InputStream in = new ByteArrayInputStream(out.toByteArray()); + QuerySettings querySettings = new QuerySettings().setUseTimeZone(TimeZone.getTimeZone("UTC").toZoneId().getId()); + RowBinaryWithNamesAndTypesFormatReader reader = + new RowBinaryWithNamesAndTypesFormatReader(in, querySettings, new BinaryStreamReader.CachingByteBufferAllocator()); + + reader.next(); + + Assert.assertEquals(reader.getByteArray("a1"), new byte[] {(byte) 1, (byte) 2}); + Assert.assertEquals(reader.getStringArray("a2"), new String[] {"a", "b"}); + Assert.assertEquals(reader.getShortArray("a3"), new short[] {(short) 1, (short) 2}); + Assert.assertEquals(reader.getIntArray("a4"), new int[] {1, 2}); + Assert.assertEquals(reader.getLongArray("a5"), new long[] {1L, 2L}); + + } } \ No newline at end of file From 60ffe9c82053cc9f950c533ad83381c5d845a018 Mon Sep 17 00:00:00 2001 From: mzitnik Date: Fri, 3 Oct 2025 09:41:12 +0300 Subject: [PATCH 2/2] Change read String Array implementation. --- .../internal/AbstractBinaryFormatReader.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java index 61fef923b..e55503bcc 100644 --- a/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java +++ b/client-v2/src/main/java/com/clickhouse/client/api/data_formats/internal/AbstractBinaryFormatReader.java @@ -640,13 +640,19 @@ public short[] getShortArray(String colName) { @Override public String[] getStringArray(String colName) { - try { - List l = getList(colName); - String [] a = l.toArray(new String[0]); - return l.toArray(new String[l.size()]); - } catch (ClassCastException | IllegalArgumentException e) { - throw new ClientException("Value cannot be converted to an array of primitives", e); + Object value = readValue(colName); + if (value instanceof BinaryStreamReader.ArrayValue) { + BinaryStreamReader.ArrayValue array = (BinaryStreamReader.ArrayValue) value; + int length = array.length; + if (!array.itemType.equals(String.class)) + throw new ClientException("Not A String type."); + String [] values = new String[length]; + for (int i = 0; i < length; i++) { + values[i] = (String)((BinaryStreamReader.ArrayValue) value).get(i); + } + return values; } + throw new ClientException("Not ArrayValue type."); } @Override