Skip to content

Commit 1f83b42

Browse files
authored
Merge pull request #815 from zhicwu/fix-precison
Fix incorrect precision and scale from DatabaseMetaData.getColumns
2 parents fd3d923 + 671cd32 commit 1f83b42

File tree

22 files changed

+466
-110
lines changed

22 files changed

+466
-110
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Java 8 or higher is required in order to use Java client([clickhouse-client](htt
9999
<groupId>com.clickhouse</groupId>
100100
<!-- or clickhouse-grpc-client if you prefer gRPC -->
101101
<artifactId>clickhouse-http-client</artifactId>
102-
<version>0.3.2-patch2</version>
102+
<version>0.3.2-patch3</version>
103103
</dependency>
104104
```
105105

@@ -135,7 +135,7 @@ try (ClickHouseClient client = ClickHouseClient.newInstance(preferredProtocol);
135135
<!-- will stop using ru.yandex.clickhouse starting from 0.4.0 -->
136136
<groupId>com.clickhouse</groupId>
137137
<artifactId>clickhouse-jdbc</artifactId>
138-
<version>0.3.2-patch2</version>
138+
<version>0.3.2-patch3</version>
139139
<!-- below is only needed when all you want is a shaded jar -->
140140
<classifier>http</classifier>
141141
<exclusions>

clickhouse-client/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Async Java client for ClickHouse. `clickhouse-client` is an abstract module, so
99
<dependency>
1010
<groupId>com.clickhouse</groupId>
1111
<artifactId>clickhouse-http-client</artifactId>
12-
<version>0.3.2-patch1</version>
12+
<version>0.3.2-patch3</version>
1313
</dependency>
1414
```
1515

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseColumn.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public final class ClickHouseColumn implements Serializable {
4545
private static ClickHouseColumn update(ClickHouseColumn column) {
4646
column.enumConstants = ClickHouseEnum.EMPTY;
4747
int size = column.parameters.size();
48+
column.precision = column.dataType.getMaxPrecision();
4849
switch (column.dataType) {
4950
case Array:
5051
column.arrayLevel = 1;

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseDataType.java

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,15 @@ public enum ClickHouseDataType {
4444
UInt32(Long.class, false, true, false, 4, 10, 0, 0, 0, "INT UNSIGNED", "INTEGER UNSIGNED", "MEDIUMINT UNSIGNED"),
4545
UInt64(Long.class, false, true, false, 8, 20, 0, 0, 0, "BIGINT UNSIGNED"),
4646
UInt128(BigInteger.class, false, true, false, 16, 39, 0, 0, 0),
47-
UInt256(BigInteger.class, false, true, false, 32, 78, 0, 0, 0), Int8(Byte.class, false, true, true, 1, 3, 0, 0, 0,
48-
"BYTE", "INT1", "INT1 SIGNED", "TINYINT", "TINYINT SIGNED"),
47+
UInt256(BigInteger.class, false, true, false, 32, 78, 0, 0, 0),
48+
Int8(Byte.class, false, true, true, 1, 3, 0, 0, 0, "BYTE", "INT1", "INT1 SIGNED", "TINYINT", "TINYINT SIGNED"),
4949
Int16(Short.class, false, true, true, 2, 5, 0, 0, 0, "SMALLINT", "SMALLINT SIGNED"),
5050
Int32(Integer.class, false, true, true, 4, 10, 0, 0, 0, "INT", "INTEGER", "MEDIUMINT", "INT SIGNED",
5151
"INTEGER SIGNED", "MEDIUMINT SIGNED"),
5252
Int64(Long.class, false, true, true, 8, 19, 0, 0, 0, "BIGINT", "BIGINT SIGNED"),
5353
Int128(BigInteger.class, false, true, true, 16, 39, 0, 0, 0),
5454
Int256(BigInteger.class, false, true, true, 32, 77, 0, 0, 0),
55-
Bool(Boolean.class, false, false, true, 1, 3, 0, 0, 0, "BOOLEAN"),
55+
Bool(Boolean.class, false, false, true, 1, 1, 0, 0, 0, "BOOLEAN"),
5656
Date(LocalDate.class, false, false, false, 2, 10, 0, 0, 0),
5757
Date32(LocalDate.class, false, false, false, 4, 10, 0, 0, 0),
5858
DateTime(LocalDateTime.class, true, false, false, 0, 29, 0, 0, 9, "TIMESTAMP"),
@@ -63,22 +63,28 @@ public enum ClickHouseDataType {
6363
Decimal64(BigDecimal.class, true, false, true, 8, 18, 18, 0, 18),
6464
Decimal128(BigDecimal.class, true, false, true, 16, 38, 38, 0, 38),
6565
Decimal256(BigDecimal.class, true, false, true, 32, 76, 20, 0, 76),
66-
UUID(UUID.class, false, true, false, 16, 69, 0, 0, 0), Enum(String.class, true, true, false, 1, 0, 0, 0, 0),
67-
Enum8(String.class, true, true, false, 1, 0, 0, 0, 0), Enum16(String.class, true, true, false, 2, 0, 0, 0, 0),
66+
UUID(UUID.class, false, true, false, 16, 69, 0, 0, 0),
67+
@Deprecated
68+
Enum(String.class, true, true, false, 1, 0, 0, 0, 0),
69+
Enum8(String.class, true, true, false, 1, 0, 0, 0, 0), // "ENUM"),
70+
Enum16(String.class, true, true, false, 2, 0, 0, 0, 0),
6871
Float32(Float.class, false, true, true, 4, 12, 0, 0, 38, "FLOAT", "REAL", "SINGLE"),
6972
Float64(Double.class, false, true, true, 16, 22, 0, 0, 308, "DOUBLE", "DOUBLE PRECISION"),
70-
IPv4(Inet4Address.class, false, true, false, 4, 0, 0, 0, 0, "INET4"),
71-
IPv6(Inet6Address.class, false, true, false, 16, 0, 0, 0, 0, "INET6"),
73+
IPv4(Inet4Address.class, false, true, false, 4, 10, 0, 0, 0, "INET4"),
74+
IPv6(Inet6Address.class, false, true, false, 16, 39, 0, 0, 0, "INET6"),
7275
FixedString(String.class, true, true, false, 0, 0, 0, 0, 0, "BINARY"),
7376
String(String.class, false, true, false, 0, 0, 0, 0, 0, "BINARY LARGE OBJECT", "BINARY VARYING", "BLOB", "BYTEA",
74-
"CHAR", "CHAR LARGE OBJECT", "CHAR VARYING", "CHARACTER", "CHARACTER LARGE OBJECT", "CHARACTER VARYING",
75-
"CLOB", "LONGBLOB", "LONGTEXT", "MEDIUMBLOB", "MEDIUMTEXT", "NATIONAL CHAR", "NATIONAL CHAR VARYING",
76-
"NATIONAL CHARACTER", "NATIONAL CHARACTER LARGE OBJECT", "NATIONAL CHARACTER VARYING", "NCHAR",
77-
"NCHAR LARGE OBJECT", "NCHAR VARYING", "NVARCHAR", "TEXT", "TINYBLOB", "TINYTEXT", "VARCHAR", "VARCHAR2"),
77+
"CHAR", "CHARACTER", "CHARACTER LARGE OBJECT", "CHARACTER VARYING", "CHAR LARGE OBJECT", "CHAR VARYING",
78+
"CLOB", "LONGBLOB", "LONGTEXT", "MEDIUMBLOB", "MEDIUMTEXT", "NATIONAL CHAR", "NATIONAL CHARACTER",
79+
"NATIONAL CHARACTER LARGE OBJECT", "NATIONAL CHARACTER VARYING", "NATIONAL CHAR VARYING", "NCHAR",
80+
"NCHAR LARGE OBJECT", "NCHAR VARYING", "NVARCHAR", "TEXT", "TINYBLOB", "TINYTEXT", "VARBINARY", "VARCHAR",
81+
"VARCHAR2"),
7882
AggregateFunction(String.class, true, true, false, 0, 0, 0, 0, 0), // implementation-defined intermediate state
7983
SimpleAggregateFunction(String.class, true, true, false, 0, 0, 0, 0, 0),
80-
Array(Object.class, true, true, false, 0, 0, 0, 0, 0), Map(Map.class, true, true, false, 0, 0, 0, 0, 0),
81-
Nested(Object.class, true, true, false, 0, 0, 0, 0, 0), Tuple(List.class, true, true, false, 0, 0, 0, 0, 0),
84+
Array(Object.class, true, true, false, 0, 0, 0, 0, 0),
85+
Map(Map.class, true, true, false, 0, 0, 0, 0, 0),
86+
Nested(Object.class, true, true, false, 0, 0, 0, 0, 0),
87+
Tuple(List.class, true, true, false, 0, 0, 0, 0, 0),
8288
Point(Object.class, false, true, true, 33, 0, 0, 0, 0), // same as Tuple(Float64, Float64)
8389
Polygon(Object.class, false, true, true, 0, 0, 0, 0, 0), // same as Array(Ring)
8490
MultiPolygon(Object.class, false, true, true, 0, 0, 0, 0, 0), // same as Array(Polygon)

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseInputStream.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,6 @@ public byte[] readBytes(int length) throws IOException {
298298
ensureOpen();
299299

300300
byte[] bytes = new byte[length];
301-
int offset = 0;
302301
int counter = 0;
303302
while (counter < length) {
304303
if (position >= limit && updateBuffer() < 0) {
@@ -314,9 +313,8 @@ public byte[] readBytes(int length) throws IOException {
314313
}
315314

316315
int size = Math.min(limit - position, length - counter);
317-
System.arraycopy(buffer, position, bytes, offset, size);
316+
System.arraycopy(buffer, position, bytes, counter, size);
318317
position += size;
319-
offset += size;
320318
counter += size;
321319
}
322320

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseValue.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,55 @@ default <T, E extends Enum<E>> T asObject(Class<T> clazz) {
538538
}
539539
}
540540

541+
/**
542+
* Gets binary value as byte array.
543+
*
544+
* @return byte array which could be null
545+
*/
546+
default byte[] asBinary() {
547+
return asBinary(0, null);
548+
}
549+
550+
/**
551+
* Gets binary value as fixed length byte array.
552+
*
553+
* @param length byte length of value, 0 or negative number means no limit
554+
* @return byte array which could be null
555+
*/
556+
default byte[] asBinary(int length) {
557+
return asBinary(length, null);
558+
}
559+
560+
/**
561+
* Gets binary value as byte array.
562+
*
563+
* @param charset charset, null is same as default(UTF-8)
564+
* @return byte array which could be null
565+
*/
566+
default byte[] asBinary(Charset charset) {
567+
return asBinary(0, charset);
568+
}
569+
570+
/**
571+
* Gets binary value as byte array.
572+
*
573+
* @param length byte length of value, 0 or negative number means no limit
574+
* @param charset charset, null is same as default(UTF-8)
575+
* @return byte array which could be null
576+
*/
577+
default byte[] asBinary(int length, Charset charset) {
578+
if (isNullOrEmpty()) {
579+
return null;
580+
}
581+
582+
byte[] bytes = asString().getBytes(charset == null ? StandardCharsets.UTF_8 : charset);
583+
if (length > 0) {
584+
ClickHouseChecker.notWithDifferentLength(bytes, length);
585+
}
586+
587+
return bytes;
588+
}
589+
541590
/**
542591
* Gets value as unbounded string, using default charset(usually UTF-8).
543592
*

clickhouse-client/src/main/java/com/clickhouse/client/ClickHouseValues.java

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import java.net.Inet6Address;
99
import java.net.InetAddress;
1010
import java.net.UnknownHostException;
11+
import java.nio.charset.StandardCharsets;
1112
import java.time.Instant;
1213
import java.time.LocalDate;
1314
import java.time.LocalDateTime;
@@ -76,7 +77,9 @@ public final class ClickHouseValues {
7677
public static final long[] EMPTY_LONG_ARRAY = new long[0];
7778
public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
7879
public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
80+
7981
public static final String EMPTY_ARRAY_EXPR = "[]";
82+
public static final String EMPTY_STRING_EXPR = "''";
8083

8184
public static final BigDecimal NANOS = new BigDecimal(BigInteger.TEN.pow(9));
8285

@@ -134,6 +137,10 @@ public final class ClickHouseValues {
134137

135138
public static final String TYPE_CLASS = "Class";
136139

140+
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.US_ASCII);
141+
private static final byte[] UNHEX_PREFIX = "unhex('".getBytes(StandardCharsets.US_ASCII);
142+
private static final byte[] UNHEX_SUFFIX = "')".getBytes(StandardCharsets.US_ASCII);
143+
137144
/**
138145
* Converts IP address to big integer.
139146
*
@@ -180,6 +187,52 @@ public static BigInteger convertToBigInteger(UUID value) {
180187
return low.add(high.multiply(BIGINT_HL_BOUNDARY));
181188
}
182189

190+
/**
191+
* Converts given byte array to string in hexadecimal format.
192+
*
193+
* @param bytes byte array
194+
* @return non-null string
195+
*/
196+
public static String convertToHexString(byte[] bytes) {
197+
int len = bytes != null ? bytes.length : 0;
198+
if (len == 0) {
199+
return "";
200+
}
201+
202+
byte[] hexChars = new byte[len * 2];
203+
for (int i = 0; i < len; i++) {
204+
int v = bytes[i] & 0xFF;
205+
int j = i * 2;
206+
hexChars[j] = HEX_ARRAY[v >>> 4];
207+
hexChars[j + 1] = HEX_ARRAY[v & 0x0F];
208+
}
209+
return new String(hexChars, StandardCharsets.UTF_8);
210+
}
211+
212+
/**
213+
* Converts given byte array to unhex() expression.
214+
*
215+
* @param bytes byte array
216+
* @return non-null expression
217+
*/
218+
public static String convertToUnhexExpression(byte[] bytes) {
219+
int len = bytes != null ? bytes.length : 0;
220+
if (len == 0) {
221+
return EMPTY_STRING_EXPR;
222+
}
223+
224+
int offset = UNHEX_PREFIX.length;
225+
byte[] hexChars = new byte[len * 2 + offset + UNHEX_SUFFIX.length];
226+
System.arraycopy(UNHEX_PREFIX, 0, hexChars, 0, offset);
227+
System.arraycopy(UNHEX_SUFFIX, 0, hexChars, hexChars.length - UNHEX_SUFFIX.length, UNHEX_SUFFIX.length);
228+
for (int i = 0; i < len; i++) {
229+
int v = bytes[i] & 0xFF;
230+
hexChars[offset++] = HEX_ARRAY[v >>> 4];
231+
hexChars[offset++] = HEX_ARRAY[v & 0x0F];
232+
}
233+
return new String(hexChars, StandardCharsets.UTF_8);
234+
}
235+
183236
/**
184237
* Converts big decimal to instant.
185238
*

clickhouse-client/src/main/java/com/clickhouse/client/data/BinaryStreamUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,6 +1649,19 @@ public static void writeString(OutputStream output, String value, Charset charse
16491649
output.write(bytes);
16501650
}
16511651

1652+
/**
1653+
* Writes a binary string to given output stream.
1654+
*
1655+
* @param output non-null output stream
1656+
* @param value non-null byte array
1657+
* @throws IOException when failed to write value to output stream or reached
1658+
* end of the stream
1659+
*/
1660+
public static void writeString(OutputStream output, byte[] value) throws IOException {
1661+
writeVarInt(output, value.length);
1662+
output.write(value);
1663+
}
1664+
16521665
/**
16531666
* Read varint from given input stream.
16541667
*

clickhouse-client/src/main/java/com/clickhouse/client/data/ClickHouseRowBinaryProcessor.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -331,13 +331,11 @@ private void buildMappingsForDataTypes() {
331331

332332
// string and uuid
333333
buildMappings(deserializers, serializers,
334-
(r, f, c, i) -> ClickHouseStringValue.of(r, BinaryStreamUtils.readFixedString(i, c.getPrecision())),
335-
(v, f, c, o) -> BinaryStreamUtils.writeFixedString(o, v.asString(c.getPrecision()),
336-
c.getPrecision()),
337-
ClickHouseDataType.FixedString);
334+
(r, f, c, i) -> ClickHouseStringValue.of(r, i.readBytes(c.getPrecision())),
335+
(v, f, c, o) -> o.write(v.asBinary(c.getPrecision())), ClickHouseDataType.FixedString);
338336
buildMappings(deserializers, serializers,
339-
(r, f, c, i) -> ClickHouseStringValue.of(r, i.readUnicodeString()),
340-
(v, f, c, o) -> BinaryStreamUtils.writeString(o, v.asString()), ClickHouseDataType.String);
337+
(r, f, c, i) -> ClickHouseStringValue.of(r, i.readBytes(i.readVarInt())),
338+
(v, f, c, o) -> BinaryStreamUtils.writeString(o, v.asBinary()), ClickHouseDataType.String);
341339
buildMappings(deserializers, serializers,
342340
(r, f, c, i) -> ClickHouseUuidValue.of(r, BinaryStreamUtils.readUuid(i)),
343341
(v, f, c, o) -> BinaryStreamUtils.writeUuid(o, v.asUuid()), ClickHouseDataType.UUID);

0 commit comments

Comments
 (0)