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 03023c728..8342c6ba0 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 @@ -30,6 +30,8 @@ import java.math.BigInteger; import java.net.Inet4Address; import java.net.Inet6Address; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; @@ -199,6 +201,7 @@ protected boolean readRecord(Object[] record) throws IOException { return true; } + @SuppressWarnings("unchecked") @Override public T readValue(int colIndex) { if (colIndex < 1 || colIndex > getSchema().getColumns().size()) { @@ -207,6 +210,7 @@ public T readValue(int colIndex) { return (T) currentRecord[colIndex - 1]; } + @SuppressWarnings("unchecked") @Override public T readValue(String colName) { return (T) currentRecord[getSchema().nameToIndex(colName)]; @@ -357,68 +361,69 @@ public String getString(int index) { return dataTypeConverter.convertToString(value, column); } - private T readNumberValue(String colName, NumberConverter.NumberType targetType) { - int colIndex = schema.nameToIndex(colName); + @SuppressWarnings("unchecked") + private T readNumberValue(int index, NumberConverter.NumberType targetType) { + int colIndex = index - 1; Function converter = (Function) convertions[colIndex].get(targetType); if (converter != null) { - Object value = readValue(colName); + Object value = readValue(index); if (value == null) { if (targetType == NumberConverter.NumberType.BigInteger || targetType == NumberConverter.NumberType.BigDecimal) { return null; } - throw new NullValueException("Column " + colName + " has null value and it cannot be cast to " + + throw new NullValueException("Column at index " + index + " has null value and it cannot be cast to " + targetType.getTypeName()); } return (T) converter.apply(value); } else { - throw new ClientException("Column " + colName + " " + columns[colIndex].getDataType().name() + + throw new ClientException("Column at index " + index + " " + columns[colIndex].getDataType().name() + " cannot be converted to " + targetType.getTypeName()); } } @Override public byte getByte(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.Byte); + return getByte(schema.nameToColumnIndex(colName)); } @Override public short getShort(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.Short); + return getShort(schema.nameToColumnIndex(colName)); } @Override public int getInteger(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.Int); + return getInteger(schema.nameToColumnIndex(colName)); } @Override public long getLong(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.Long); + return getLong(schema.nameToColumnIndex(colName)); } @Override public float getFloat(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.Float); + return getFloat(schema.nameToColumnIndex(colName)); } @Override public double getDouble(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.Double); + return getDouble(schema.nameToColumnIndex(colName)); } @Override public boolean getBoolean(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.Boolean); + return getBoolean(schema.nameToColumnIndex(colName)); } @Override public BigInteger getBigInteger(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.BigInteger); + return getBigInteger(schema.nameToColumnIndex(colName)); } @Override public BigDecimal getBigDecimal(String colName) { - return readNumberValue(colName, NumberConverter.NumberType.BigDecimal); + return getBigDecimal(schema.nameToColumnIndex(colName)); } @Override @@ -433,76 +438,60 @@ public ZonedDateTime getZonedDateTime(String colName) { @Override public Duration getDuration(String colName) { - TemporalAmount temporalAmount = getTemporalAmount(colName); - return temporalAmount == null ? null : Duration.from(temporalAmount); + return getDuration(schema.nameToColumnIndex(colName)); } @Override public TemporalAmount getTemporalAmount(String colName) { - return readValue(colName); + return getTemporalAmount(schema.nameToColumnIndex(colName)); } @Override public Inet4Address getInet4Address(String colName) { - Object val = readValue(colName); - return val == null ? null : InetAddressConverter.convertToIpv4((java.net.InetAddress) val); + return getInet4Address(schema.nameToColumnIndex(colName)); } @Override public Inet6Address getInet6Address(String colName) { - Object val = readValue(colName); - return val == null ? null : InetAddressConverter.convertToIpv6((java.net.InetAddress) val); + return getInet6Address(schema.nameToColumnIndex(colName)); } @Override public UUID getUUID(String colName) { - return readValue(colName); + return getUUID(schema.nameToColumnIndex(colName)); } @Override public ClickHouseGeoPointValue getGeoPoint(String colName) { - Object val = readValue(colName); - return val == null ? null : ClickHouseGeoPointValue.of((double[]) val); + return getGeoPoint(schema.nameToColumnIndex(colName)); } @Override public ClickHouseGeoRingValue getGeoRing(String colName) { - Object val = readValue(colName); - return val == null ? null : ClickHouseGeoRingValue.of((double[][]) val); + return getGeoRing(schema.nameToColumnIndex(colName)); } @Override public ClickHouseGeoPolygonValue getGeoPolygon(String colName) { - Object val = readValue(colName); - return val == null ? null : ClickHouseGeoPolygonValue.of((double[][][]) val); + return getGeoPolygon(schema.nameToColumnIndex(colName)); } @Override public ClickHouseGeoMultiPolygonValue getGeoMultiPolygon(String colName) { - Object val = readValue(colName); - return val == null ? null : ClickHouseGeoMultiPolygonValue.of((double[][][][]) val); + return getGeoMultiPolygon(schema.nameToColumnIndex(colName)); } @Override public List getList(String colName) { - Object value = readValue(colName); - if (value == null) { - return null; - } - if (value instanceof BinaryStreamReader.ArrayValue) { - return ((BinaryStreamReader.ArrayValue) value).asList(); - } else if (value instanceof List) { - return (List) value; - } else { - throw new ClientException("Column is not of array type"); - } + return getList(schema.nameToColumnIndex(colName)); } - private T getPrimitiveArray(String colName, Class componentType) { + @SuppressWarnings("unchecked") + private T getPrimitiveArray(int index, Class componentType) { try { - Object value = readValue(colName); + Object value = readValue(index); if (value == null) { return null; } @@ -520,6 +509,10 @@ private T getPrimitiveArray(String colName, Class componentType) { Array.set(array, i, list.get(i)); } return (T)array; + } else if (value instanceof String) { + return (T) ((String)value).getBytes(StandardCharsets.UTF_8); + } else if (value instanceof InetAddress) { + return (T) ((InetAddress)value).getAddress(); } throw new ClientException("Column is not of array type"); } catch (ClassCastException e) { @@ -529,85 +522,42 @@ private T getPrimitiveArray(String colName, Class componentType) { @Override public byte[] getByteArray(String colName) { - try { - return getPrimitiveArray(colName, byte.class); - } catch (ClassCastException | IllegalArgumentException e) { - throw new ClientException("Value cannot be converted to an array of primitives", e); - } + return getByteArray(schema.nameToColumnIndex(colName)); } @Override public int[] getIntArray(String colName) { - try { - return getPrimitiveArray(colName, int.class); - } catch (ClassCastException | IllegalArgumentException e) { - throw new ClientException("Value cannot be converted to an array of primitives", e); - } + return getIntArray(schema.nameToColumnIndex(colName)); } @Override public long[] getLongArray(String colName) { - try { - return getPrimitiveArray(colName, long.class); - } catch (ClassCastException | IllegalArgumentException e) { - throw new ClientException("Value cannot be converted to an array of primitives", e); - } + return getLongArray(schema.nameToColumnIndex(colName)); } @Override public float[] getFloatArray(String colName) { - try { - return getPrimitiveArray(colName, float.class); - } catch (ClassCastException | IllegalArgumentException e) { - throw new ClientException("Value cannot be converted to an array of primitives", e); - } + return getFloatArray(schema.nameToColumnIndex(colName)); } @Override public double[] getDoubleArray(String colName) { - try { - return getPrimitiveArray(colName, double.class); - } catch (ClassCastException | IllegalArgumentException e) { - throw new ClientException("Value cannot be converted to an array of primitives", e); - } + return getDoubleArray(schema.nameToColumnIndex(colName)); } @Override public boolean[] getBooleanArray(String colName) { - try { - return getPrimitiveArray(colName, boolean.class); - } catch (ClassCastException | IllegalArgumentException e) { - throw new ClientException("Value cannot be converted to an array of primitives", e); - } + return getBooleanArray(schema.nameToColumnIndex(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); - } + return getShortArray(schema.nameToColumnIndex(colName)); } @Override public String[] getStringArray(String colName) { - Object value = readValue(colName); - if (value == null) { - return null; - } - 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."); + return getStringArray(schema.nameToColumnIndex(colName)); } @Override @@ -617,52 +567,52 @@ public boolean hasValue(int colIndex) { @Override public boolean hasValue(String colName) { - return currentRecord[getSchema().nameToIndex(colName)] != null; + return hasValue(schema.nameToColumnIndex(colName)); } @Override public byte getByte(int index) { - return getByte(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.Byte); } @Override public short getShort(int index) { - return getShort(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.Short); } @Override public int getInteger(int index) { - return getInteger(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.Int); } @Override public long getLong(int index) { - return getLong(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.Long); } @Override public float getFloat(int index) { - return getFloat(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.Float); } @Override public double getDouble(int index) { - return getDouble(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.Double); } @Override public boolean getBoolean(int index) { - return getBoolean(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.Boolean); } @Override public BigInteger getBigInteger(int index) { - return getBigInteger(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.BigInteger); } @Override public BigDecimal getBigDecimal(int index) { - return getBigDecimal(schema.columnIndexToName(index)); + return readNumberValue(index, NumberConverter.NumberType.BigDecimal); } @Override @@ -728,12 +678,13 @@ public ZonedDateTime getZonedDateTime(int index) { @Override public Duration getDuration(int index) { - return getDuration(schema.columnIndexToName(index)); + TemporalAmount temporalAmount = getTemporalAmount(index); + return temporalAmount == null ? null : Duration.from(temporalAmount); } @Override public TemporalAmount getTemporalAmount(int index) { - return getTemporalAmount(schema.columnIndexToName(index)); + return readValue(index); } @Override @@ -755,67 +706,124 @@ public UUID getUUID(int index) { @Override public ClickHouseGeoPointValue getGeoPoint(int index) { - return getGeoPoint(schema.columnIndexToName(index)); + Object val = readValue(index); + return val == null ? null : ClickHouseGeoPointValue.of((double[]) val); } @Override public ClickHouseGeoRingValue getGeoRing(int index) { - return getGeoRing(schema.columnIndexToName(index)); + Object val = readValue(index); + return val == null ? null : ClickHouseGeoRingValue.of((double[][]) val); } @Override public ClickHouseGeoPolygonValue getGeoPolygon(int index) { - return getGeoPolygon(schema.columnIndexToName(index)); + Object val = readValue(index); + return val == null ? null : ClickHouseGeoPolygonValue.of((double[][][]) val); } @Override public ClickHouseGeoMultiPolygonValue getGeoMultiPolygon(int index) { - return getGeoMultiPolygon(schema.columnIndexToName(index)); + Object val = readValue(index); + return val == null ? null : ClickHouseGeoMultiPolygonValue.of((double[][][][]) val); } @Override public List getList(int index) { - return getList(schema.columnIndexToName(index)); + Object value = readValue(index); + if (value == null) { + return null; + } + if (value instanceof BinaryStreamReader.ArrayValue) { + return ((BinaryStreamReader.ArrayValue) value).asList(); + } else if (value instanceof List) { + return (List) value; + } else { + throw new ClientException("Column is not of array type"); + } } @Override public byte[] getByteArray(int index) { - return getByteArray(schema.columnIndexToName(index)); + try { + return getPrimitiveArray(index, byte.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } } @Override public int[] getIntArray(int index) { - return getIntArray(schema.columnIndexToName(index)); + try { + return getPrimitiveArray(index, int.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } } @Override public long[] getLongArray(int index) { - return getLongArray(schema.columnIndexToName(index)); + try { + return getPrimitiveArray(index, long.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } } @Override public float[] getFloatArray(int index) { - return getFloatArray(schema.columnIndexToName(index)); + try { + return getPrimitiveArray(index, float.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } } @Override public double[] getDoubleArray(int index) { - return getDoubleArray(schema.columnIndexToName(index)); + try { + return getPrimitiveArray(index, double.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } } @Override public boolean[] getBooleanArray(int index) { - return getBooleanArray(schema.columnIndexToName(index)); + try { + return getPrimitiveArray(index, boolean.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } } @Override public short[] getShortArray(int index) { - return getShortArray(schema.columnIndexToName(index)); + try { + return getPrimitiveArray(index, short.class); + } catch (ClassCastException | IllegalArgumentException e) { + throw new ClientException("Value cannot be converted to an array of primitives", e); + } } @Override public String[] getStringArray(int index) { - return getStringArray(schema.columnIndexToName(index)); + Object value = readValue(index); + if (value == null) { + return null; + } + 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 @@ -825,35 +833,35 @@ public Object[] getTuple(int index) { @Override public Object[] getTuple(String colName) { - return readValue(colName); + return getTuple(schema.nameToColumnIndex(colName)); } @Override public byte getEnum8(String colName) { - BinaryStreamReader.EnumValue enumValue = readValue(colName); - if (enumValue == null) { - throw new NullValueException("Column " + colName + " has null value and it cannot be cast to byte"); - } - return enumValue.byteValue(); + return getEnum8(schema.nameToColumnIndex(colName)); } @Override public byte getEnum8(int index) { - return getEnum8(schema.columnIndexToName(index)); + BinaryStreamReader.EnumValue enumValue = readValue(index); + if (enumValue == null) { + throw new NullValueException("Column at index " + index + " has null value and it cannot be cast to byte"); + } + return enumValue.byteValue(); } @Override public short getEnum16(String colName) { - BinaryStreamReader.EnumValue enumValue = readValue(colName); - if (enumValue == null) { - throw new NullValueException("Column " + colName + " has null value and it cannot be cast to short"); - } - return enumValue.shortValue(); + return getEnum16(schema.nameToColumnIndex(colName)); } @Override public short getEnum16(int index) { - return getEnum16(schema.columnIndexToName(index)); + BinaryStreamReader.EnumValue enumValue = readValue(index); + if (enumValue == null) { + throw new NullValueException("Column at index " + index + " has null value and it cannot be cast to short"); + } + return enumValue.shortValue(); } @Override @@ -1004,7 +1012,7 @@ public OffsetDateTime getOffsetDateTime(int index) { @Override public ClickHouseBitmap getClickHouseBitmap(String colName) { - return readValue(colName); + return getClickHouseBitmap(schema.nameToColumnIndex(colName)); } @Override diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java index 96e8566f7..0055bad84 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java @@ -798,6 +798,8 @@ private String encodeObject(Object x, Long length) throws SQLException { return "fromUnixTimestamp64Nano(" + (((Instant) x).getEpochSecond() * 1_000_000_000L + ((Instant) x).getNano()) + ")"; } else if (x instanceof InetAddress) { return QUOTE + ((InetAddress) x).getHostAddress() + QUOTE; + } else if (x instanceof byte[]) { + return JdbcUtils.convertToUnhexExpression((byte[]) x); } else if (x instanceof java.sql.Array) { com.clickhouse.jdbc.types.Array array = (com.clickhouse.jdbc.types.Array) x; int nestedLevel = Math.max(1, array.getNestedLevel()); diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java index 3c2a6cc09..20844431b 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java @@ -227,7 +227,18 @@ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException @Override public byte[] getBytes(int columnIndex) throws SQLException { - return getBytes(columnIndexToName(columnIndex)); + checkClosed(); + try { + if (reader.hasValue(columnIndex)) { + wasNull = false; + return reader.getByteArray(columnIndex); + } else { + wasNull = true; + return null; + } + } catch (Exception e) { + throw ExceptionUtils.toSqlState(String.format("Method: getBytes(\"%s\") encountered an exception.", columnIndex), String.format("SQL: [%s]", parentStatement.getLastStatementSql()), e); + } } @Override @@ -406,18 +417,7 @@ public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLExcepti @Override public byte[] getBytes(String columnLabel) throws SQLException { - checkClosed(); - try { - if (reader.hasValue(columnLabel)) { - wasNull = false; - return reader.getByteArray(columnLabel); - } else { - wasNull = true; - return null; - } - } catch (Exception e) { - throw ExceptionUtils.toSqlState(String.format("Method: getBytes(\"%s\") encountered an exception.", columnLabel), String.format("SQL: [%s]", parentStatement.getLastStatementSql()), e); - } + return getBytes(getSchema().nameToColumnIndex(columnLabel)); } @Override diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java index 57a074684..51d613b60 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java @@ -13,6 +13,7 @@ import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; +import java.nio.charset.StandardCharsets; import java.sql.Date; import java.sql.JDBCType; import java.sql.SQLException; @@ -569,4 +570,38 @@ public static Object[] arrayToObjectArray(Object array) { } throw new IllegalArgumentException("Cannot convert " + array.getClass().getName() + " to an Object[]"); } + + public static final String EMPTY_ARRAY_EXPR = "[]"; + public static final String EMPTY_MAP_EXPR = "{}"; + public static final String EMPTY_STRING_EXPR = "''"; + public static final String EMPTY_TUPLE_EXPR = "()"; + + private static final byte[] UNHEX_PREFIX = "unhex('".getBytes(StandardCharsets.US_ASCII); + private static final byte[] UNHEX_SUFFIX = "')".getBytes(StandardCharsets.US_ASCII); + private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII); + + + /** + * Converts given byte array to unhex() expression. + * + * @param bytes byte array + * @return non-null expression + */ + public static String convertToUnhexExpression(byte[] bytes) { + int len = bytes != null ? bytes.length : 0; + if (len == 0) { + return EMPTY_STRING_EXPR; + } + + int offset = UNHEX_PREFIX.length; + byte[] hexChars = new byte[len * 2 + offset + UNHEX_SUFFIX.length]; + System.arraycopy(UNHEX_PREFIX, 0, hexChars, 0, offset); + System.arraycopy(UNHEX_SUFFIX, 0, hexChars, hexChars.length - UNHEX_SUFFIX.length, UNHEX_SUFFIX.length); + for (int i = 0; i < len; i++) { + int v = bytes[i] & 0xFF; + hexChars[offset++] = HEX_ARRAY[v >>> 4]; + hexChars[offset++] = HEX_ARRAY[v & 0x0F]; + } + return new String(hexChars, StandardCharsets.UTF_8); + } } diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java index e3784f17a..3425da6f9 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcDataTypeTests.java @@ -878,6 +878,9 @@ public void testIpAddressTypes() throws SQLException, UnknownHostException { assertEquals(rs.getString("ipv6"), ipv6Address.getHostAddress()); assertEquals(rs.getObject("ipv4_as_ipv6"), ipv4AsIpv6); assertEquals(rs.getObject("ipv4_as_ipv6", Inet4Address.class), ipv4AsIpv6); + assertEquals(rs.getBytes("ipv4_ip"), ipv4AddressByIp.getAddress()); + assertEquals(rs.getBytes("ipv6"), ipv6Address.getAddress()); + assertFalse(rs.next()); } } @@ -1175,6 +1178,34 @@ public void testArrayTypes() throws SQLException { } } + @Test(groups = { "integration" }) + public void testStringsUsedAsBytes() throws Exception { + runQuery("CREATE TABLE test_strings_as_bytes (order Int8, str String, fixed FixedString(10)) ENGINE = MergeTree ORDER BY ()"); + + String[][] testData = {{"Hello, World!", "FixedStr"}, {"Test String 123", "ABC"}}; + + try (Connection conn = getJdbcConnection(); + PreparedStatement insert = conn.prepareStatement("INSERT INTO test_strings_as_bytes VALUES (?, ?, ?)")) { + for (int i = 0; i < testData.length; i++) { + insert.setInt(1, i + 1); + insert.setBytes(2, testData[i][0].getBytes("UTF-8")); + insert.setBytes(3, testData[i][1].getBytes("UTF-8")); + insert.executeUpdate(); + } + } + + try (Connection conn = getJdbcConnection(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT * FROM test_strings_as_bytes ORDER BY order")) { + for (String[] expected : testData) { + assertTrue(rs.next()); + assertEquals(new String(rs.getBytes("str"), "UTF-8"), expected[0]); + assertEquals(new String(rs.getBytes("fixed"), "UTF-8").replace("\0", ""), expected[1]); + } + assertFalse(rs.next()); + } + } + @Test(groups = { "integration" }) public void testNestedArrays() throws Exception { try (Connection conn = getJdbcConnection()) { diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java index 2a28f8e67..0aabc98fd 100644 --- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java @@ -177,8 +177,11 @@ public void testSetString() throws Exception { @Test(groups = { "integration" }) public void testSetBytes() throws Exception { + // see com.clickhouse.jdbc.JdbcDataTypeTests.testStringsUsedAsBytes + // setBytes is dedicated for binary strings (see spec). + // arrays are set via Array object. try (Connection conn = getJdbcConnection()) { - try (PreparedStatement stmt = conn.prepareStatement("SELECT ?::Array(Int8)")) { + try (PreparedStatement stmt = conn.prepareStatement("SELECT ?")) { stmt.setBytes(1, new byte[] { 1, 2, 3 }); try (ResultSet rs = stmt.executeQuery()) { assertTrue(rs.next());